blob: fd5a51ccb8e4b910961a2e7197fbdc0da782d10e [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
Gustavo Padovan8c520a52012-05-23 04:04:22 -030027#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020032#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030033#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030034#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Linus Torvalds1da177e2005-04-16 15:20:36 -070036/* Handle HCI Event packets */
37
Marcel Holtmanna9de9242007-10-20 13:33:56 +020038static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020040 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030042 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Andre Guedese6d465c2011-11-09 17:14:26 -030044 if (status) {
45 hci_dev_lock(hdev);
46 mgmt_stop_discovery_failed(hdev, status);
47 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020048 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Andre Guedes89352e72011-11-04 14:16:53 -030051 clear_bit(HCI_INQUIRY, &hdev->flags);
52
Johan Hedberg56e5cb82011-11-08 20:40:16 +020053 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020054 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020055 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010056
Johan Hedberg23bb5762010-12-21 23:01:27 +020057 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010058
Marcel Holtmanna9de9242007-10-20 13:33:56 +020059 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060}
61
Andre Guedes4d934832012-03-21 00:03:35 -030062static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
63{
64 __u8 status = *((__u8 *) skb->data);
65
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030066 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesae854a72012-03-21 00:03:36 -030067
68 if (status)
69 return;
70
71 set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
Andre Guedes4d934832012-03-21 00:03:35 -030072}
73
Marcel Holtmanna9de9242007-10-20 13:33:56 +020074static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020076 __u8 status = *((__u8 *) skb->data);
77
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030078 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020079
80 if (status)
81 return;
82
Andre Guedesae854a72012-03-21 00:03:36 -030083 clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
84
Marcel Holtmanna9de9242007-10-20 13:33:56 +020085 hci_conn_check_pending(hdev);
86}
87
Gustavo Padovan807deac2012-05-17 00:36:24 -030088static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
89 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +020090{
91 BT_DBG("%s", hdev->name);
92}
93
94static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
95{
96 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030099 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200101 if (rp->status)
102 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200104 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200106 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
107 if (conn) {
108 if (rp->role)
109 conn->link_mode &= ~HCI_LM_MASTER;
110 else
111 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200113
114 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200117static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
118{
119 struct hci_rp_read_link_policy *rp = (void *) skb->data;
120 struct hci_conn *conn;
121
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300122 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200123
124 if (rp->status)
125 return;
126
127 hci_dev_lock(hdev);
128
129 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
130 if (conn)
131 conn->link_policy = __le16_to_cpu(rp->policy);
132
133 hci_dev_unlock(hdev);
134}
135
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200136static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200138 struct hci_rp_write_link_policy *rp = (void *) skb->data;
139 struct hci_conn *conn;
140 void *sent;
141
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300142 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200143
144 if (rp->status)
145 return;
146
147 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
148 if (!sent)
149 return;
150
151 hci_dev_lock(hdev);
152
153 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200154 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700155 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200156
157 hci_dev_unlock(hdev);
158}
159
Gustavo Padovan807deac2012-05-17 00:36:24 -0300160static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
161 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200162{
163 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
164
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300165 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200166
167 if (rp->status)
168 return;
169
170 hdev->link_policy = __le16_to_cpu(rp->policy);
171}
172
Gustavo Padovan807deac2012-05-17 00:36:24 -0300173static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
174 struct sk_buff *skb)
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200175{
176 __u8 status = *((__u8 *) skb->data);
177 void *sent;
178
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300179 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200180
181 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
182 if (!sent)
183 return;
184
185 if (!status)
186 hdev->link_policy = get_unaligned_le16(sent);
187
Johan Hedberg23bb5762010-12-21 23:01:27 +0200188 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200189}
190
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200191static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
192{
193 __u8 status = *((__u8 *) skb->data);
194
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300195 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200196
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300197 clear_bit(HCI_RESET, &hdev->flags);
198
Johan Hedberg23bb5762010-12-21 23:01:27 +0200199 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300200
Johan Hedberga297e972012-02-21 17:55:47 +0200201 /* Reset all non-persistent flags */
Andre Guedesae854a72012-03-21 00:03:36 -0300202 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
203 BIT(HCI_PERIODIC_INQ));
Andre Guedes69775ff2012-02-23 16:50:05 +0200204
205 hdev->discovery.state = DISCOVERY_STOPPED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200206}
207
208static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
209{
210 __u8 status = *((__u8 *) skb->data);
211 void *sent;
212
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300213 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200214
215 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
216 if (!sent)
217 return;
218
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200219 hci_dev_lock(hdev);
220
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200221 if (test_bit(HCI_MGMT, &hdev->dev_flags))
222 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200223 else if (!status)
224 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200225
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200226 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200227
228 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200229}
230
231static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
232{
233 struct hci_rp_read_local_name *rp = (void *) skb->data;
234
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300235 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200236
237 if (rp->status)
238 return;
239
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200240 if (test_bit(HCI_SETUP, &hdev->dev_flags))
241 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200242}
243
244static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
245{
246 __u8 status = *((__u8 *) skb->data);
247 void *sent;
248
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300249 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200250
251 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
252 if (!sent)
253 return;
254
255 if (!status) {
256 __u8 param = *((__u8 *) sent);
257
258 if (param == AUTH_ENABLED)
259 set_bit(HCI_AUTH, &hdev->flags);
260 else
261 clear_bit(HCI_AUTH, &hdev->flags);
262 }
263
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200264 if (test_bit(HCI_MGMT, &hdev->dev_flags))
265 mgmt_auth_enable_complete(hdev, status);
266
Johan Hedberg23bb5762010-12-21 23:01:27 +0200267 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200268}
269
270static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
271{
272 __u8 status = *((__u8 *) skb->data);
273 void *sent;
274
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300275 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200276
277 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
278 if (!sent)
279 return;
280
281 if (!status) {
282 __u8 param = *((__u8 *) sent);
283
284 if (param)
285 set_bit(HCI_ENCRYPT, &hdev->flags);
286 else
287 clear_bit(HCI_ENCRYPT, &hdev->flags);
288 }
289
Johan Hedberg23bb5762010-12-21 23:01:27 +0200290 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200291}
292
293static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
294{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200295 __u8 param, status = *((__u8 *) skb->data);
296 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200297 void *sent;
298
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300299 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200300
301 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
302 if (!sent)
303 return;
304
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200305 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200306
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200307 hci_dev_lock(hdev);
308
Mikel Astizfa1bd912012-08-09 09:52:29 +0200309 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200310 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200311 hdev->discov_timeout = 0;
312 goto done;
313 }
314
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200315 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
316 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200317
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200318 if (param & SCAN_INQUIRY) {
319 set_bit(HCI_ISCAN, &hdev->flags);
320 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200321 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200322 if (hdev->discov_timeout > 0) {
323 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
324 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300325 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200326 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200327 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200328 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200329
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200330 if (param & SCAN_PAGE) {
331 set_bit(HCI_PSCAN, &hdev->flags);
332 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200333 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200334 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200335 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200336
337done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200338 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200339 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200340}
341
342static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
343{
344 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
345
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300346 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200347
348 if (rp->status)
349 return;
350
351 memcpy(hdev->dev_class, rp->dev_class, 3);
352
353 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300354 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200355}
356
357static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
358{
359 __u8 status = *((__u8 *) skb->data);
360 void *sent;
361
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300362 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200363
364 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
365 if (!sent)
366 return;
367
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100368 hci_dev_lock(hdev);
369
370 if (status == 0)
371 memcpy(hdev->dev_class, sent, 3);
372
373 if (test_bit(HCI_MGMT, &hdev->dev_flags))
374 mgmt_set_class_of_dev_complete(hdev, sent, status);
375
376 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200377}
378
379static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
380{
381 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200383
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300384 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200385
386 if (rp->status)
387 return;
388
389 setting = __le16_to_cpu(rp->voice_setting);
390
Marcel Holtmannf383f272008-07-14 20:13:47 +0200391 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392 return;
393
394 hdev->voice_setting = setting;
395
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300396 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200397
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200398 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200399 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200400}
401
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300402static void hci_cc_write_voice_setting(struct hci_dev *hdev,
403 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200404{
405 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200406 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 void *sent;
408
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300409 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Marcel Holtmannf383f272008-07-14 20:13:47 +0200411 if (status)
412 return;
413
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200414 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
415 if (!sent)
416 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Marcel Holtmannf383f272008-07-14 20:13:47 +0200418 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Marcel Holtmannf383f272008-07-14 20:13:47 +0200420 if (hdev->voice_setting == setting)
421 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Marcel Holtmannf383f272008-07-14 20:13:47 +0200423 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300425 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200426
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200427 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200428 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200431static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200433 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300435 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Johan Hedberg23bb5762010-12-21 23:01:27 +0200437 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438}
439
Marcel Holtmann333140b2008-07-14 20:13:48 +0200440static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
441{
442 __u8 status = *((__u8 *) skb->data);
443 void *sent;
444
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300445 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200446
Marcel Holtmann333140b2008-07-14 20:13:48 +0200447 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
448 if (!sent)
449 return;
450
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200451 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200452 mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
453 else if (!status) {
454 if (*((u8 *) sent))
455 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
456 else
457 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
458 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200459}
460
Johan Hedbergd5859e22011-01-25 01:19:58 +0200461static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
462{
463 if (hdev->features[6] & LMP_EXT_INQ)
464 return 2;
465
466 if (hdev->features[3] & LMP_RSSI_INQ)
467 return 1;
468
469 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300470 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200471 return 1;
472
473 if (hdev->manufacturer == 15) {
474 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
475 return 1;
476 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
477 return 1;
478 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
479 return 1;
480 }
481
482 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300483 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200484 return 1;
485
486 return 0;
487}
488
489static void hci_setup_inquiry_mode(struct hci_dev *hdev)
490{
491 u8 mode;
492
493 mode = hci_get_inquiry_mode(hdev);
494
495 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
496}
497
498static void hci_setup_event_mask(struct hci_dev *hdev)
499{
500 /* The second byte is 0xff instead of 0x9f (two reserved bits
501 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
502 * command otherwise */
503 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
504
Ville Tervo6de6c182011-05-27 11:16:21 +0300505 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
506 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200507 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300508 return;
509
Johan Hedberge1171e82012-10-19 20:57:45 +0300510 if (lmp_bredr_capable(hdev)) {
511 events[4] |= 0x01; /* Flow Specification Complete */
512 events[4] |= 0x02; /* Inquiry Result with RSSI */
513 events[4] |= 0x04; /* Read Remote Extended Features Complete */
514 events[5] |= 0x08; /* Synchronous Connection Complete */
515 events[5] |= 0x10; /* Synchronous Connection Changed */
516 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200517
518 if (hdev->features[3] & LMP_RSSI_INQ)
Johan Hedberga24299e2012-04-26 09:47:46 +0300519 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200520
Andre Guedes999dcd12012-07-24 15:03:52 -0300521 if (lmp_sniffsubr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200522 events[5] |= 0x20; /* Sniff Subrating */
523
524 if (hdev->features[5] & LMP_PAUSE_ENC)
525 events[5] |= 0x80; /* Encryption Key Refresh Complete */
526
527 if (hdev->features[6] & LMP_EXT_INQ)
528 events[5] |= 0x40; /* Extended Inquiry Result */
529
Andre Guedesc58e8102012-07-24 15:03:53 -0300530 if (lmp_no_flush_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200531 events[7] |= 0x01; /* Enhanced Flush Complete */
532
533 if (hdev->features[7] & LMP_LSTO)
534 events[6] |= 0x80; /* Link Supervision Timeout Changed */
535
Andre Guedes9a1a1992012-07-24 15:03:48 -0300536 if (lmp_ssp_capable(hdev)) {
Johan Hedbergd5859e22011-01-25 01:19:58 +0200537 events[6] |= 0x01; /* IO Capability Request */
538 events[6] |= 0x02; /* IO Capability Response */
539 events[6] |= 0x04; /* User Confirmation Request */
540 events[6] |= 0x08; /* User Passkey Request */
541 events[6] |= 0x10; /* Remote OOB Data Request */
542 events[6] |= 0x20; /* Simple Pairing Complete */
543 events[7] |= 0x04; /* User Passkey Notification */
544 events[7] |= 0x08; /* Keypress Notification */
545 events[7] |= 0x10; /* Remote Host Supported
546 * Features Notification */
547 }
548
Andre Guedesc383ddc2012-07-24 15:03:47 -0300549 if (lmp_le_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200550 events[7] |= 0x20; /* LE Meta-Event */
551
552 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
Johan Hedberge36b04c2012-10-19 20:57:47 +0300553
554 if (lmp_le_capable(hdev)) {
555 memset(events, 0, sizeof(events));
556 events[0] = 0x1f;
557 hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
558 sizeof(events), events);
559 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200560}
561
Johan Hedberge1171e82012-10-19 20:57:45 +0300562static void bredr_init(struct hci_dev *hdev)
563{
564 struct hci_cp_delete_stored_link_key cp;
565 __le16 param;
566 __u8 flt_type;
567
568 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
569 hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
570
571 /* Read Class of Device */
572 hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
573
574 /* Read Local Name */
575 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
576
577 /* Read Voice Setting */
578 hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
579
580 /* Clear Event Filters */
581 flt_type = HCI_FLT_CLEAR_ALL;
582 hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
583
584 /* Connection accept timeout ~20 secs */
585 param = __constant_cpu_to_le16(0x7d00);
586 hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
587
588 bacpy(&cp.bdaddr, BDADDR_ANY);
589 cp.delete_all = 1;
590 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
591}
592
593static void le_init(struct hci_dev *hdev)
594{
595 /* Read LE Buffer Size */
596 hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
Johan Hedberg8fa19092012-10-19 20:57:49 +0300597
598 /* Read LE Advertising Channel TX Power */
599 hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
Johan Hedberge1171e82012-10-19 20:57:45 +0300600}
601
Johan Hedbergd5859e22011-01-25 01:19:58 +0200602static void hci_setup(struct hci_dev *hdev)
603{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200604 if (hdev->dev_type != HCI_BREDR)
605 return;
606
Johan Hedberge1171e82012-10-19 20:57:45 +0300607 /* Read BD Address */
608 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
609
610 if (lmp_bredr_capable(hdev))
611 bredr_init(hdev);
612
613 if (lmp_le_capable(hdev))
614 le_init(hdev);
615
Johan Hedbergd5859e22011-01-25 01:19:58 +0200616 hci_setup_event_mask(hdev);
617
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200618 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200619 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
620
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300621 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200622 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
623 u8 mode = 0x01;
624 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300625 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200626 } else {
627 struct hci_cp_write_eir cp;
628
629 memset(hdev->eir, 0, sizeof(hdev->eir));
630 memset(&cp, 0, sizeof(cp));
631
632 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
633 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200634 }
635
636 if (hdev->features[3] & LMP_RSSI_INQ)
637 hci_setup_inquiry_mode(hdev);
638
639 if (hdev->features[7] & LMP_INQ_TX_PWR)
640 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300641
642 if (hdev->features[7] & LMP_EXTFEATURES) {
643 struct hci_cp_read_local_ext_features cp;
644
645 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300646 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
647 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300648 }
Andre Guedese6100a22011-06-30 19:20:54 -0300649
Johan Hedberg47990ea2012-02-22 11:58:37 +0200650 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
651 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300652 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
653 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200654 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200655}
656
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200657static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
658{
659 struct hci_rp_read_local_version *rp = (void *) skb->data;
660
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300661 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200662
663 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200664 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200665
666 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200667 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200668 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200669 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200670 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200671
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300672 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300673 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200674
675 if (test_bit(HCI_INIT, &hdev->flags))
676 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200677
678done:
679 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200680}
681
682static void hci_setup_link_policy(struct hci_dev *hdev)
683{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200684 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200685 u16 link_policy = 0;
686
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300687 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200688 link_policy |= HCI_LP_RSWITCH;
689 if (hdev->features[0] & LMP_HOLD)
690 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300691 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200692 link_policy |= HCI_LP_SNIFF;
693 if (hdev->features[1] & LMP_PARK)
694 link_policy |= HCI_LP_PARK;
695
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200696 cp.policy = cpu_to_le16(link_policy);
697 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200698}
699
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300700static void hci_cc_read_local_commands(struct hci_dev *hdev,
701 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200702{
703 struct hci_rp_read_local_commands *rp = (void *) skb->data;
704
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300705 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200706
707 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200708 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200709
710 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200711
712 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
713 hci_setup_link_policy(hdev);
714
715done:
716 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200717}
718
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300719static void hci_cc_read_local_features(struct hci_dev *hdev,
720 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200721{
722 struct hci_rp_read_local_features *rp = (void *) skb->data;
723
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300724 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200725
726 if (rp->status)
727 return;
728
729 memcpy(hdev->features, rp->features, 8);
730
731 /* Adjust default settings according to features
732 * supported by device. */
733
734 if (hdev->features[0] & LMP_3SLOT)
735 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
736
737 if (hdev->features[0] & LMP_5SLOT)
738 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
739
740 if (hdev->features[1] & LMP_HV2) {
741 hdev->pkt_type |= (HCI_HV2);
742 hdev->esco_type |= (ESCO_HV2);
743 }
744
745 if (hdev->features[1] & LMP_HV3) {
746 hdev->pkt_type |= (HCI_HV3);
747 hdev->esco_type |= (ESCO_HV3);
748 }
749
Andre Guedes45db810f2012-07-24 15:03:49 -0300750 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200751 hdev->esco_type |= (ESCO_EV3);
752
753 if (hdev->features[4] & LMP_EV4)
754 hdev->esco_type |= (ESCO_EV4);
755
756 if (hdev->features[4] & LMP_EV5)
757 hdev->esco_type |= (ESCO_EV5);
758
Marcel Holtmannefc76882009-02-06 09:13:37 +0100759 if (hdev->features[5] & LMP_EDR_ESCO_2M)
760 hdev->esco_type |= (ESCO_2EV3);
761
762 if (hdev->features[5] & LMP_EDR_ESCO_3M)
763 hdev->esco_type |= (ESCO_3EV3);
764
765 if (hdev->features[5] & LMP_EDR_3S_ESCO)
766 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
767
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200768 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300769 hdev->features[0], hdev->features[1],
770 hdev->features[2], hdev->features[3],
771 hdev->features[4], hdev->features[5],
772 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200773}
774
Johan Hedberg8f984df2012-02-28 01:07:22 +0200775static void hci_set_le_support(struct hci_dev *hdev)
776{
777 struct hci_cp_write_le_host_supported cp;
778
779 memset(&cp, 0, sizeof(cp));
780
Marcel Holtmann9d428202012-05-03 07:12:31 +0200781 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200782 cp.le = 1;
783 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
784 }
785
786 if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300787 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
788 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200789}
790
Andre Guedes971e3a42011-06-30 19:20:52 -0300791static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300792 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300793{
794 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
795
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300796 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300797
798 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200799 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300800
Andre Guedesb5b32b62011-12-30 10:34:04 -0300801 switch (rp->page) {
802 case 0:
803 memcpy(hdev->features, rp->features, 8);
804 break;
805 case 1:
806 memcpy(hdev->host_features, rp->features, 8);
807 break;
808 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300809
Andre Guedesc383ddc2012-07-24 15:03:47 -0300810 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200811 hci_set_le_support(hdev);
812
813done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300814 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
815}
816
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200817static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300818 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200819{
820 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
821
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300822 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200823
824 if (rp->status)
825 return;
826
827 hdev->flow_ctl_mode = rp->mode;
828
829 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
830}
831
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200832static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
833{
834 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
835
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300836 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200837
838 if (rp->status)
839 return;
840
841 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
842 hdev->sco_mtu = rp->sco_mtu;
843 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
844 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
845
846 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
847 hdev->sco_mtu = 64;
848 hdev->sco_pkts = 8;
849 }
850
851 hdev->acl_cnt = hdev->acl_pkts;
852 hdev->sco_cnt = hdev->sco_pkts;
853
Gustavo Padovan807deac2012-05-17 00:36:24 -0300854 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
855 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200856}
857
858static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
859{
860 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
861
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300862 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200863
864 if (!rp->status)
865 bacpy(&hdev->bdaddr, &rp->bdaddr);
866
Johan Hedberg23bb5762010-12-21 23:01:27 +0200867 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
868}
869
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200870static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300871 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200872{
873 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
874
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300875 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200876
877 if (rp->status)
878 return;
879
880 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
881 hdev->block_len = __le16_to_cpu(rp->block_len);
882 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
883
884 hdev->block_cnt = hdev->num_blocks;
885
886 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300887 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200888
889 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
890}
891
Johan Hedberg23bb5762010-12-21 23:01:27 +0200892static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
893{
894 __u8 status = *((__u8 *) skb->data);
895
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300896 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200897
898 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200899}
900
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300901static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300902 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300903{
904 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
905
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300906 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300907
908 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300909 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300910
911 hdev->amp_status = rp->amp_status;
912 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
913 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
914 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
915 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
916 hdev->amp_type = rp->amp_type;
917 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
918 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
919 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
920 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
921
922 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300923
924a2mp_rsp:
925 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300926}
927
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300928static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
929 struct sk_buff *skb)
930{
931 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
932 struct amp_assoc *assoc = &hdev->loc_assoc;
933 size_t rem_len, frag_len;
934
935 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
936
937 if (rp->status)
938 goto a2mp_rsp;
939
940 frag_len = skb->len - sizeof(*rp);
941 rem_len = __le16_to_cpu(rp->rem_len);
942
943 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300944 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300945
946 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
947 assoc->offset += frag_len;
948
949 /* Read other fragments */
950 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
951
952 return;
953 }
954
955 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
956 assoc->len = assoc->offset + rem_len;
957 assoc->offset = 0;
958
959a2mp_rsp:
960 /* Send A2MP Rsp when all fragments are received */
961 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300962 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300963}
964
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200965static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300966 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200967{
968 __u8 status = *((__u8 *) skb->data);
969
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300970 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200971
972 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
973}
974
Johan Hedbergd5859e22011-01-25 01:19:58 +0200975static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
976{
977 __u8 status = *((__u8 *) skb->data);
978
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300979 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200980
981 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
982}
983
984static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300985 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200986{
987 __u8 status = *((__u8 *) skb->data);
988
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300989 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200990
991 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
992}
993
994static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300995 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200996{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700997 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200998
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300999 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001000
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001001 if (!rp->status)
1002 hdev->inq_tx_power = rp->tx_power;
1003
1004 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001005}
1006
1007static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1008{
1009 __u8 status = *((__u8 *) skb->data);
1010
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001011 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001012
1013 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1014}
1015
Johan Hedberg980e1a52011-01-22 06:10:07 +02001016static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1017{
1018 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1019 struct hci_cp_pin_code_reply *cp;
1020 struct hci_conn *conn;
1021
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001022 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001023
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001024 hci_dev_lock(hdev);
1025
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001026 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001027 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001028
Mikel Astizfa1bd912012-08-09 09:52:29 +02001029 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001030 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001031
1032 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1033 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001034 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001035
1036 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1037 if (conn)
1038 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001039
1040unlock:
1041 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001042}
1043
1044static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1045{
1046 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1047
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001048 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001049
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001050 hci_dev_lock(hdev);
1051
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001052 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001053 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001054 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001055
1056 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001057}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001058
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001059static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1060 struct sk_buff *skb)
1061{
1062 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1063
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001064 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001065
1066 if (rp->status)
1067 return;
1068
1069 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1070 hdev->le_pkts = rp->le_max_pkt;
1071
1072 hdev->le_cnt = hdev->le_pkts;
1073
1074 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1075
1076 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1077}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001078
Johan Hedberg8fa19092012-10-19 20:57:49 +03001079static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
1080 struct sk_buff *skb)
1081{
1082 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
1083
1084 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1085
1086 if (!rp->status)
1087 hdev->adv_tx_power = rp->tx_power;
1088
1089 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
1090}
1091
Johan Hedberge36b04c2012-10-19 20:57:47 +03001092static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1093{
1094 __u8 status = *((__u8 *) skb->data);
1095
1096 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1097
1098 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1099}
1100
Johan Hedberga5c29682011-02-19 12:05:57 -03001101static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1102{
1103 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1104
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001105 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001106
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001107 hci_dev_lock(hdev);
1108
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001109 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001110 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1111 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001112
1113 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001114}
1115
1116static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001117 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001118{
1119 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1120
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001121 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001122
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001123 hci_dev_lock(hdev);
1124
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001125 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001126 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001127 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001128
1129 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001130}
1131
Brian Gix1143d452011-11-23 08:28:34 -08001132static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1133{
1134 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1135
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001136 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001137
1138 hci_dev_lock(hdev);
1139
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001140 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001141 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001142 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001143
1144 hci_dev_unlock(hdev);
1145}
1146
1147static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001148 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001149{
1150 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1151
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001152 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001153
1154 hci_dev_lock(hdev);
1155
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001156 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001157 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001158 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001159
1160 hci_dev_unlock(hdev);
1161}
1162
Szymon Jancc35938b2011-03-22 13:12:21 +01001163static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001164 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001165{
1166 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1167
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001168 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001169
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001170 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001171 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001172 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001173 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001174}
1175
Andre Guedes07f7fa52011-12-02 21:13:31 +09001176static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1177{
1178 __u8 status = *((__u8 *) skb->data);
1179
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001180 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001181
1182 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001183
1184 if (status) {
1185 hci_dev_lock(hdev);
1186 mgmt_start_discovery_failed(hdev, status);
1187 hci_dev_unlock(hdev);
1188 return;
1189 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001190}
1191
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001192static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001193 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001194{
1195 struct hci_cp_le_set_scan_enable *cp;
1196 __u8 status = *((__u8 *) skb->data);
1197
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001198 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001199
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001200 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1201 if (!cp)
1202 return;
1203
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001204 switch (cp->enable) {
1205 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001206 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1207
Andre Guedes3fd24152012-02-03 17:48:01 -03001208 if (status) {
1209 hci_dev_lock(hdev);
1210 mgmt_start_discovery_failed(hdev, status);
1211 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001212 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001213 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001214
Andre Guedesd23264a2011-11-25 20:53:38 -03001215 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1216
Andre Guedesa8f13c82011-09-09 18:56:24 -03001217 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001218 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001219 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001220 break;
1221
1222 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001223 if (status) {
1224 hci_dev_lock(hdev);
1225 mgmt_stop_discovery_failed(hdev, status);
1226 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001227 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001228 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001229
Andre Guedesd23264a2011-11-25 20:53:38 -03001230 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1231
Andre Guedesbc3dd332012-03-06 19:37:06 -03001232 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1233 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001234 mgmt_interleaved_discovery(hdev);
1235 } else {
1236 hci_dev_lock(hdev);
1237 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1238 hci_dev_unlock(hdev);
1239 }
1240
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001241 break;
1242
1243 default:
1244 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1245 break;
Andre Guedes35815082011-05-26 16:23:53 -03001246 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001247}
1248
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001249static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1250{
1251 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1252
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001253 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001254
1255 if (rp->status)
1256 return;
1257
1258 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1259}
1260
1261static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1262{
1263 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1264
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001265 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001266
1267 if (rp->status)
1268 return;
1269
1270 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1271}
1272
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001273static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1274 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001275{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001276 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001277 __u8 status = *((__u8 *) skb->data);
1278
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001279 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001280
Johan Hedberg06199cf2012-02-22 16:37:11 +02001281 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001282 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001283 return;
1284
Johan Hedberg8f984df2012-02-28 01:07:22 +02001285 if (!status) {
1286 if (sent->le)
1287 hdev->host_features[0] |= LMP_HOST_LE;
1288 else
1289 hdev->host_features[0] &= ~LMP_HOST_LE;
1290 }
1291
1292 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001293 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001294 mgmt_le_enable_complete(hdev, sent->le, status);
1295
1296 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001297}
1298
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001299static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1300 struct sk_buff *skb)
1301{
1302 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1303
1304 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1305 hdev->name, rp->status, rp->phy_handle);
1306
1307 if (rp->status)
1308 return;
1309
1310 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1311}
1312
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001313static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001314{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001315 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001316
1317 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001318 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001319 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001320 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001321 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001322 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001323 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001324 return;
1325 }
1326
Andre Guedes89352e72011-11-04 14:16:53 -03001327 set_bit(HCI_INQUIRY, &hdev->flags);
1328
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001329 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001330 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001331 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001332}
1333
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001334static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001336 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001339 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001340
1341 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 if (!cp)
1343 return;
1344
1345 hci_dev_lock(hdev);
1346
1347 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1348
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001349 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
1351 if (status) {
1352 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001353 if (status != 0x0c || conn->attempt > 2) {
1354 conn->state = BT_CLOSED;
1355 hci_proto_connect_cfm(conn, status);
1356 hci_conn_del(conn);
1357 } else
1358 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 }
1360 } else {
1361 if (!conn) {
1362 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1363 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001364 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 conn->link_mode |= HCI_LM_MASTER;
1366 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001367 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 }
1369 }
1370
1371 hci_dev_unlock(hdev);
1372}
1373
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001374static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001376 struct hci_cp_add_sco *cp;
1377 struct hci_conn *acl, *sco;
1378 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001380 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001381
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001382 if (!status)
1383 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001385 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1386 if (!cp)
1387 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001389 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001391 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001392
1393 hci_dev_lock(hdev);
1394
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001395 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001396 if (acl) {
1397 sco = acl->link;
1398 if (sco) {
1399 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001400
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001401 hci_proto_connect_cfm(sco, status);
1402 hci_conn_del(sco);
1403 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001404 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001405
1406 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407}
1408
Marcel Holtmannf8558552008-07-14 20:13:49 +02001409static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1410{
1411 struct hci_cp_auth_requested *cp;
1412 struct hci_conn *conn;
1413
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001414 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001415
1416 if (!status)
1417 return;
1418
1419 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1420 if (!cp)
1421 return;
1422
1423 hci_dev_lock(hdev);
1424
1425 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1426 if (conn) {
1427 if (conn->state == BT_CONFIG) {
1428 hci_proto_connect_cfm(conn, status);
1429 hci_conn_put(conn);
1430 }
1431 }
1432
1433 hci_dev_unlock(hdev);
1434}
1435
1436static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1437{
1438 struct hci_cp_set_conn_encrypt *cp;
1439 struct hci_conn *conn;
1440
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001441 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001442
1443 if (!status)
1444 return;
1445
1446 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1447 if (!cp)
1448 return;
1449
1450 hci_dev_lock(hdev);
1451
1452 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1453 if (conn) {
1454 if (conn->state == BT_CONFIG) {
1455 hci_proto_connect_cfm(conn, status);
1456 hci_conn_put(conn);
1457 }
1458 }
1459
1460 hci_dev_unlock(hdev);
1461}
1462
Johan Hedberg127178d2010-11-18 22:22:29 +02001463static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001464 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001465{
Johan Hedberg392599b2010-11-18 22:22:28 +02001466 if (conn->state != BT_CONFIG || !conn->out)
1467 return 0;
1468
Johan Hedberg765c2a92011-01-19 12:06:52 +05301469 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001470 return 0;
1471
1472 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001473 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001474 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1475 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001476 return 0;
1477
Johan Hedberg392599b2010-11-18 22:22:28 +02001478 return 1;
1479}
1480
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001481static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001482 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001483{
1484 struct hci_cp_remote_name_req cp;
1485
1486 memset(&cp, 0, sizeof(cp));
1487
1488 bacpy(&cp.bdaddr, &e->data.bdaddr);
1489 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1490 cp.pscan_mode = e->data.pscan_mode;
1491 cp.clock_offset = e->data.clock_offset;
1492
1493 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1494}
1495
Johan Hedbergb644ba32012-01-17 21:48:47 +02001496static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001497{
1498 struct discovery_state *discov = &hdev->discovery;
1499 struct inquiry_entry *e;
1500
Johan Hedbergb644ba32012-01-17 21:48:47 +02001501 if (list_empty(&discov->resolve))
1502 return false;
1503
1504 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001505 if (!e)
1506 return false;
1507
Johan Hedbergb644ba32012-01-17 21:48:47 +02001508 if (hci_resolve_name(hdev, e) == 0) {
1509 e->name_state = NAME_PENDING;
1510 return true;
1511 }
1512
1513 return false;
1514}
1515
1516static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001517 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001518{
1519 struct discovery_state *discov = &hdev->discovery;
1520 struct inquiry_entry *e;
1521
1522 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001523 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1524 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001525
1526 if (discov->state == DISCOVERY_STOPPED)
1527 return;
1528
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001529 if (discov->state == DISCOVERY_STOPPING)
1530 goto discov_complete;
1531
1532 if (discov->state != DISCOVERY_RESOLVING)
1533 return;
1534
1535 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001536 /* If the device was not found in a list of found devices names of which
1537 * are pending. there is no need to continue resolving a next name as it
1538 * will be done upon receiving another Remote Name Request Complete
1539 * Event */
1540 if (!e)
1541 return;
1542
1543 list_del(&e->list);
1544 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001545 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001546 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1547 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001548 } else {
1549 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001550 }
1551
Johan Hedbergb644ba32012-01-17 21:48:47 +02001552 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001553 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001554
1555discov_complete:
1556 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1557}
1558
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001559static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1560{
Johan Hedberg127178d2010-11-18 22:22:29 +02001561 struct hci_cp_remote_name_req *cp;
1562 struct hci_conn *conn;
1563
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001564 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001565
1566 /* If successful wait for the name req complete event before
1567 * checking for the need to do authentication */
1568 if (!status)
1569 return;
1570
1571 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1572 if (!cp)
1573 return;
1574
1575 hci_dev_lock(hdev);
1576
1577 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001578
1579 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1580 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1581
Johan Hedberg79c6c702011-04-28 11:28:55 -07001582 if (!conn)
1583 goto unlock;
1584
1585 if (!hci_outgoing_auth_needed(hdev, conn))
1586 goto unlock;
1587
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001588 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001589 struct hci_cp_auth_requested cp;
1590 cp.handle = __cpu_to_le16(conn->handle);
1591 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1592 }
1593
Johan Hedberg79c6c702011-04-28 11:28:55 -07001594unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001595 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001596}
1597
Marcel Holtmann769be972008-07-14 20:13:49 +02001598static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1599{
1600 struct hci_cp_read_remote_features *cp;
1601 struct hci_conn *conn;
1602
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001603 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001604
1605 if (!status)
1606 return;
1607
1608 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1609 if (!cp)
1610 return;
1611
1612 hci_dev_lock(hdev);
1613
1614 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1615 if (conn) {
1616 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001617 hci_proto_connect_cfm(conn, status);
1618 hci_conn_put(conn);
1619 }
1620 }
1621
1622 hci_dev_unlock(hdev);
1623}
1624
1625static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1626{
1627 struct hci_cp_read_remote_ext_features *cp;
1628 struct hci_conn *conn;
1629
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001630 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001631
1632 if (!status)
1633 return;
1634
1635 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1636 if (!cp)
1637 return;
1638
1639 hci_dev_lock(hdev);
1640
1641 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1642 if (conn) {
1643 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001644 hci_proto_connect_cfm(conn, status);
1645 hci_conn_put(conn);
1646 }
1647 }
1648
1649 hci_dev_unlock(hdev);
1650}
1651
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001652static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1653{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001654 struct hci_cp_setup_sync_conn *cp;
1655 struct hci_conn *acl, *sco;
1656 __u16 handle;
1657
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001658 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001659
1660 if (!status)
1661 return;
1662
1663 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1664 if (!cp)
1665 return;
1666
1667 handle = __le16_to_cpu(cp->handle);
1668
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001669 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001670
1671 hci_dev_lock(hdev);
1672
1673 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001674 if (acl) {
1675 sco = acl->link;
1676 if (sco) {
1677 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001678
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001679 hci_proto_connect_cfm(sco, status);
1680 hci_conn_del(sco);
1681 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001682 }
1683
1684 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001685}
1686
1687static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1688{
1689 struct hci_cp_sniff_mode *cp;
1690 struct hci_conn *conn;
1691
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001692 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001693
1694 if (!status)
1695 return;
1696
1697 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1698 if (!cp)
1699 return;
1700
1701 hci_dev_lock(hdev);
1702
1703 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001704 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001705 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001706
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001707 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001708 hci_sco_setup(conn, status);
1709 }
1710
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001711 hci_dev_unlock(hdev);
1712}
1713
1714static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1715{
1716 struct hci_cp_exit_sniff_mode *cp;
1717 struct hci_conn *conn;
1718
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001719 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001720
1721 if (!status)
1722 return;
1723
1724 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1725 if (!cp)
1726 return;
1727
1728 hci_dev_lock(hdev);
1729
1730 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001731 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001732 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001733
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001734 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001735 hci_sco_setup(conn, status);
1736 }
1737
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001738 hci_dev_unlock(hdev);
1739}
1740
Johan Hedberg88c3df12012-02-09 14:27:38 +02001741static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1742{
1743 struct hci_cp_disconnect *cp;
1744 struct hci_conn *conn;
1745
1746 if (!status)
1747 return;
1748
1749 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1750 if (!cp)
1751 return;
1752
1753 hci_dev_lock(hdev);
1754
1755 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1756 if (conn)
1757 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001758 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001759
1760 hci_dev_unlock(hdev);
1761}
1762
Ville Tervofcd89c02011-02-10 22:38:47 -03001763static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1764{
Ville Tervofcd89c02011-02-10 22:38:47 -03001765 struct hci_conn *conn;
1766
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001767 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001768
Ville Tervofcd89c02011-02-10 22:38:47 -03001769 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001770 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001771
Andre Guedes0c95ab72012-07-27 15:10:14 -03001772 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001773 if (!conn) {
1774 hci_dev_unlock(hdev);
1775 return;
1776 }
1777
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001778 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001779
1780 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001781 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001782 conn->dst_type, status);
1783 hci_proto_connect_cfm(conn, status);
1784 hci_conn_del(conn);
1785
1786 hci_dev_unlock(hdev);
1787 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001788}
1789
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001790static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1791{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001792 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001793}
1794
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001795static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1796{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001797 struct hci_cp_create_phy_link *cp;
1798
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001799 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001800
1801 if (status)
1802 return;
1803
1804 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1805 if (!cp)
1806 return;
1807
1808 amp_write_remote_assoc(hdev, cp->phy_handle);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001809}
1810
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001811static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1812{
1813 struct hci_cp_accept_phy_link *cp;
1814
1815 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1816
1817 if (status)
1818 return;
1819
1820 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1821 if (!cp)
1822 return;
1823
1824 amp_write_remote_assoc(hdev, cp->phy_handle);
1825}
1826
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001827static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001828{
1829 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001830 struct discovery_state *discov = &hdev->discovery;
1831 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001832
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001833 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001834
Johan Hedberg23bb5762010-12-21 23:01:27 +02001835 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001836
1837 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001838
1839 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1840 return;
1841
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001842 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001843 return;
1844
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001845 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001846
Andre Guedes343f9352012-02-17 20:39:37 -03001847 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001848 goto unlock;
1849
1850 if (list_empty(&discov->resolve)) {
1851 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1852 goto unlock;
1853 }
1854
1855 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1856 if (e && hci_resolve_name(hdev, e) == 0) {
1857 e->name_state = NAME_PENDING;
1858 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1859 } else {
1860 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1861 }
1862
1863unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001864 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001865}
1866
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001867static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001869 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001870 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 int num_rsp = *((__u8 *) skb->data);
1872
1873 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1874
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001875 if (!num_rsp)
1876 return;
1877
Andre Guedes1519cc12012-03-21 00:03:38 -03001878 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1879 return;
1880
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001882
Johan Hedberge17acd42011-03-30 23:57:16 +03001883 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001884 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001885
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 bacpy(&data.bdaddr, &info->bdaddr);
1887 data.pscan_rep_mode = info->pscan_rep_mode;
1888 data.pscan_period_mode = info->pscan_period_mode;
1889 data.pscan_mode = info->pscan_mode;
1890 memcpy(data.dev_class, info->dev_class, 3);
1891 data.clock_offset = info->clock_offset;
1892 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001893 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001894
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001895 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001896 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001897 info->dev_class, 0, !name_known, ssp, NULL,
1898 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001900
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 hci_dev_unlock(hdev);
1902}
1903
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001904static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001906 struct hci_ev_conn_complete *ev = (void *) skb->data;
1907 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001909 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001910
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001912
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001913 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001914 if (!conn) {
1915 if (ev->link_type != SCO_LINK)
1916 goto unlock;
1917
1918 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1919 if (!conn)
1920 goto unlock;
1921
1922 conn->type = SCO_LINK;
1923 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001924
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001925 if (!ev->status) {
1926 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001927
1928 if (conn->type == ACL_LINK) {
1929 conn->state = BT_CONFIG;
1930 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001931
1932 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1933 !hci_find_link_key(hdev, &ev->bdaddr))
1934 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1935 else
1936 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001937 } else
1938 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001939
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001940 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001941 hci_conn_add_sysfs(conn);
1942
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001943 if (test_bit(HCI_AUTH, &hdev->flags))
1944 conn->link_mode |= HCI_LM_AUTH;
1945
1946 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1947 conn->link_mode |= HCI_LM_ENCRYPT;
1948
1949 /* Get remote features */
1950 if (conn->type == ACL_LINK) {
1951 struct hci_cp_read_remote_features cp;
1952 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001953 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001954 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001955 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001956
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001957 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001958 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001959 struct hci_cp_change_conn_ptype cp;
1960 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001961 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001962 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1963 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001964 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001965 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001966 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001967 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001968 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001969 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001970 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001971
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001972 if (conn->type == ACL_LINK)
1973 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001974
Marcel Holtmann769be972008-07-14 20:13:49 +02001975 if (ev->status) {
1976 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001977 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001978 } else if (ev->link_type != ACL_LINK)
1979 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001980
1981unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001983
1984 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985}
1986
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001987static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001989 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 int mask = hdev->link_mode;
1991
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001992 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001993 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
1995 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1996
Szymon Janc138d22e2011-02-17 16:44:23 +01001997 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001998 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002000 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
2003 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002004
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002005 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2006 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002007 memcpy(ie->data.dev_class, ev->dev_class, 3);
2008
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002009 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
2010 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002012 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2013 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03002014 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 hci_dev_unlock(hdev);
2016 return;
2017 }
2018 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002019
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 memcpy(conn->dev_class, ev->dev_class, 3);
2021 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002022
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 hci_dev_unlock(hdev);
2024
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002025 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2026 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002028 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002030 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2031 cp.role = 0x00; /* Become master */
2032 else
2033 cp.role = 0x01; /* Remain slave */
2034
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002035 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2036 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002037 } else {
2038 struct hci_cp_accept_sync_conn_req cp;
2039
2040 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002041 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002042
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002043 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2044 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2045 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002046 cp.content_format = cpu_to_le16(hdev->voice_setting);
2047 cp.retrans_effort = 0xff;
2048
2049 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002050 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 } else {
2053 /* Connection rejected */
2054 struct hci_cp_reject_conn_req cp;
2055
2056 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002057 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002058 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 }
2060}
2061
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002062static u8 hci_to_mgmt_reason(u8 err)
2063{
2064 switch (err) {
2065 case HCI_ERROR_CONNECTION_TIMEOUT:
2066 return MGMT_DEV_DISCONN_TIMEOUT;
2067 case HCI_ERROR_REMOTE_USER_TERM:
2068 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2069 case HCI_ERROR_REMOTE_POWER_OFF:
2070 return MGMT_DEV_DISCONN_REMOTE;
2071 case HCI_ERROR_LOCAL_HOST_TERM:
2072 return MGMT_DEV_DISCONN_LOCAL_HOST;
2073 default:
2074 return MGMT_DEV_DISCONN_UNKNOWN;
2075 }
2076}
2077
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002078static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002080 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002081 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002083 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 hci_dev_lock(hdev);
2086
Marcel Holtmann04837f62006-07-03 10:02:33 +02002087 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002088 if (!conn)
2089 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002090
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002091 if (ev->status == 0)
2092 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Johan Hedbergb644ba32012-01-17 21:48:47 +02002094 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002095 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002096 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002097 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002098 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002099 } else {
2100 u8 reason = hci_to_mgmt_reason(ev->reason);
2101
Johan Hedbergafc747a2012-01-15 18:11:07 +02002102 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002103 conn->dst_type, reason);
2104 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002105 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002106
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002107 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302108 if (conn->type == ACL_LINK && conn->flush_key)
2109 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002110 hci_proto_disconn_cfm(conn, ev->reason);
2111 hci_conn_del(conn);
2112 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002113
2114unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 hci_dev_unlock(hdev);
2116}
2117
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002118static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002119{
2120 struct hci_ev_auth_complete *ev = (void *) skb->data;
2121 struct hci_conn *conn;
2122
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002123 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002124
2125 hci_dev_lock(hdev);
2126
2127 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002128 if (!conn)
2129 goto unlock;
2130
2131 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002132 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002133 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002134 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002135 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002136 conn->link_mode |= HCI_LM_AUTH;
2137 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002138 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002139 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002140 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002141 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002142 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002143
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002144 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2145 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002146
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002147 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002148 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002149 struct hci_cp_set_conn_encrypt cp;
2150 cp.handle = ev->handle;
2151 cp.encrypt = 0x01;
2152 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002153 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002154 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002155 conn->state = BT_CONNECTED;
2156 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002157 hci_conn_put(conn);
2158 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002159 } else {
2160 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002161
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002162 hci_conn_hold(conn);
2163 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2164 hci_conn_put(conn);
2165 }
2166
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002167 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002168 if (!ev->status) {
2169 struct hci_cp_set_conn_encrypt cp;
2170 cp.handle = ev->handle;
2171 cp.encrypt = 0x01;
2172 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002173 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002174 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002175 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002176 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002177 }
2178 }
2179
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002180unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002181 hci_dev_unlock(hdev);
2182}
2183
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002184static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002185{
Johan Hedberg127178d2010-11-18 22:22:29 +02002186 struct hci_ev_remote_name *ev = (void *) skb->data;
2187 struct hci_conn *conn;
2188
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002189 BT_DBG("%s", hdev->name);
2190
2191 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002192
2193 hci_dev_lock(hdev);
2194
2195 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002196
2197 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2198 goto check_auth;
2199
2200 if (ev->status == 0)
2201 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002202 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002203 else
2204 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2205
2206check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002207 if (!conn)
2208 goto unlock;
2209
2210 if (!hci_outgoing_auth_needed(hdev, conn))
2211 goto unlock;
2212
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002213 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002214 struct hci_cp_auth_requested cp;
2215 cp.handle = __cpu_to_le16(conn->handle);
2216 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2217 }
2218
Johan Hedberg79c6c702011-04-28 11:28:55 -07002219unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002220 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002221}
2222
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002223static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002224{
2225 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2226 struct hci_conn *conn;
2227
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002228 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002229
2230 hci_dev_lock(hdev);
2231
2232 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2233 if (conn) {
2234 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002235 if (ev->encrypt) {
2236 /* Encryption implies authentication */
2237 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002238 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002239 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002240 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002241 conn->link_mode &= ~HCI_LM_ENCRYPT;
2242 }
2243
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002244 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002245
Gustavo Padovana7d77232012-05-13 03:20:07 -03002246 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002247 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002248 hci_conn_put(conn);
2249 goto unlock;
2250 }
2251
Marcel Holtmannf8558552008-07-14 20:13:49 +02002252 if (conn->state == BT_CONFIG) {
2253 if (!ev->status)
2254 conn->state = BT_CONNECTED;
2255
2256 hci_proto_connect_cfm(conn, ev->status);
2257 hci_conn_put(conn);
2258 } else
2259 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002260 }
2261
Gustavo Padovana7d77232012-05-13 03:20:07 -03002262unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002263 hci_dev_unlock(hdev);
2264}
2265
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002266static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2267 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002268{
2269 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2270 struct hci_conn *conn;
2271
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002272 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002273
2274 hci_dev_lock(hdev);
2275
2276 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2277 if (conn) {
2278 if (!ev->status)
2279 conn->link_mode |= HCI_LM_SECURE;
2280
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002281 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002282
2283 hci_key_change_cfm(conn, ev->status);
2284 }
2285
2286 hci_dev_unlock(hdev);
2287}
2288
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002289static void hci_remote_features_evt(struct hci_dev *hdev,
2290 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002291{
2292 struct hci_ev_remote_features *ev = (void *) skb->data;
2293 struct hci_conn *conn;
2294
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002295 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002296
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002297 hci_dev_lock(hdev);
2298
2299 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002300 if (!conn)
2301 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002302
Johan Hedbergccd556f2010-11-10 17:11:51 +02002303 if (!ev->status)
2304 memcpy(conn->features, ev->features, 8);
2305
2306 if (conn->state != BT_CONFIG)
2307 goto unlock;
2308
2309 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2310 struct hci_cp_read_remote_ext_features cp;
2311 cp.handle = ev->handle;
2312 cp.page = 0x01;
2313 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002314 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002315 goto unlock;
2316 }
2317
Johan Hedberg671267b2012-05-12 16:11:50 -03002318 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002319 struct hci_cp_remote_name_req cp;
2320 memset(&cp, 0, sizeof(cp));
2321 bacpy(&cp.bdaddr, &conn->dst);
2322 cp.pscan_rep_mode = 0x02;
2323 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002324 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2325 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002326 conn->dst_type, 0, NULL, 0,
2327 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002328
Johan Hedberg127178d2010-11-18 22:22:29 +02002329 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002330 conn->state = BT_CONNECTED;
2331 hci_proto_connect_cfm(conn, ev->status);
2332 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002333 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002334
Johan Hedbergccd556f2010-11-10 17:11:51 +02002335unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002336 hci_dev_unlock(hdev);
2337}
2338
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002339static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002340{
2341 BT_DBG("%s", hdev->name);
2342}
2343
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002344static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2345 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002346{
2347 BT_DBG("%s", hdev->name);
2348}
2349
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002350static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002351{
2352 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2353 __u16 opcode;
2354
2355 skb_pull(skb, sizeof(*ev));
2356
2357 opcode = __le16_to_cpu(ev->opcode);
2358
2359 switch (opcode) {
2360 case HCI_OP_INQUIRY_CANCEL:
2361 hci_cc_inquiry_cancel(hdev, skb);
2362 break;
2363
Andre Guedes4d934832012-03-21 00:03:35 -03002364 case HCI_OP_PERIODIC_INQ:
2365 hci_cc_periodic_inq(hdev, skb);
2366 break;
2367
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002368 case HCI_OP_EXIT_PERIODIC_INQ:
2369 hci_cc_exit_periodic_inq(hdev, skb);
2370 break;
2371
2372 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2373 hci_cc_remote_name_req_cancel(hdev, skb);
2374 break;
2375
2376 case HCI_OP_ROLE_DISCOVERY:
2377 hci_cc_role_discovery(hdev, skb);
2378 break;
2379
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002380 case HCI_OP_READ_LINK_POLICY:
2381 hci_cc_read_link_policy(hdev, skb);
2382 break;
2383
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002384 case HCI_OP_WRITE_LINK_POLICY:
2385 hci_cc_write_link_policy(hdev, skb);
2386 break;
2387
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002388 case HCI_OP_READ_DEF_LINK_POLICY:
2389 hci_cc_read_def_link_policy(hdev, skb);
2390 break;
2391
2392 case HCI_OP_WRITE_DEF_LINK_POLICY:
2393 hci_cc_write_def_link_policy(hdev, skb);
2394 break;
2395
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002396 case HCI_OP_RESET:
2397 hci_cc_reset(hdev, skb);
2398 break;
2399
2400 case HCI_OP_WRITE_LOCAL_NAME:
2401 hci_cc_write_local_name(hdev, skb);
2402 break;
2403
2404 case HCI_OP_READ_LOCAL_NAME:
2405 hci_cc_read_local_name(hdev, skb);
2406 break;
2407
2408 case HCI_OP_WRITE_AUTH_ENABLE:
2409 hci_cc_write_auth_enable(hdev, skb);
2410 break;
2411
2412 case HCI_OP_WRITE_ENCRYPT_MODE:
2413 hci_cc_write_encrypt_mode(hdev, skb);
2414 break;
2415
2416 case HCI_OP_WRITE_SCAN_ENABLE:
2417 hci_cc_write_scan_enable(hdev, skb);
2418 break;
2419
2420 case HCI_OP_READ_CLASS_OF_DEV:
2421 hci_cc_read_class_of_dev(hdev, skb);
2422 break;
2423
2424 case HCI_OP_WRITE_CLASS_OF_DEV:
2425 hci_cc_write_class_of_dev(hdev, skb);
2426 break;
2427
2428 case HCI_OP_READ_VOICE_SETTING:
2429 hci_cc_read_voice_setting(hdev, skb);
2430 break;
2431
2432 case HCI_OP_WRITE_VOICE_SETTING:
2433 hci_cc_write_voice_setting(hdev, skb);
2434 break;
2435
2436 case HCI_OP_HOST_BUFFER_SIZE:
2437 hci_cc_host_buffer_size(hdev, skb);
2438 break;
2439
Marcel Holtmann333140b2008-07-14 20:13:48 +02002440 case HCI_OP_WRITE_SSP_MODE:
2441 hci_cc_write_ssp_mode(hdev, skb);
2442 break;
2443
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002444 case HCI_OP_READ_LOCAL_VERSION:
2445 hci_cc_read_local_version(hdev, skb);
2446 break;
2447
2448 case HCI_OP_READ_LOCAL_COMMANDS:
2449 hci_cc_read_local_commands(hdev, skb);
2450 break;
2451
2452 case HCI_OP_READ_LOCAL_FEATURES:
2453 hci_cc_read_local_features(hdev, skb);
2454 break;
2455
Andre Guedes971e3a42011-06-30 19:20:52 -03002456 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2457 hci_cc_read_local_ext_features(hdev, skb);
2458 break;
2459
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002460 case HCI_OP_READ_BUFFER_SIZE:
2461 hci_cc_read_buffer_size(hdev, skb);
2462 break;
2463
2464 case HCI_OP_READ_BD_ADDR:
2465 hci_cc_read_bd_addr(hdev, skb);
2466 break;
2467
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002468 case HCI_OP_READ_DATA_BLOCK_SIZE:
2469 hci_cc_read_data_block_size(hdev, skb);
2470 break;
2471
Johan Hedberg23bb5762010-12-21 23:01:27 +02002472 case HCI_OP_WRITE_CA_TIMEOUT:
2473 hci_cc_write_ca_timeout(hdev, skb);
2474 break;
2475
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002476 case HCI_OP_READ_FLOW_CONTROL_MODE:
2477 hci_cc_read_flow_control_mode(hdev, skb);
2478 break;
2479
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002480 case HCI_OP_READ_LOCAL_AMP_INFO:
2481 hci_cc_read_local_amp_info(hdev, skb);
2482 break;
2483
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002484 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2485 hci_cc_read_local_amp_assoc(hdev, skb);
2486 break;
2487
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002488 case HCI_OP_DELETE_STORED_LINK_KEY:
2489 hci_cc_delete_stored_link_key(hdev, skb);
2490 break;
2491
Johan Hedbergd5859e22011-01-25 01:19:58 +02002492 case HCI_OP_SET_EVENT_MASK:
2493 hci_cc_set_event_mask(hdev, skb);
2494 break;
2495
2496 case HCI_OP_WRITE_INQUIRY_MODE:
2497 hci_cc_write_inquiry_mode(hdev, skb);
2498 break;
2499
2500 case HCI_OP_READ_INQ_RSP_TX_POWER:
2501 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2502 break;
2503
2504 case HCI_OP_SET_EVENT_FLT:
2505 hci_cc_set_event_flt(hdev, skb);
2506 break;
2507
Johan Hedberg980e1a52011-01-22 06:10:07 +02002508 case HCI_OP_PIN_CODE_REPLY:
2509 hci_cc_pin_code_reply(hdev, skb);
2510 break;
2511
2512 case HCI_OP_PIN_CODE_NEG_REPLY:
2513 hci_cc_pin_code_neg_reply(hdev, skb);
2514 break;
2515
Szymon Jancc35938b2011-03-22 13:12:21 +01002516 case HCI_OP_READ_LOCAL_OOB_DATA:
2517 hci_cc_read_local_oob_data_reply(hdev, skb);
2518 break;
2519
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002520 case HCI_OP_LE_READ_BUFFER_SIZE:
2521 hci_cc_le_read_buffer_size(hdev, skb);
2522 break;
2523
Johan Hedberg8fa19092012-10-19 20:57:49 +03002524 case HCI_OP_LE_READ_ADV_TX_POWER:
2525 hci_cc_le_read_adv_tx_power(hdev, skb);
2526 break;
2527
Johan Hedberge36b04c2012-10-19 20:57:47 +03002528 case HCI_OP_LE_SET_EVENT_MASK:
2529 hci_cc_le_set_event_mask(hdev, skb);
2530 break;
2531
Johan Hedberga5c29682011-02-19 12:05:57 -03002532 case HCI_OP_USER_CONFIRM_REPLY:
2533 hci_cc_user_confirm_reply(hdev, skb);
2534 break;
2535
2536 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2537 hci_cc_user_confirm_neg_reply(hdev, skb);
2538 break;
2539
Brian Gix1143d452011-11-23 08:28:34 -08002540 case HCI_OP_USER_PASSKEY_REPLY:
2541 hci_cc_user_passkey_reply(hdev, skb);
2542 break;
2543
2544 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2545 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002546 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002547
2548 case HCI_OP_LE_SET_SCAN_PARAM:
2549 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002550 break;
2551
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002552 case HCI_OP_LE_SET_SCAN_ENABLE:
2553 hci_cc_le_set_scan_enable(hdev, skb);
2554 break;
2555
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002556 case HCI_OP_LE_LTK_REPLY:
2557 hci_cc_le_ltk_reply(hdev, skb);
2558 break;
2559
2560 case HCI_OP_LE_LTK_NEG_REPLY:
2561 hci_cc_le_ltk_neg_reply(hdev, skb);
2562 break;
2563
Andre Guedesf9b49302011-06-30 19:20:53 -03002564 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2565 hci_cc_write_le_host_supported(hdev, skb);
2566 break;
2567
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002568 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2569 hci_cc_write_remote_amp_assoc(hdev, skb);
2570 break;
2571
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002572 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002573 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002574 break;
2575 }
2576
Ville Tervo6bd32322011-02-16 16:32:41 +02002577 if (ev->opcode != HCI_OP_NOP)
2578 del_timer(&hdev->cmd_timer);
2579
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002580 if (ev->ncmd) {
2581 atomic_set(&hdev->cmd_cnt, 1);
2582 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002583 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002584 }
2585}
2586
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002587static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002588{
2589 struct hci_ev_cmd_status *ev = (void *) skb->data;
2590 __u16 opcode;
2591
2592 skb_pull(skb, sizeof(*ev));
2593
2594 opcode = __le16_to_cpu(ev->opcode);
2595
2596 switch (opcode) {
2597 case HCI_OP_INQUIRY:
2598 hci_cs_inquiry(hdev, ev->status);
2599 break;
2600
2601 case HCI_OP_CREATE_CONN:
2602 hci_cs_create_conn(hdev, ev->status);
2603 break;
2604
2605 case HCI_OP_ADD_SCO:
2606 hci_cs_add_sco(hdev, ev->status);
2607 break;
2608
Marcel Holtmannf8558552008-07-14 20:13:49 +02002609 case HCI_OP_AUTH_REQUESTED:
2610 hci_cs_auth_requested(hdev, ev->status);
2611 break;
2612
2613 case HCI_OP_SET_CONN_ENCRYPT:
2614 hci_cs_set_conn_encrypt(hdev, ev->status);
2615 break;
2616
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002617 case HCI_OP_REMOTE_NAME_REQ:
2618 hci_cs_remote_name_req(hdev, ev->status);
2619 break;
2620
Marcel Holtmann769be972008-07-14 20:13:49 +02002621 case HCI_OP_READ_REMOTE_FEATURES:
2622 hci_cs_read_remote_features(hdev, ev->status);
2623 break;
2624
2625 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2626 hci_cs_read_remote_ext_features(hdev, ev->status);
2627 break;
2628
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002629 case HCI_OP_SETUP_SYNC_CONN:
2630 hci_cs_setup_sync_conn(hdev, ev->status);
2631 break;
2632
2633 case HCI_OP_SNIFF_MODE:
2634 hci_cs_sniff_mode(hdev, ev->status);
2635 break;
2636
2637 case HCI_OP_EXIT_SNIFF_MODE:
2638 hci_cs_exit_sniff_mode(hdev, ev->status);
2639 break;
2640
Johan Hedberg8962ee72011-01-20 12:40:27 +02002641 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002642 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002643 break;
2644
Ville Tervofcd89c02011-02-10 22:38:47 -03002645 case HCI_OP_LE_CREATE_CONN:
2646 hci_cs_le_create_conn(hdev, ev->status);
2647 break;
2648
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002649 case HCI_OP_LE_START_ENC:
2650 hci_cs_le_start_enc(hdev, ev->status);
2651 break;
2652
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002653 case HCI_OP_CREATE_PHY_LINK:
2654 hci_cs_create_phylink(hdev, ev->status);
2655 break;
2656
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002657 case HCI_OP_ACCEPT_PHY_LINK:
2658 hci_cs_accept_phylink(hdev, ev->status);
2659 break;
2660
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002661 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002662 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002663 break;
2664 }
2665
Ville Tervo6bd32322011-02-16 16:32:41 +02002666 if (ev->opcode != HCI_OP_NOP)
2667 del_timer(&hdev->cmd_timer);
2668
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002669 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002670 atomic_set(&hdev->cmd_cnt, 1);
2671 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002672 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002673 }
2674}
2675
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002676static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002677{
2678 struct hci_ev_role_change *ev = (void *) skb->data;
2679 struct hci_conn *conn;
2680
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002681 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002682
2683 hci_dev_lock(hdev);
2684
2685 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2686 if (conn) {
2687 if (!ev->status) {
2688 if (ev->role)
2689 conn->link_mode &= ~HCI_LM_MASTER;
2690 else
2691 conn->link_mode |= HCI_LM_MASTER;
2692 }
2693
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002694 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002695
2696 hci_role_switch_cfm(conn, ev->status, ev->role);
2697 }
2698
2699 hci_dev_unlock(hdev);
2700}
2701
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002702static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002704 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 int i;
2706
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002707 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2708 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2709 return;
2710 }
2711
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002712 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002713 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 BT_DBG("%s bad parameters", hdev->name);
2715 return;
2716 }
2717
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002718 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2719
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002720 for (i = 0; i < ev->num_hndl; i++) {
2721 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 struct hci_conn *conn;
2723 __u16 handle, count;
2724
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002725 handle = __le16_to_cpu(info->handle);
2726 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727
2728 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002729 if (!conn)
2730 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002732 conn->sent -= count;
2733
2734 switch (conn->type) {
2735 case ACL_LINK:
2736 hdev->acl_cnt += count;
2737 if (hdev->acl_cnt > hdev->acl_pkts)
2738 hdev->acl_cnt = hdev->acl_pkts;
2739 break;
2740
2741 case LE_LINK:
2742 if (hdev->le_pkts) {
2743 hdev->le_cnt += count;
2744 if (hdev->le_cnt > hdev->le_pkts)
2745 hdev->le_cnt = hdev->le_pkts;
2746 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002747 hdev->acl_cnt += count;
2748 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 hdev->acl_cnt = hdev->acl_pkts;
2750 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002751 break;
2752
2753 case SCO_LINK:
2754 hdev->sco_cnt += count;
2755 if (hdev->sco_cnt > hdev->sco_pkts)
2756 hdev->sco_cnt = hdev->sco_pkts;
2757 break;
2758
2759 default:
2760 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2761 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 }
2763 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002764
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002765 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766}
2767
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002768static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2769 __u16 handle)
2770{
2771 struct hci_chan *chan;
2772
2773 switch (hdev->dev_type) {
2774 case HCI_BREDR:
2775 return hci_conn_hash_lookup_handle(hdev, handle);
2776 case HCI_AMP:
2777 chan = hci_chan_lookup_handle(hdev, handle);
2778 if (chan)
2779 return chan->conn;
2780 break;
2781 default:
2782 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2783 break;
2784 }
2785
2786 return NULL;
2787}
2788
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002789static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002790{
2791 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2792 int i;
2793
2794 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2795 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2796 return;
2797 }
2798
2799 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002800 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002801 BT_DBG("%s bad parameters", hdev->name);
2802 return;
2803 }
2804
2805 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002806 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002807
2808 for (i = 0; i < ev->num_hndl; i++) {
2809 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002810 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002811 __u16 handle, block_count;
2812
2813 handle = __le16_to_cpu(info->handle);
2814 block_count = __le16_to_cpu(info->blocks);
2815
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002816 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002817 if (!conn)
2818 continue;
2819
2820 conn->sent -= block_count;
2821
2822 switch (conn->type) {
2823 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002824 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002825 hdev->block_cnt += block_count;
2826 if (hdev->block_cnt > hdev->num_blocks)
2827 hdev->block_cnt = hdev->num_blocks;
2828 break;
2829
2830 default:
2831 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2832 break;
2833 }
2834 }
2835
2836 queue_work(hdev->workqueue, &hdev->tx_work);
2837}
2838
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002839static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002841 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002842 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002844 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845
2846 hci_dev_lock(hdev);
2847
Marcel Holtmann04837f62006-07-03 10:02:33 +02002848 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2849 if (conn) {
2850 conn->mode = ev->mode;
2851 conn->interval = __le16_to_cpu(ev->interval);
2852
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002853 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2854 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002855 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002856 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002857 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002858 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002859 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002860
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002861 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002862 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002863 }
2864
2865 hci_dev_unlock(hdev);
2866}
2867
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002868static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002870 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2871 struct hci_conn *conn;
2872
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002873 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002874
2875 hci_dev_lock(hdev);
2876
2877 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002878 if (!conn)
2879 goto unlock;
2880
2881 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002882 hci_conn_hold(conn);
2883 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2884 hci_conn_put(conn);
2885 }
2886
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002887 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002888 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002889 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002890 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002891 u8 secure;
2892
2893 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2894 secure = 1;
2895 else
2896 secure = 0;
2897
Johan Hedberg744cf192011-11-08 20:40:14 +02002898 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002899 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002900
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002901unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002902 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903}
2904
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002905static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002907 struct hci_ev_link_key_req *ev = (void *) skb->data;
2908 struct hci_cp_link_key_reply cp;
2909 struct hci_conn *conn;
2910 struct link_key *key;
2911
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002912 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002913
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002914 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002915 return;
2916
2917 hci_dev_lock(hdev);
2918
2919 key = hci_find_link_key(hdev, &ev->bdaddr);
2920 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002921 BT_DBG("%s link key not found for %pMR", hdev->name,
2922 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002923 goto not_found;
2924 }
2925
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002926 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2927 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002928
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002929 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002930 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002931 BT_DBG("%s ignoring debug key", hdev->name);
2932 goto not_found;
2933 }
2934
2935 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002936 if (conn) {
2937 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002938 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002939 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2940 goto not_found;
2941 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002942
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002943 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002944 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002945 BT_DBG("%s ignoring key unauthenticated for high security",
2946 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002947 goto not_found;
2948 }
2949
2950 conn->key_type = key->type;
2951 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002952 }
2953
2954 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002955 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002956
2957 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2958
2959 hci_dev_unlock(hdev);
2960
2961 return;
2962
2963not_found:
2964 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2965 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966}
2967
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002968static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002970 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2971 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002972 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002973
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002974 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002975
2976 hci_dev_lock(hdev);
2977
2978 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2979 if (conn) {
2980 hci_conn_hold(conn);
2981 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002982 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002983
2984 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2985 conn->key_type = ev->key_type;
2986
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002987 hci_conn_put(conn);
2988 }
2989
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002990 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002991 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002992 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002993
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002994 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995}
2996
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002997static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002998{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002999 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003000 struct hci_conn *conn;
3001
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003002 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003003
3004 hci_dev_lock(hdev);
3005
3006 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 if (conn && !ev->status) {
3008 struct inquiry_entry *ie;
3009
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003010 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3011 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 ie->data.clock_offset = ev->clock_offset;
3013 ie->timestamp = jiffies;
3014 }
3015 }
3016
3017 hci_dev_unlock(hdev);
3018}
3019
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003020static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003021{
3022 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3023 struct hci_conn *conn;
3024
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003025 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003026
3027 hci_dev_lock(hdev);
3028
3029 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3030 if (conn && !ev->status)
3031 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3032
3033 hci_dev_unlock(hdev);
3034}
3035
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003036static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003037{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003038 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003039 struct inquiry_entry *ie;
3040
3041 BT_DBG("%s", hdev->name);
3042
3043 hci_dev_lock(hdev);
3044
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003045 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3046 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003047 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3048 ie->timestamp = jiffies;
3049 }
3050
3051 hci_dev_unlock(hdev);
3052}
3053
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003054static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3055 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003056{
3057 struct inquiry_data data;
3058 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003059 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003060
3061 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3062
3063 if (!num_rsp)
3064 return;
3065
Andre Guedes1519cc12012-03-21 00:03:38 -03003066 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3067 return;
3068
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003069 hci_dev_lock(hdev);
3070
3071 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003072 struct inquiry_info_with_rssi_and_pscan_mode *info;
3073 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003074
Johan Hedberge17acd42011-03-30 23:57:16 +03003075 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003076 bacpy(&data.bdaddr, &info->bdaddr);
3077 data.pscan_rep_mode = info->pscan_rep_mode;
3078 data.pscan_period_mode = info->pscan_period_mode;
3079 data.pscan_mode = info->pscan_mode;
3080 memcpy(data.dev_class, info->dev_class, 3);
3081 data.clock_offset = info->clock_offset;
3082 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003083 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003084
3085 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003086 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003087 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003088 info->dev_class, info->rssi,
3089 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003090 }
3091 } else {
3092 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3093
Johan Hedberge17acd42011-03-30 23:57:16 +03003094 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003095 bacpy(&data.bdaddr, &info->bdaddr);
3096 data.pscan_rep_mode = info->pscan_rep_mode;
3097 data.pscan_period_mode = info->pscan_period_mode;
3098 data.pscan_mode = 0x00;
3099 memcpy(data.dev_class, info->dev_class, 3);
3100 data.clock_offset = info->clock_offset;
3101 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003102 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003103 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003104 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003105 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003106 info->dev_class, info->rssi,
3107 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003108 }
3109 }
3110
3111 hci_dev_unlock(hdev);
3112}
3113
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003114static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3115 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003116{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003117 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3118 struct hci_conn *conn;
3119
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003120 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003121
Marcel Holtmann41a96212008-07-14 20:13:48 +02003122 hci_dev_lock(hdev);
3123
3124 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003125 if (!conn)
3126 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003127
Johan Hedbergccd556f2010-11-10 17:11:51 +02003128 if (!ev->status && ev->page == 0x01) {
3129 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003130
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003131 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3132 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003133 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003134
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003135 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003136 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003137 }
3138
Johan Hedbergccd556f2010-11-10 17:11:51 +02003139 if (conn->state != BT_CONFIG)
3140 goto unlock;
3141
Johan Hedberg671267b2012-05-12 16:11:50 -03003142 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003143 struct hci_cp_remote_name_req cp;
3144 memset(&cp, 0, sizeof(cp));
3145 bacpy(&cp.bdaddr, &conn->dst);
3146 cp.pscan_rep_mode = 0x02;
3147 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003148 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3149 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003150 conn->dst_type, 0, NULL, 0,
3151 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003152
Johan Hedberg127178d2010-11-18 22:22:29 +02003153 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003154 conn->state = BT_CONNECTED;
3155 hci_proto_connect_cfm(conn, ev->status);
3156 hci_conn_put(conn);
3157 }
3158
3159unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003160 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003161}
3162
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003163static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3164 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003165{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003166 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3167 struct hci_conn *conn;
3168
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003169 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003170
3171 hci_dev_lock(hdev);
3172
3173 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003174 if (!conn) {
3175 if (ev->link_type == ESCO_LINK)
3176 goto unlock;
3177
3178 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3179 if (!conn)
3180 goto unlock;
3181
3182 conn->type = SCO_LINK;
3183 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003184
Marcel Holtmann732547f2009-04-19 19:14:14 +02003185 switch (ev->status) {
3186 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003187 conn->handle = __le16_to_cpu(ev->handle);
3188 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003189
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003190 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003191 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003192 break;
3193
Stephen Coe705e5712010-02-16 11:29:44 -05003194 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003195 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003196 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003197 case 0x1f: /* Unspecified error */
3198 if (conn->out && conn->attempt < 2) {
3199 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3200 (hdev->esco_type & EDR_ESCO_MASK);
3201 hci_setup_sync(conn, conn->link->handle);
3202 goto unlock;
3203 }
3204 /* fall through */
3205
3206 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003207 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003208 break;
3209 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003210
3211 hci_proto_connect_cfm(conn, ev->status);
3212 if (ev->status)
3213 hci_conn_del(conn);
3214
3215unlock:
3216 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003217}
3218
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003219static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003220{
3221 BT_DBG("%s", hdev->name);
3222}
3223
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003224static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003225{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003226 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003227
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003228 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003229}
3230
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003231static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3232 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003233{
3234 struct inquiry_data data;
3235 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3236 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303237 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003238
3239 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3240
3241 if (!num_rsp)
3242 return;
3243
Andre Guedes1519cc12012-03-21 00:03:38 -03003244 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3245 return;
3246
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003247 hci_dev_lock(hdev);
3248
Johan Hedberge17acd42011-03-30 23:57:16 +03003249 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003250 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003251
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003252 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003253 data.pscan_rep_mode = info->pscan_rep_mode;
3254 data.pscan_period_mode = info->pscan_period_mode;
3255 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003256 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003257 data.clock_offset = info->clock_offset;
3258 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003259 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003260
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003261 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003262 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003263 sizeof(info->data),
3264 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003265 else
3266 name_known = true;
3267
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003268 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003269 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303270 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003271 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003272 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303273 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003274 }
3275
3276 hci_dev_unlock(hdev);
3277}
3278
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003279static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3280 struct sk_buff *skb)
3281{
3282 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3283 struct hci_conn *conn;
3284
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003285 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003286 __le16_to_cpu(ev->handle));
3287
3288 hci_dev_lock(hdev);
3289
3290 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3291 if (!conn)
3292 goto unlock;
3293
3294 if (!ev->status)
3295 conn->sec_level = conn->pending_sec_level;
3296
3297 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3298
3299 if (ev->status && conn->state == BT_CONNECTED) {
3300 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3301 hci_conn_put(conn);
3302 goto unlock;
3303 }
3304
3305 if (conn->state == BT_CONFIG) {
3306 if (!ev->status)
3307 conn->state = BT_CONNECTED;
3308
3309 hci_proto_connect_cfm(conn, ev->status);
3310 hci_conn_put(conn);
3311 } else {
3312 hci_auth_cfm(conn, ev->status);
3313
3314 hci_conn_hold(conn);
3315 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3316 hci_conn_put(conn);
3317 }
3318
3319unlock:
3320 hci_dev_unlock(hdev);
3321}
3322
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003323static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003324{
3325 /* If remote requests dedicated bonding follow that lead */
3326 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3327 /* If both remote and local IO capabilities allow MITM
3328 * protection then require it, otherwise don't */
3329 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3330 return 0x02;
3331 else
3332 return 0x03;
3333 }
3334
3335 /* If remote requests no-bonding follow that lead */
3336 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003337 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003338
3339 return conn->auth_type;
3340}
3341
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003342static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003343{
3344 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3345 struct hci_conn *conn;
3346
3347 BT_DBG("%s", hdev->name);
3348
3349 hci_dev_lock(hdev);
3350
3351 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003352 if (!conn)
3353 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003354
Johan Hedberg03b555e2011-01-04 15:40:05 +02003355 hci_conn_hold(conn);
3356
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003357 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003358 goto unlock;
3359
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003360 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003361 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003362 struct hci_cp_io_capability_reply cp;
3363
3364 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303365 /* Change the IO capability from KeyboardDisplay
3366 * to DisplayYesNo as it is not supported by BT spec. */
3367 cp.capability = (conn->io_capability == 0x04) ?
3368 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003369 conn->auth_type = hci_get_auth_req(conn);
3370 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003371
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003372 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3373 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003374 cp.oob_data = 0x01;
3375 else
3376 cp.oob_data = 0x00;
3377
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003378 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003379 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003380 } else {
3381 struct hci_cp_io_capability_neg_reply cp;
3382
3383 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003384 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003385
3386 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003387 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003388 }
3389
3390unlock:
3391 hci_dev_unlock(hdev);
3392}
3393
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003394static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003395{
3396 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3397 struct hci_conn *conn;
3398
3399 BT_DBG("%s", hdev->name);
3400
3401 hci_dev_lock(hdev);
3402
3403 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3404 if (!conn)
3405 goto unlock;
3406
Johan Hedberg03b555e2011-01-04 15:40:05 +02003407 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003408 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003409 if (ev->oob_data)
3410 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003411
3412unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003413 hci_dev_unlock(hdev);
3414}
3415
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003416static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3417 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003418{
3419 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003420 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003421 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003422
3423 BT_DBG("%s", hdev->name);
3424
3425 hci_dev_lock(hdev);
3426
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003427 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003428 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003429
Johan Hedberg7a828902011-04-28 11:28:53 -07003430 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3431 if (!conn)
3432 goto unlock;
3433
3434 loc_mitm = (conn->auth_type & 0x01);
3435 rem_mitm = (conn->remote_auth & 0x01);
3436
3437 /* If we require MITM but the remote device can't provide that
3438 * (it has NoInputNoOutput) then reject the confirmation
3439 * request. The only exception is when we're dedicated bonding
3440 * initiators (connect_cfm_cb set) since then we always have the MITM
3441 * bit set. */
3442 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3443 BT_DBG("Rejecting request: remote device can't provide MITM");
3444 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003445 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003446 goto unlock;
3447 }
3448
3449 /* If no side requires MITM protection; auto-accept */
3450 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003451 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003452
3453 /* If we're not the initiators request authorization to
3454 * proceed from user space (mgmt_user_confirm with
3455 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003456 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003457 BT_DBG("Confirming auto-accept as acceptor");
3458 confirm_hint = 1;
3459 goto confirm;
3460 }
3461
Johan Hedberg9f616562011-04-28 11:28:54 -07003462 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003463 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003464
3465 if (hdev->auto_accept_delay > 0) {
3466 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3467 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3468 goto unlock;
3469 }
3470
Johan Hedberg7a828902011-04-28 11:28:53 -07003471 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003472 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003473 goto unlock;
3474 }
3475
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003476confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003477 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003478 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003479
3480unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003481 hci_dev_unlock(hdev);
3482}
3483
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003484static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3485 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003486{
3487 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3488
3489 BT_DBG("%s", hdev->name);
3490
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003491 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003492 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003493}
3494
Johan Hedberg92a25252012-09-06 18:39:26 +03003495static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3496 struct sk_buff *skb)
3497{
3498 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3499 struct hci_conn *conn;
3500
3501 BT_DBG("%s", hdev->name);
3502
3503 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3504 if (!conn)
3505 return;
3506
3507 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3508 conn->passkey_entered = 0;
3509
3510 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3511 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3512 conn->dst_type, conn->passkey_notify,
3513 conn->passkey_entered);
3514}
3515
3516static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3517{
3518 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3519 struct hci_conn *conn;
3520
3521 BT_DBG("%s", hdev->name);
3522
3523 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3524 if (!conn)
3525 return;
3526
3527 switch (ev->type) {
3528 case HCI_KEYPRESS_STARTED:
3529 conn->passkey_entered = 0;
3530 return;
3531
3532 case HCI_KEYPRESS_ENTERED:
3533 conn->passkey_entered++;
3534 break;
3535
3536 case HCI_KEYPRESS_ERASED:
3537 conn->passkey_entered--;
3538 break;
3539
3540 case HCI_KEYPRESS_CLEARED:
3541 conn->passkey_entered = 0;
3542 break;
3543
3544 case HCI_KEYPRESS_COMPLETED:
3545 return;
3546 }
3547
3548 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3549 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3550 conn->dst_type, conn->passkey_notify,
3551 conn->passkey_entered);
3552}
3553
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003554static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3555 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003556{
3557 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3558 struct hci_conn *conn;
3559
3560 BT_DBG("%s", hdev->name);
3561
3562 hci_dev_lock(hdev);
3563
3564 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003565 if (!conn)
3566 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003567
Johan Hedberg2a611692011-02-19 12:06:00 -03003568 /* To avoid duplicate auth_failed events to user space we check
3569 * the HCI_CONN_AUTH_PEND flag which will be set if we
3570 * initiated the authentication. A traditional auth_complete
3571 * event gets always produced as initiator and is also mapped to
3572 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003573 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003574 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003575 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003576
3577 hci_conn_put(conn);
3578
3579unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003580 hci_dev_unlock(hdev);
3581}
3582
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003583static void hci_remote_host_features_evt(struct hci_dev *hdev,
3584 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003585{
3586 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3587 struct inquiry_entry *ie;
3588
3589 BT_DBG("%s", hdev->name);
3590
3591 hci_dev_lock(hdev);
3592
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003593 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3594 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003595 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003596
3597 hci_dev_unlock(hdev);
3598}
3599
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003600static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3601 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003602{
3603 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3604 struct oob_data *data;
3605
3606 BT_DBG("%s", hdev->name);
3607
3608 hci_dev_lock(hdev);
3609
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003610 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003611 goto unlock;
3612
Szymon Janc2763eda2011-03-22 13:12:22 +01003613 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3614 if (data) {
3615 struct hci_cp_remote_oob_data_reply cp;
3616
3617 bacpy(&cp.bdaddr, &ev->bdaddr);
3618 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3619 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3620
3621 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003622 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003623 } else {
3624 struct hci_cp_remote_oob_data_neg_reply cp;
3625
3626 bacpy(&cp.bdaddr, &ev->bdaddr);
3627 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003628 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003629 }
3630
Szymon Jance1ba1f12011-04-06 13:01:59 +02003631unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003632 hci_dev_unlock(hdev);
3633}
3634
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003635static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003636{
3637 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3638 struct hci_conn *conn;
3639
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003640 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003641
3642 hci_dev_lock(hdev);
3643
Andre Guedesb47a09b2012-07-27 15:10:15 -03003644 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003645 if (!conn) {
3646 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3647 if (!conn) {
3648 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003649 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003650 }
Andre Guedes29b79882011-05-31 14:20:54 -03003651
3652 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003653
3654 if (ev->role == LE_CONN_ROLE_MASTER) {
3655 conn->out = true;
3656 conn->link_mode |= HCI_LM_MASTER;
3657 }
Ville Tervob62f3282011-02-10 22:38:50 -03003658 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003659
Andre Guedescd17dec2012-07-27 15:10:16 -03003660 if (ev->status) {
3661 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3662 conn->dst_type, ev->status);
3663 hci_proto_connect_cfm(conn, ev->status);
3664 conn->state = BT_CLOSED;
3665 hci_conn_del(conn);
3666 goto unlock;
3667 }
3668
Johan Hedbergb644ba32012-01-17 21:48:47 +02003669 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3670 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003671 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003672
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003673 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003674 conn->handle = __le16_to_cpu(ev->handle);
3675 conn->state = BT_CONNECTED;
3676
3677 hci_conn_hold_device(conn);
3678 hci_conn_add_sysfs(conn);
3679
3680 hci_proto_connect_cfm(conn, ev->status);
3681
3682unlock:
3683 hci_dev_unlock(hdev);
3684}
3685
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003686static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003687{
Andre Guedese95beb42011-09-26 20:48:35 -03003688 u8 num_reports = skb->data[0];
3689 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003690 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003691
3692 hci_dev_lock(hdev);
3693
Andre Guedese95beb42011-09-26 20:48:35 -03003694 while (num_reports--) {
3695 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003696
Andre Guedes3c9e9192012-01-10 18:20:50 -03003697 rssi = ev->data[ev->length];
3698 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003699 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003700
Andre Guedese95beb42011-09-26 20:48:35 -03003701 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003702 }
3703
3704 hci_dev_unlock(hdev);
3705}
3706
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003707static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003708{
3709 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3710 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003711 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003712 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003713 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003714
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003715 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003716
3717 hci_dev_lock(hdev);
3718
3719 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003720 if (conn == NULL)
3721 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003722
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003723 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3724 if (ltk == NULL)
3725 goto not_found;
3726
3727 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003728 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003729
3730 if (ltk->authenticated)
3731 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003732
3733 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3734
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003735 if (ltk->type & HCI_SMP_STK) {
3736 list_del(&ltk->list);
3737 kfree(ltk);
3738 }
3739
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003740 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003741
3742 return;
3743
3744not_found:
3745 neg.handle = ev->handle;
3746 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3747 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003748}
3749
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003750static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003751{
3752 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3753
3754 skb_pull(skb, sizeof(*le_ev));
3755
3756 switch (le_ev->subevent) {
3757 case HCI_EV_LE_CONN_COMPLETE:
3758 hci_le_conn_complete_evt(hdev, skb);
3759 break;
3760
Andre Guedes9aa04c92011-05-26 16:23:51 -03003761 case HCI_EV_LE_ADVERTISING_REPORT:
3762 hci_le_adv_report_evt(hdev, skb);
3763 break;
3764
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003765 case HCI_EV_LE_LTK_REQ:
3766 hci_le_ltk_request_evt(hdev, skb);
3767 break;
3768
Ville Tervofcd89c02011-02-10 22:38:47 -03003769 default:
3770 break;
3771 }
3772}
3773
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003774static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3775{
3776 struct hci_ev_channel_selected *ev = (void *) skb->data;
3777 struct hci_conn *hcon;
3778
3779 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3780
3781 skb_pull(skb, sizeof(*ev));
3782
3783 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3784 if (!hcon)
3785 return;
3786
3787 amp_read_loc_assoc_final_data(hdev, hcon);
3788}
3789
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3791{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003792 struct hci_event_hdr *hdr = (void *) skb->data;
3793 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794
3795 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3796
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003797 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 case HCI_EV_INQUIRY_COMPLETE:
3799 hci_inquiry_complete_evt(hdev, skb);
3800 break;
3801
3802 case HCI_EV_INQUIRY_RESULT:
3803 hci_inquiry_result_evt(hdev, skb);
3804 break;
3805
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003806 case HCI_EV_CONN_COMPLETE:
3807 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003808 break;
3809
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 case HCI_EV_CONN_REQUEST:
3811 hci_conn_request_evt(hdev, skb);
3812 break;
3813
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 case HCI_EV_DISCONN_COMPLETE:
3815 hci_disconn_complete_evt(hdev, skb);
3816 break;
3817
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818 case HCI_EV_AUTH_COMPLETE:
3819 hci_auth_complete_evt(hdev, skb);
3820 break;
3821
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003822 case HCI_EV_REMOTE_NAME:
3823 hci_remote_name_evt(hdev, skb);
3824 break;
3825
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 case HCI_EV_ENCRYPT_CHANGE:
3827 hci_encrypt_change_evt(hdev, skb);
3828 break;
3829
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003830 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3831 hci_change_link_key_complete_evt(hdev, skb);
3832 break;
3833
3834 case HCI_EV_REMOTE_FEATURES:
3835 hci_remote_features_evt(hdev, skb);
3836 break;
3837
3838 case HCI_EV_REMOTE_VERSION:
3839 hci_remote_version_evt(hdev, skb);
3840 break;
3841
3842 case HCI_EV_QOS_SETUP_COMPLETE:
3843 hci_qos_setup_complete_evt(hdev, skb);
3844 break;
3845
3846 case HCI_EV_CMD_COMPLETE:
3847 hci_cmd_complete_evt(hdev, skb);
3848 break;
3849
3850 case HCI_EV_CMD_STATUS:
3851 hci_cmd_status_evt(hdev, skb);
3852 break;
3853
3854 case HCI_EV_ROLE_CHANGE:
3855 hci_role_change_evt(hdev, skb);
3856 break;
3857
3858 case HCI_EV_NUM_COMP_PKTS:
3859 hci_num_comp_pkts_evt(hdev, skb);
3860 break;
3861
3862 case HCI_EV_MODE_CHANGE:
3863 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 break;
3865
3866 case HCI_EV_PIN_CODE_REQ:
3867 hci_pin_code_request_evt(hdev, skb);
3868 break;
3869
3870 case HCI_EV_LINK_KEY_REQ:
3871 hci_link_key_request_evt(hdev, skb);
3872 break;
3873
3874 case HCI_EV_LINK_KEY_NOTIFY:
3875 hci_link_key_notify_evt(hdev, skb);
3876 break;
3877
3878 case HCI_EV_CLOCK_OFFSET:
3879 hci_clock_offset_evt(hdev, skb);
3880 break;
3881
Marcel Holtmanna8746412008-07-14 20:13:46 +02003882 case HCI_EV_PKT_TYPE_CHANGE:
3883 hci_pkt_type_change_evt(hdev, skb);
3884 break;
3885
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003886 case HCI_EV_PSCAN_REP_MODE:
3887 hci_pscan_rep_mode_evt(hdev, skb);
3888 break;
3889
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003890 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3891 hci_inquiry_result_with_rssi_evt(hdev, skb);
3892 break;
3893
3894 case HCI_EV_REMOTE_EXT_FEATURES:
3895 hci_remote_ext_features_evt(hdev, skb);
3896 break;
3897
3898 case HCI_EV_SYNC_CONN_COMPLETE:
3899 hci_sync_conn_complete_evt(hdev, skb);
3900 break;
3901
3902 case HCI_EV_SYNC_CONN_CHANGED:
3903 hci_sync_conn_changed_evt(hdev, skb);
3904 break;
3905
Marcel Holtmann04837f62006-07-03 10:02:33 +02003906 case HCI_EV_SNIFF_SUBRATE:
3907 hci_sniff_subrate_evt(hdev, skb);
3908 break;
3909
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003910 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3911 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 break;
3913
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003914 case HCI_EV_KEY_REFRESH_COMPLETE:
3915 hci_key_refresh_complete_evt(hdev, skb);
3916 break;
3917
Marcel Holtmann04936842008-07-14 20:13:48 +02003918 case HCI_EV_IO_CAPA_REQUEST:
3919 hci_io_capa_request_evt(hdev, skb);
3920 break;
3921
Johan Hedberg03b555e2011-01-04 15:40:05 +02003922 case HCI_EV_IO_CAPA_REPLY:
3923 hci_io_capa_reply_evt(hdev, skb);
3924 break;
3925
Johan Hedberga5c29682011-02-19 12:05:57 -03003926 case HCI_EV_USER_CONFIRM_REQUEST:
3927 hci_user_confirm_request_evt(hdev, skb);
3928 break;
3929
Brian Gix1143d452011-11-23 08:28:34 -08003930 case HCI_EV_USER_PASSKEY_REQUEST:
3931 hci_user_passkey_request_evt(hdev, skb);
3932 break;
3933
Johan Hedberg92a25252012-09-06 18:39:26 +03003934 case HCI_EV_USER_PASSKEY_NOTIFY:
3935 hci_user_passkey_notify_evt(hdev, skb);
3936 break;
3937
3938 case HCI_EV_KEYPRESS_NOTIFY:
3939 hci_keypress_notify_evt(hdev, skb);
3940 break;
3941
Marcel Holtmann04936842008-07-14 20:13:48 +02003942 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3943 hci_simple_pair_complete_evt(hdev, skb);
3944 break;
3945
Marcel Holtmann41a96212008-07-14 20:13:48 +02003946 case HCI_EV_REMOTE_HOST_FEATURES:
3947 hci_remote_host_features_evt(hdev, skb);
3948 break;
3949
Ville Tervofcd89c02011-02-10 22:38:47 -03003950 case HCI_EV_LE_META:
3951 hci_le_meta_evt(hdev, skb);
3952 break;
3953
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003954 case HCI_EV_CHANNEL_SELECTED:
3955 hci_chan_selected_evt(hdev, skb);
3956 break;
3957
Szymon Janc2763eda2011-03-22 13:12:22 +01003958 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3959 hci_remote_oob_data_request_evt(hdev, skb);
3960 break;
3961
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003962 case HCI_EV_NUM_COMP_BLOCKS:
3963 hci_num_comp_blocks_evt(hdev, skb);
3964 break;
3965
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003966 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003967 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 break;
3969 }
3970
3971 kfree_skb(skb);
3972 hdev->stat.evt_rx++;
3973}