blob: f4f0b8bfdee600a9b4e8fb864255eba455b9c719 [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);
553}
554
Johan Hedberge1171e82012-10-19 20:57:45 +0300555static void bredr_init(struct hci_dev *hdev)
556{
557 struct hci_cp_delete_stored_link_key cp;
558 __le16 param;
559 __u8 flt_type;
560
561 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
562 hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
563
564 /* Read Class of Device */
565 hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
566
567 /* Read Local Name */
568 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
569
570 /* Read Voice Setting */
571 hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
572
573 /* Clear Event Filters */
574 flt_type = HCI_FLT_CLEAR_ALL;
575 hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
576
577 /* Connection accept timeout ~20 secs */
578 param = __constant_cpu_to_le16(0x7d00);
579 hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
580
581 bacpy(&cp.bdaddr, BDADDR_ANY);
582 cp.delete_all = 1;
583 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
584}
585
586static void le_init(struct hci_dev *hdev)
587{
588 /* Read LE Buffer Size */
589 hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
590}
591
Johan Hedbergd5859e22011-01-25 01:19:58 +0200592static void hci_setup(struct hci_dev *hdev)
593{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200594 if (hdev->dev_type != HCI_BREDR)
595 return;
596
Johan Hedberge1171e82012-10-19 20:57:45 +0300597 /* Read BD Address */
598 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
599
600 if (lmp_bredr_capable(hdev))
601 bredr_init(hdev);
602
603 if (lmp_le_capable(hdev))
604 le_init(hdev);
605
Johan Hedbergd5859e22011-01-25 01:19:58 +0200606 hci_setup_event_mask(hdev);
607
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200608 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200609 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
610
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300611 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200612 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
613 u8 mode = 0x01;
614 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300615 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200616 } else {
617 struct hci_cp_write_eir cp;
618
619 memset(hdev->eir, 0, sizeof(hdev->eir));
620 memset(&cp, 0, sizeof(cp));
621
622 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
623 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200624 }
625
626 if (hdev->features[3] & LMP_RSSI_INQ)
627 hci_setup_inquiry_mode(hdev);
628
629 if (hdev->features[7] & LMP_INQ_TX_PWR)
630 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300631
632 if (hdev->features[7] & LMP_EXTFEATURES) {
633 struct hci_cp_read_local_ext_features cp;
634
635 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300636 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
637 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300638 }
Andre Guedese6100a22011-06-30 19:20:54 -0300639
Johan Hedberg47990ea2012-02-22 11:58:37 +0200640 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
641 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300642 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
643 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200644 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200645}
646
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200647static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
648{
649 struct hci_rp_read_local_version *rp = (void *) skb->data;
650
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300651 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200652
653 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200654 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200655
656 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200657 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200658 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200659 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200660 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200661
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300662 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300663 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200664
665 if (test_bit(HCI_INIT, &hdev->flags))
666 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200667
668done:
669 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200670}
671
672static void hci_setup_link_policy(struct hci_dev *hdev)
673{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200674 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200675 u16 link_policy = 0;
676
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300677 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200678 link_policy |= HCI_LP_RSWITCH;
679 if (hdev->features[0] & LMP_HOLD)
680 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300681 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200682 link_policy |= HCI_LP_SNIFF;
683 if (hdev->features[1] & LMP_PARK)
684 link_policy |= HCI_LP_PARK;
685
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200686 cp.policy = cpu_to_le16(link_policy);
687 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200688}
689
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300690static void hci_cc_read_local_commands(struct hci_dev *hdev,
691 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200692{
693 struct hci_rp_read_local_commands *rp = (void *) skb->data;
694
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300695 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200696
697 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200698 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200699
700 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200701
702 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
703 hci_setup_link_policy(hdev);
704
705done:
706 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200707}
708
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300709static void hci_cc_read_local_features(struct hci_dev *hdev,
710 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200711{
712 struct hci_rp_read_local_features *rp = (void *) skb->data;
713
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300714 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200715
716 if (rp->status)
717 return;
718
719 memcpy(hdev->features, rp->features, 8);
720
721 /* Adjust default settings according to features
722 * supported by device. */
723
724 if (hdev->features[0] & LMP_3SLOT)
725 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
726
727 if (hdev->features[0] & LMP_5SLOT)
728 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
729
730 if (hdev->features[1] & LMP_HV2) {
731 hdev->pkt_type |= (HCI_HV2);
732 hdev->esco_type |= (ESCO_HV2);
733 }
734
735 if (hdev->features[1] & LMP_HV3) {
736 hdev->pkt_type |= (HCI_HV3);
737 hdev->esco_type |= (ESCO_HV3);
738 }
739
Andre Guedes45db810f2012-07-24 15:03:49 -0300740 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200741 hdev->esco_type |= (ESCO_EV3);
742
743 if (hdev->features[4] & LMP_EV4)
744 hdev->esco_type |= (ESCO_EV4);
745
746 if (hdev->features[4] & LMP_EV5)
747 hdev->esco_type |= (ESCO_EV5);
748
Marcel Holtmannefc76882009-02-06 09:13:37 +0100749 if (hdev->features[5] & LMP_EDR_ESCO_2M)
750 hdev->esco_type |= (ESCO_2EV3);
751
752 if (hdev->features[5] & LMP_EDR_ESCO_3M)
753 hdev->esco_type |= (ESCO_3EV3);
754
755 if (hdev->features[5] & LMP_EDR_3S_ESCO)
756 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
757
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200758 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300759 hdev->features[0], hdev->features[1],
760 hdev->features[2], hdev->features[3],
761 hdev->features[4], hdev->features[5],
762 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200763}
764
Johan Hedberg8f984df2012-02-28 01:07:22 +0200765static void hci_set_le_support(struct hci_dev *hdev)
766{
767 struct hci_cp_write_le_host_supported cp;
768
769 memset(&cp, 0, sizeof(cp));
770
Marcel Holtmann9d428202012-05-03 07:12:31 +0200771 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200772 cp.le = 1;
773 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
774 }
775
776 if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300777 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
778 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200779}
780
Andre Guedes971e3a42011-06-30 19:20:52 -0300781static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300782 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300783{
784 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
785
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300786 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300787
788 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200789 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300790
Andre Guedesb5b32b62011-12-30 10:34:04 -0300791 switch (rp->page) {
792 case 0:
793 memcpy(hdev->features, rp->features, 8);
794 break;
795 case 1:
796 memcpy(hdev->host_features, rp->features, 8);
797 break;
798 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300799
Andre Guedesc383ddc2012-07-24 15:03:47 -0300800 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200801 hci_set_le_support(hdev);
802
803done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300804 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
805}
806
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200807static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300808 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200809{
810 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
811
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300812 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200813
814 if (rp->status)
815 return;
816
817 hdev->flow_ctl_mode = rp->mode;
818
819 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
820}
821
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200822static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
823{
824 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
825
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300826 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200827
828 if (rp->status)
829 return;
830
831 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
832 hdev->sco_mtu = rp->sco_mtu;
833 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
834 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
835
836 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
837 hdev->sco_mtu = 64;
838 hdev->sco_pkts = 8;
839 }
840
841 hdev->acl_cnt = hdev->acl_pkts;
842 hdev->sco_cnt = hdev->sco_pkts;
843
Gustavo Padovan807deac2012-05-17 00:36:24 -0300844 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
845 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200846}
847
848static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
849{
850 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
851
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300852 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200853
854 if (!rp->status)
855 bacpy(&hdev->bdaddr, &rp->bdaddr);
856
Johan Hedberg23bb5762010-12-21 23:01:27 +0200857 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
858}
859
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200860static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300861 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200862{
863 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
864
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300865 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200866
867 if (rp->status)
868 return;
869
870 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
871 hdev->block_len = __le16_to_cpu(rp->block_len);
872 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
873
874 hdev->block_cnt = hdev->num_blocks;
875
876 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300877 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200878
879 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
880}
881
Johan Hedberg23bb5762010-12-21 23:01:27 +0200882static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
883{
884 __u8 status = *((__u8 *) skb->data);
885
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300886 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200887
888 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200889}
890
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300891static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300892 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300893{
894 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
895
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300896 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300897
898 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300899 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300900
901 hdev->amp_status = rp->amp_status;
902 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
903 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
904 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
905 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
906 hdev->amp_type = rp->amp_type;
907 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
908 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
909 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
910 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
911
912 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300913
914a2mp_rsp:
915 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300916}
917
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300918static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
919 struct sk_buff *skb)
920{
921 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
922 struct amp_assoc *assoc = &hdev->loc_assoc;
923 size_t rem_len, frag_len;
924
925 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
926
927 if (rp->status)
928 goto a2mp_rsp;
929
930 frag_len = skb->len - sizeof(*rp);
931 rem_len = __le16_to_cpu(rp->rem_len);
932
933 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300934 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300935
936 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
937 assoc->offset += frag_len;
938
939 /* Read other fragments */
940 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
941
942 return;
943 }
944
945 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
946 assoc->len = assoc->offset + rem_len;
947 assoc->offset = 0;
948
949a2mp_rsp:
950 /* Send A2MP Rsp when all fragments are received */
951 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300952 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300953}
954
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200955static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300956 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200957{
958 __u8 status = *((__u8 *) skb->data);
959
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300960 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200961
962 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
963}
964
Johan Hedbergd5859e22011-01-25 01:19:58 +0200965static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
966{
967 __u8 status = *((__u8 *) skb->data);
968
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300969 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200970
971 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
972}
973
974static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300975 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200976{
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_WRITE_INQUIRY_MODE, status);
982}
983
984static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300985 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200986{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700987 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200988
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300989 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200990
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700991 if (!rp->status)
992 hdev->inq_tx_power = rp->tx_power;
993
994 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200995}
996
997static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
998{
999 __u8 status = *((__u8 *) skb->data);
1000
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001001 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001002
1003 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1004}
1005
Johan Hedberg980e1a52011-01-22 06:10:07 +02001006static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1007{
1008 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1009 struct hci_cp_pin_code_reply *cp;
1010 struct hci_conn *conn;
1011
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001012 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001013
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001014 hci_dev_lock(hdev);
1015
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001016 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001017 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001018
Mikel Astizfa1bd912012-08-09 09:52:29 +02001019 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001020 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001021
1022 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1023 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001024 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001025
1026 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1027 if (conn)
1028 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001029
1030unlock:
1031 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001032}
1033
1034static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1035{
1036 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1037
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001038 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001039
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001040 hci_dev_lock(hdev);
1041
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001042 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001043 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001044 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001045
1046 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001047}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001048
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001049static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1050 struct sk_buff *skb)
1051{
1052 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1053
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001054 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001055
1056 if (rp->status)
1057 return;
1058
1059 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1060 hdev->le_pkts = rp->le_max_pkt;
1061
1062 hdev->le_cnt = hdev->le_pkts;
1063
1064 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1065
1066 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1067}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001068
Johan Hedberga5c29682011-02-19 12:05:57 -03001069static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1070{
1071 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1072
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001073 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001074
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001075 hci_dev_lock(hdev);
1076
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001077 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001078 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1079 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001080
1081 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001082}
1083
1084static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001085 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001086{
1087 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1088
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001089 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001090
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001091 hci_dev_lock(hdev);
1092
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001093 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001094 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001095 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001096
1097 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001098}
1099
Brian Gix1143d452011-11-23 08:28:34 -08001100static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1101{
1102 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1103
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001104 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001105
1106 hci_dev_lock(hdev);
1107
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001108 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001109 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001110 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001111
1112 hci_dev_unlock(hdev);
1113}
1114
1115static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001116 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001117{
1118 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1119
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001120 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001121
1122 hci_dev_lock(hdev);
1123
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001124 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001125 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001126 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001127
1128 hci_dev_unlock(hdev);
1129}
1130
Szymon Jancc35938b2011-03-22 13:12:21 +01001131static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001132 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001133{
1134 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1135
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001136 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001137
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001138 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001139 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001140 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001141 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001142}
1143
Andre Guedes07f7fa52011-12-02 21:13:31 +09001144static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1145{
1146 __u8 status = *((__u8 *) skb->data);
1147
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001148 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001149
1150 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001151
1152 if (status) {
1153 hci_dev_lock(hdev);
1154 mgmt_start_discovery_failed(hdev, status);
1155 hci_dev_unlock(hdev);
1156 return;
1157 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001158}
1159
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001160static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001161 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001162{
1163 struct hci_cp_le_set_scan_enable *cp;
1164 __u8 status = *((__u8 *) skb->data);
1165
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001166 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001167
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001168 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1169 if (!cp)
1170 return;
1171
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001172 switch (cp->enable) {
1173 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001174 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1175
Andre Guedes3fd24152012-02-03 17:48:01 -03001176 if (status) {
1177 hci_dev_lock(hdev);
1178 mgmt_start_discovery_failed(hdev, status);
1179 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001180 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001181 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001182
Andre Guedesd23264a2011-11-25 20:53:38 -03001183 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1184
Andre Guedesa8f13c82011-09-09 18:56:24 -03001185 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001186 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001187 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001188 break;
1189
1190 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001191 if (status) {
1192 hci_dev_lock(hdev);
1193 mgmt_stop_discovery_failed(hdev, status);
1194 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001195 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001196 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001197
Andre Guedesd23264a2011-11-25 20:53:38 -03001198 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1199
Andre Guedesbc3dd332012-03-06 19:37:06 -03001200 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1201 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001202 mgmt_interleaved_discovery(hdev);
1203 } else {
1204 hci_dev_lock(hdev);
1205 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1206 hci_dev_unlock(hdev);
1207 }
1208
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001209 break;
1210
1211 default:
1212 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1213 break;
Andre Guedes35815082011-05-26 16:23:53 -03001214 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001215}
1216
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001217static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1218{
1219 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1220
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001221 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001222
1223 if (rp->status)
1224 return;
1225
1226 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1227}
1228
1229static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1230{
1231 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1232
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001233 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001234
1235 if (rp->status)
1236 return;
1237
1238 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1239}
1240
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001241static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1242 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001243{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001244 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001245 __u8 status = *((__u8 *) skb->data);
1246
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001247 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001248
Johan Hedberg06199cf2012-02-22 16:37:11 +02001249 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001250 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001251 return;
1252
Johan Hedberg8f984df2012-02-28 01:07:22 +02001253 if (!status) {
1254 if (sent->le)
1255 hdev->host_features[0] |= LMP_HOST_LE;
1256 else
1257 hdev->host_features[0] &= ~LMP_HOST_LE;
1258 }
1259
1260 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001261 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001262 mgmt_le_enable_complete(hdev, sent->le, status);
1263
1264 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001265}
1266
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001267static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1268 struct sk_buff *skb)
1269{
1270 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1271
1272 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1273 hdev->name, rp->status, rp->phy_handle);
1274
1275 if (rp->status)
1276 return;
1277
1278 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1279}
1280
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001281static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001282{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001283 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001284
1285 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001286 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001287 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001288 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001289 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001290 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001291 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001292 return;
1293 }
1294
Andre Guedes89352e72011-11-04 14:16:53 -03001295 set_bit(HCI_INQUIRY, &hdev->flags);
1296
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001297 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001298 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001299 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001300}
1301
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001302static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001304 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001307 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001308
1309 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 if (!cp)
1311 return;
1312
1313 hci_dev_lock(hdev);
1314
1315 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1316
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001317 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
1319 if (status) {
1320 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001321 if (status != 0x0c || conn->attempt > 2) {
1322 conn->state = BT_CLOSED;
1323 hci_proto_connect_cfm(conn, status);
1324 hci_conn_del(conn);
1325 } else
1326 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 }
1328 } else {
1329 if (!conn) {
1330 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1331 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001332 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 conn->link_mode |= HCI_LM_MASTER;
1334 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001335 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 }
1337 }
1338
1339 hci_dev_unlock(hdev);
1340}
1341
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001342static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001344 struct hci_cp_add_sco *cp;
1345 struct hci_conn *acl, *sco;
1346 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001348 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001349
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001350 if (!status)
1351 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001353 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1354 if (!cp)
1355 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001357 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001359 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001360
1361 hci_dev_lock(hdev);
1362
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001363 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001364 if (acl) {
1365 sco = acl->link;
1366 if (sco) {
1367 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001368
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001369 hci_proto_connect_cfm(sco, status);
1370 hci_conn_del(sco);
1371 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001372 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001373
1374 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375}
1376
Marcel Holtmannf8558552008-07-14 20:13:49 +02001377static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1378{
1379 struct hci_cp_auth_requested *cp;
1380 struct hci_conn *conn;
1381
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001382 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001383
1384 if (!status)
1385 return;
1386
1387 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1388 if (!cp)
1389 return;
1390
1391 hci_dev_lock(hdev);
1392
1393 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1394 if (conn) {
1395 if (conn->state == BT_CONFIG) {
1396 hci_proto_connect_cfm(conn, status);
1397 hci_conn_put(conn);
1398 }
1399 }
1400
1401 hci_dev_unlock(hdev);
1402}
1403
1404static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1405{
1406 struct hci_cp_set_conn_encrypt *cp;
1407 struct hci_conn *conn;
1408
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001409 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001410
1411 if (!status)
1412 return;
1413
1414 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1415 if (!cp)
1416 return;
1417
1418 hci_dev_lock(hdev);
1419
1420 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1421 if (conn) {
1422 if (conn->state == BT_CONFIG) {
1423 hci_proto_connect_cfm(conn, status);
1424 hci_conn_put(conn);
1425 }
1426 }
1427
1428 hci_dev_unlock(hdev);
1429}
1430
Johan Hedberg127178d2010-11-18 22:22:29 +02001431static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001432 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001433{
Johan Hedberg392599b2010-11-18 22:22:28 +02001434 if (conn->state != BT_CONFIG || !conn->out)
1435 return 0;
1436
Johan Hedberg765c2a92011-01-19 12:06:52 +05301437 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001438 return 0;
1439
1440 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001441 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001442 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1443 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001444 return 0;
1445
Johan Hedberg392599b2010-11-18 22:22:28 +02001446 return 1;
1447}
1448
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001449static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001450 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001451{
1452 struct hci_cp_remote_name_req cp;
1453
1454 memset(&cp, 0, sizeof(cp));
1455
1456 bacpy(&cp.bdaddr, &e->data.bdaddr);
1457 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1458 cp.pscan_mode = e->data.pscan_mode;
1459 cp.clock_offset = e->data.clock_offset;
1460
1461 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1462}
1463
Johan Hedbergb644ba32012-01-17 21:48:47 +02001464static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001465{
1466 struct discovery_state *discov = &hdev->discovery;
1467 struct inquiry_entry *e;
1468
Johan Hedbergb644ba32012-01-17 21:48:47 +02001469 if (list_empty(&discov->resolve))
1470 return false;
1471
1472 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001473 if (!e)
1474 return false;
1475
Johan Hedbergb644ba32012-01-17 21:48:47 +02001476 if (hci_resolve_name(hdev, e) == 0) {
1477 e->name_state = NAME_PENDING;
1478 return true;
1479 }
1480
1481 return false;
1482}
1483
1484static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001485 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001486{
1487 struct discovery_state *discov = &hdev->discovery;
1488 struct inquiry_entry *e;
1489
1490 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001491 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1492 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001493
1494 if (discov->state == DISCOVERY_STOPPED)
1495 return;
1496
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001497 if (discov->state == DISCOVERY_STOPPING)
1498 goto discov_complete;
1499
1500 if (discov->state != DISCOVERY_RESOLVING)
1501 return;
1502
1503 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001504 /* If the device was not found in a list of found devices names of which
1505 * are pending. there is no need to continue resolving a next name as it
1506 * will be done upon receiving another Remote Name Request Complete
1507 * Event */
1508 if (!e)
1509 return;
1510
1511 list_del(&e->list);
1512 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001513 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001514 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1515 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001516 } else {
1517 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001518 }
1519
Johan Hedbergb644ba32012-01-17 21:48:47 +02001520 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001521 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001522
1523discov_complete:
1524 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1525}
1526
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001527static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1528{
Johan Hedberg127178d2010-11-18 22:22:29 +02001529 struct hci_cp_remote_name_req *cp;
1530 struct hci_conn *conn;
1531
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001532 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001533
1534 /* If successful wait for the name req complete event before
1535 * checking for the need to do authentication */
1536 if (!status)
1537 return;
1538
1539 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1540 if (!cp)
1541 return;
1542
1543 hci_dev_lock(hdev);
1544
1545 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001546
1547 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1548 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1549
Johan Hedberg79c6c702011-04-28 11:28:55 -07001550 if (!conn)
1551 goto unlock;
1552
1553 if (!hci_outgoing_auth_needed(hdev, conn))
1554 goto unlock;
1555
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001556 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001557 struct hci_cp_auth_requested cp;
1558 cp.handle = __cpu_to_le16(conn->handle);
1559 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1560 }
1561
Johan Hedberg79c6c702011-04-28 11:28:55 -07001562unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001563 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001564}
1565
Marcel Holtmann769be972008-07-14 20:13:49 +02001566static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1567{
1568 struct hci_cp_read_remote_features *cp;
1569 struct hci_conn *conn;
1570
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001571 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001572
1573 if (!status)
1574 return;
1575
1576 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1577 if (!cp)
1578 return;
1579
1580 hci_dev_lock(hdev);
1581
1582 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1583 if (conn) {
1584 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001585 hci_proto_connect_cfm(conn, status);
1586 hci_conn_put(conn);
1587 }
1588 }
1589
1590 hci_dev_unlock(hdev);
1591}
1592
1593static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1594{
1595 struct hci_cp_read_remote_ext_features *cp;
1596 struct hci_conn *conn;
1597
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001598 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001599
1600 if (!status)
1601 return;
1602
1603 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1604 if (!cp)
1605 return;
1606
1607 hci_dev_lock(hdev);
1608
1609 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1610 if (conn) {
1611 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001612 hci_proto_connect_cfm(conn, status);
1613 hci_conn_put(conn);
1614 }
1615 }
1616
1617 hci_dev_unlock(hdev);
1618}
1619
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001620static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1621{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001622 struct hci_cp_setup_sync_conn *cp;
1623 struct hci_conn *acl, *sco;
1624 __u16 handle;
1625
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001626 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001627
1628 if (!status)
1629 return;
1630
1631 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1632 if (!cp)
1633 return;
1634
1635 handle = __le16_to_cpu(cp->handle);
1636
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001637 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001638
1639 hci_dev_lock(hdev);
1640
1641 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001642 if (acl) {
1643 sco = acl->link;
1644 if (sco) {
1645 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001646
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001647 hci_proto_connect_cfm(sco, status);
1648 hci_conn_del(sco);
1649 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001650 }
1651
1652 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001653}
1654
1655static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1656{
1657 struct hci_cp_sniff_mode *cp;
1658 struct hci_conn *conn;
1659
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001660 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001661
1662 if (!status)
1663 return;
1664
1665 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1666 if (!cp)
1667 return;
1668
1669 hci_dev_lock(hdev);
1670
1671 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001672 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001673 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001674
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001675 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001676 hci_sco_setup(conn, status);
1677 }
1678
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001679 hci_dev_unlock(hdev);
1680}
1681
1682static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1683{
1684 struct hci_cp_exit_sniff_mode *cp;
1685 struct hci_conn *conn;
1686
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001687 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001688
1689 if (!status)
1690 return;
1691
1692 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1693 if (!cp)
1694 return;
1695
1696 hci_dev_lock(hdev);
1697
1698 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001699 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001700 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001701
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001702 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001703 hci_sco_setup(conn, status);
1704 }
1705
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001706 hci_dev_unlock(hdev);
1707}
1708
Johan Hedberg88c3df12012-02-09 14:27:38 +02001709static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1710{
1711 struct hci_cp_disconnect *cp;
1712 struct hci_conn *conn;
1713
1714 if (!status)
1715 return;
1716
1717 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1718 if (!cp)
1719 return;
1720
1721 hci_dev_lock(hdev);
1722
1723 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1724 if (conn)
1725 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001726 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001727
1728 hci_dev_unlock(hdev);
1729}
1730
Ville Tervofcd89c02011-02-10 22:38:47 -03001731static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1732{
Ville Tervofcd89c02011-02-10 22:38:47 -03001733 struct hci_conn *conn;
1734
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001735 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001736
Ville Tervofcd89c02011-02-10 22:38:47 -03001737 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001738 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001739
Andre Guedes0c95ab72012-07-27 15:10:14 -03001740 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001741 if (!conn) {
1742 hci_dev_unlock(hdev);
1743 return;
1744 }
1745
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001746 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001747
1748 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001749 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001750 conn->dst_type, status);
1751 hci_proto_connect_cfm(conn, status);
1752 hci_conn_del(conn);
1753
1754 hci_dev_unlock(hdev);
1755 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001756}
1757
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001758static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1759{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001760 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001761}
1762
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001763static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1764{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001765 struct hci_cp_create_phy_link *cp;
1766
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001767 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001768
1769 if (status)
1770 return;
1771
1772 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1773 if (!cp)
1774 return;
1775
1776 amp_write_remote_assoc(hdev, cp->phy_handle);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001777}
1778
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001779static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1780{
1781 struct hci_cp_accept_phy_link *cp;
1782
1783 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1784
1785 if (status)
1786 return;
1787
1788 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1789 if (!cp)
1790 return;
1791
1792 amp_write_remote_assoc(hdev, cp->phy_handle);
1793}
1794
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001795static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001796{
1797 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001798 struct discovery_state *discov = &hdev->discovery;
1799 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001800
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001801 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001802
Johan Hedberg23bb5762010-12-21 23:01:27 +02001803 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001804
1805 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001806
1807 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1808 return;
1809
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001810 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001811 return;
1812
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001813 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001814
Andre Guedes343f9352012-02-17 20:39:37 -03001815 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001816 goto unlock;
1817
1818 if (list_empty(&discov->resolve)) {
1819 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1820 goto unlock;
1821 }
1822
1823 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1824 if (e && hci_resolve_name(hdev, e) == 0) {
1825 e->name_state = NAME_PENDING;
1826 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1827 } else {
1828 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1829 }
1830
1831unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001832 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001833}
1834
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001835static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001837 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001838 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 int num_rsp = *((__u8 *) skb->data);
1840
1841 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1842
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001843 if (!num_rsp)
1844 return;
1845
Andre Guedes1519cc12012-03-21 00:03:38 -03001846 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1847 return;
1848
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001850
Johan Hedberge17acd42011-03-30 23:57:16 +03001851 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001852 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001853
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 bacpy(&data.bdaddr, &info->bdaddr);
1855 data.pscan_rep_mode = info->pscan_rep_mode;
1856 data.pscan_period_mode = info->pscan_period_mode;
1857 data.pscan_mode = info->pscan_mode;
1858 memcpy(data.dev_class, info->dev_class, 3);
1859 data.clock_offset = info->clock_offset;
1860 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001861 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001862
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001863 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001864 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001865 info->dev_class, 0, !name_known, ssp, NULL,
1866 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001868
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 hci_dev_unlock(hdev);
1870}
1871
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001872static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001874 struct hci_ev_conn_complete *ev = (void *) skb->data;
1875 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001877 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001878
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001880
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001881 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001882 if (!conn) {
1883 if (ev->link_type != SCO_LINK)
1884 goto unlock;
1885
1886 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1887 if (!conn)
1888 goto unlock;
1889
1890 conn->type = SCO_LINK;
1891 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001892
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001893 if (!ev->status) {
1894 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001895
1896 if (conn->type == ACL_LINK) {
1897 conn->state = BT_CONFIG;
1898 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001899
1900 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1901 !hci_find_link_key(hdev, &ev->bdaddr))
1902 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1903 else
1904 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001905 } else
1906 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001907
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001908 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001909 hci_conn_add_sysfs(conn);
1910
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001911 if (test_bit(HCI_AUTH, &hdev->flags))
1912 conn->link_mode |= HCI_LM_AUTH;
1913
1914 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1915 conn->link_mode |= HCI_LM_ENCRYPT;
1916
1917 /* Get remote features */
1918 if (conn->type == ACL_LINK) {
1919 struct hci_cp_read_remote_features cp;
1920 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001921 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001922 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001923 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001924
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001925 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001926 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001927 struct hci_cp_change_conn_ptype cp;
1928 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001929 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001930 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1931 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001932 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001933 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001934 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001935 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001936 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001937 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001938 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001939
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001940 if (conn->type == ACL_LINK)
1941 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001942
Marcel Holtmann769be972008-07-14 20:13:49 +02001943 if (ev->status) {
1944 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001945 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001946 } else if (ev->link_type != ACL_LINK)
1947 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001948
1949unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001951
1952 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953}
1954
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001955static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001957 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 int mask = hdev->link_mode;
1959
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001960 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001961 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962
1963 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1964
Szymon Janc138d22e2011-02-17 16:44:23 +01001965 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001966 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001968 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
1971 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001972
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001973 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1974 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001975 memcpy(ie->data.dev_class, ev->dev_class, 3);
1976
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001977 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1978 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001980 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1981 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001982 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 hci_dev_unlock(hdev);
1984 return;
1985 }
1986 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001987
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 memcpy(conn->dev_class, ev->dev_class, 3);
1989 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001990
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 hci_dev_unlock(hdev);
1992
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001993 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1994 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001996 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001998 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1999 cp.role = 0x00; /* Become master */
2000 else
2001 cp.role = 0x01; /* Remain slave */
2002
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002003 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2004 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002005 } else {
2006 struct hci_cp_accept_sync_conn_req cp;
2007
2008 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002009 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002010
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002011 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2012 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2013 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002014 cp.content_format = cpu_to_le16(hdev->voice_setting);
2015 cp.retrans_effort = 0xff;
2016
2017 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002018 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 } else {
2021 /* Connection rejected */
2022 struct hci_cp_reject_conn_req cp;
2023
2024 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002025 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002026 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 }
2028}
2029
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002030static u8 hci_to_mgmt_reason(u8 err)
2031{
2032 switch (err) {
2033 case HCI_ERROR_CONNECTION_TIMEOUT:
2034 return MGMT_DEV_DISCONN_TIMEOUT;
2035 case HCI_ERROR_REMOTE_USER_TERM:
2036 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2037 case HCI_ERROR_REMOTE_POWER_OFF:
2038 return MGMT_DEV_DISCONN_REMOTE;
2039 case HCI_ERROR_LOCAL_HOST_TERM:
2040 return MGMT_DEV_DISCONN_LOCAL_HOST;
2041 default:
2042 return MGMT_DEV_DISCONN_UNKNOWN;
2043 }
2044}
2045
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002046static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002048 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002049 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002051 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 hci_dev_lock(hdev);
2054
Marcel Holtmann04837f62006-07-03 10:02:33 +02002055 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002056 if (!conn)
2057 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002058
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002059 if (ev->status == 0)
2060 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
Johan Hedbergb644ba32012-01-17 21:48:47 +02002062 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002063 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002064 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002065 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002066 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002067 } else {
2068 u8 reason = hci_to_mgmt_reason(ev->reason);
2069
Johan Hedbergafc747a2012-01-15 18:11:07 +02002070 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002071 conn->dst_type, reason);
2072 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002073 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002074
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002075 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302076 if (conn->type == ACL_LINK && conn->flush_key)
2077 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002078 hci_proto_disconn_cfm(conn, ev->reason);
2079 hci_conn_del(conn);
2080 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002081
2082unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 hci_dev_unlock(hdev);
2084}
2085
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002086static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002087{
2088 struct hci_ev_auth_complete *ev = (void *) skb->data;
2089 struct hci_conn *conn;
2090
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002091 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002092
2093 hci_dev_lock(hdev);
2094
2095 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002096 if (!conn)
2097 goto unlock;
2098
2099 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002100 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002101 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002102 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002103 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002104 conn->link_mode |= HCI_LM_AUTH;
2105 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002106 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002107 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002108 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002109 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002110 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002111
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002112 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2113 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002114
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002115 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002116 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002117 struct hci_cp_set_conn_encrypt cp;
2118 cp.handle = ev->handle;
2119 cp.encrypt = 0x01;
2120 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002121 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002122 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002123 conn->state = BT_CONNECTED;
2124 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002125 hci_conn_put(conn);
2126 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002127 } else {
2128 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002129
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002130 hci_conn_hold(conn);
2131 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2132 hci_conn_put(conn);
2133 }
2134
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002135 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002136 if (!ev->status) {
2137 struct hci_cp_set_conn_encrypt cp;
2138 cp.handle = ev->handle;
2139 cp.encrypt = 0x01;
2140 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002141 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002142 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002143 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002144 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002145 }
2146 }
2147
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002148unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002149 hci_dev_unlock(hdev);
2150}
2151
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002152static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002153{
Johan Hedberg127178d2010-11-18 22:22:29 +02002154 struct hci_ev_remote_name *ev = (void *) skb->data;
2155 struct hci_conn *conn;
2156
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002157 BT_DBG("%s", hdev->name);
2158
2159 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002160
2161 hci_dev_lock(hdev);
2162
2163 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002164
2165 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2166 goto check_auth;
2167
2168 if (ev->status == 0)
2169 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002170 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002171 else
2172 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2173
2174check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002175 if (!conn)
2176 goto unlock;
2177
2178 if (!hci_outgoing_auth_needed(hdev, conn))
2179 goto unlock;
2180
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002181 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002182 struct hci_cp_auth_requested cp;
2183 cp.handle = __cpu_to_le16(conn->handle);
2184 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2185 }
2186
Johan Hedberg79c6c702011-04-28 11:28:55 -07002187unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002188 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002189}
2190
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002191static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002192{
2193 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2194 struct hci_conn *conn;
2195
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002196 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002197
2198 hci_dev_lock(hdev);
2199
2200 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2201 if (conn) {
2202 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002203 if (ev->encrypt) {
2204 /* Encryption implies authentication */
2205 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002206 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002207 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002208 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002209 conn->link_mode &= ~HCI_LM_ENCRYPT;
2210 }
2211
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002212 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002213
Gustavo Padovana7d77232012-05-13 03:20:07 -03002214 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002215 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002216 hci_conn_put(conn);
2217 goto unlock;
2218 }
2219
Marcel Holtmannf8558552008-07-14 20:13:49 +02002220 if (conn->state == BT_CONFIG) {
2221 if (!ev->status)
2222 conn->state = BT_CONNECTED;
2223
2224 hci_proto_connect_cfm(conn, ev->status);
2225 hci_conn_put(conn);
2226 } else
2227 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002228 }
2229
Gustavo Padovana7d77232012-05-13 03:20:07 -03002230unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002231 hci_dev_unlock(hdev);
2232}
2233
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002234static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2235 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002236{
2237 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2238 struct hci_conn *conn;
2239
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002240 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002241
2242 hci_dev_lock(hdev);
2243
2244 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2245 if (conn) {
2246 if (!ev->status)
2247 conn->link_mode |= HCI_LM_SECURE;
2248
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002249 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002250
2251 hci_key_change_cfm(conn, ev->status);
2252 }
2253
2254 hci_dev_unlock(hdev);
2255}
2256
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002257static void hci_remote_features_evt(struct hci_dev *hdev,
2258 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002259{
2260 struct hci_ev_remote_features *ev = (void *) skb->data;
2261 struct hci_conn *conn;
2262
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002263 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002264
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002265 hci_dev_lock(hdev);
2266
2267 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002268 if (!conn)
2269 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002270
Johan Hedbergccd556f2010-11-10 17:11:51 +02002271 if (!ev->status)
2272 memcpy(conn->features, ev->features, 8);
2273
2274 if (conn->state != BT_CONFIG)
2275 goto unlock;
2276
2277 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2278 struct hci_cp_read_remote_ext_features cp;
2279 cp.handle = ev->handle;
2280 cp.page = 0x01;
2281 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002282 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002283 goto unlock;
2284 }
2285
Johan Hedberg671267b2012-05-12 16:11:50 -03002286 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002287 struct hci_cp_remote_name_req cp;
2288 memset(&cp, 0, sizeof(cp));
2289 bacpy(&cp.bdaddr, &conn->dst);
2290 cp.pscan_rep_mode = 0x02;
2291 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002292 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2293 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002294 conn->dst_type, 0, NULL, 0,
2295 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002296
Johan Hedberg127178d2010-11-18 22:22:29 +02002297 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002298 conn->state = BT_CONNECTED;
2299 hci_proto_connect_cfm(conn, ev->status);
2300 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002301 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002302
Johan Hedbergccd556f2010-11-10 17:11:51 +02002303unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002304 hci_dev_unlock(hdev);
2305}
2306
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002307static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002308{
2309 BT_DBG("%s", hdev->name);
2310}
2311
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002312static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2313 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002314{
2315 BT_DBG("%s", hdev->name);
2316}
2317
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002318static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002319{
2320 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2321 __u16 opcode;
2322
2323 skb_pull(skb, sizeof(*ev));
2324
2325 opcode = __le16_to_cpu(ev->opcode);
2326
2327 switch (opcode) {
2328 case HCI_OP_INQUIRY_CANCEL:
2329 hci_cc_inquiry_cancel(hdev, skb);
2330 break;
2331
Andre Guedes4d934832012-03-21 00:03:35 -03002332 case HCI_OP_PERIODIC_INQ:
2333 hci_cc_periodic_inq(hdev, skb);
2334 break;
2335
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002336 case HCI_OP_EXIT_PERIODIC_INQ:
2337 hci_cc_exit_periodic_inq(hdev, skb);
2338 break;
2339
2340 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2341 hci_cc_remote_name_req_cancel(hdev, skb);
2342 break;
2343
2344 case HCI_OP_ROLE_DISCOVERY:
2345 hci_cc_role_discovery(hdev, skb);
2346 break;
2347
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002348 case HCI_OP_READ_LINK_POLICY:
2349 hci_cc_read_link_policy(hdev, skb);
2350 break;
2351
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002352 case HCI_OP_WRITE_LINK_POLICY:
2353 hci_cc_write_link_policy(hdev, skb);
2354 break;
2355
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002356 case HCI_OP_READ_DEF_LINK_POLICY:
2357 hci_cc_read_def_link_policy(hdev, skb);
2358 break;
2359
2360 case HCI_OP_WRITE_DEF_LINK_POLICY:
2361 hci_cc_write_def_link_policy(hdev, skb);
2362 break;
2363
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002364 case HCI_OP_RESET:
2365 hci_cc_reset(hdev, skb);
2366 break;
2367
2368 case HCI_OP_WRITE_LOCAL_NAME:
2369 hci_cc_write_local_name(hdev, skb);
2370 break;
2371
2372 case HCI_OP_READ_LOCAL_NAME:
2373 hci_cc_read_local_name(hdev, skb);
2374 break;
2375
2376 case HCI_OP_WRITE_AUTH_ENABLE:
2377 hci_cc_write_auth_enable(hdev, skb);
2378 break;
2379
2380 case HCI_OP_WRITE_ENCRYPT_MODE:
2381 hci_cc_write_encrypt_mode(hdev, skb);
2382 break;
2383
2384 case HCI_OP_WRITE_SCAN_ENABLE:
2385 hci_cc_write_scan_enable(hdev, skb);
2386 break;
2387
2388 case HCI_OP_READ_CLASS_OF_DEV:
2389 hci_cc_read_class_of_dev(hdev, skb);
2390 break;
2391
2392 case HCI_OP_WRITE_CLASS_OF_DEV:
2393 hci_cc_write_class_of_dev(hdev, skb);
2394 break;
2395
2396 case HCI_OP_READ_VOICE_SETTING:
2397 hci_cc_read_voice_setting(hdev, skb);
2398 break;
2399
2400 case HCI_OP_WRITE_VOICE_SETTING:
2401 hci_cc_write_voice_setting(hdev, skb);
2402 break;
2403
2404 case HCI_OP_HOST_BUFFER_SIZE:
2405 hci_cc_host_buffer_size(hdev, skb);
2406 break;
2407
Marcel Holtmann333140b2008-07-14 20:13:48 +02002408 case HCI_OP_WRITE_SSP_MODE:
2409 hci_cc_write_ssp_mode(hdev, skb);
2410 break;
2411
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002412 case HCI_OP_READ_LOCAL_VERSION:
2413 hci_cc_read_local_version(hdev, skb);
2414 break;
2415
2416 case HCI_OP_READ_LOCAL_COMMANDS:
2417 hci_cc_read_local_commands(hdev, skb);
2418 break;
2419
2420 case HCI_OP_READ_LOCAL_FEATURES:
2421 hci_cc_read_local_features(hdev, skb);
2422 break;
2423
Andre Guedes971e3a42011-06-30 19:20:52 -03002424 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2425 hci_cc_read_local_ext_features(hdev, skb);
2426 break;
2427
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002428 case HCI_OP_READ_BUFFER_SIZE:
2429 hci_cc_read_buffer_size(hdev, skb);
2430 break;
2431
2432 case HCI_OP_READ_BD_ADDR:
2433 hci_cc_read_bd_addr(hdev, skb);
2434 break;
2435
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002436 case HCI_OP_READ_DATA_BLOCK_SIZE:
2437 hci_cc_read_data_block_size(hdev, skb);
2438 break;
2439
Johan Hedberg23bb5762010-12-21 23:01:27 +02002440 case HCI_OP_WRITE_CA_TIMEOUT:
2441 hci_cc_write_ca_timeout(hdev, skb);
2442 break;
2443
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002444 case HCI_OP_READ_FLOW_CONTROL_MODE:
2445 hci_cc_read_flow_control_mode(hdev, skb);
2446 break;
2447
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002448 case HCI_OP_READ_LOCAL_AMP_INFO:
2449 hci_cc_read_local_amp_info(hdev, skb);
2450 break;
2451
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002452 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2453 hci_cc_read_local_amp_assoc(hdev, skb);
2454 break;
2455
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002456 case HCI_OP_DELETE_STORED_LINK_KEY:
2457 hci_cc_delete_stored_link_key(hdev, skb);
2458 break;
2459
Johan Hedbergd5859e22011-01-25 01:19:58 +02002460 case HCI_OP_SET_EVENT_MASK:
2461 hci_cc_set_event_mask(hdev, skb);
2462 break;
2463
2464 case HCI_OP_WRITE_INQUIRY_MODE:
2465 hci_cc_write_inquiry_mode(hdev, skb);
2466 break;
2467
2468 case HCI_OP_READ_INQ_RSP_TX_POWER:
2469 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2470 break;
2471
2472 case HCI_OP_SET_EVENT_FLT:
2473 hci_cc_set_event_flt(hdev, skb);
2474 break;
2475
Johan Hedberg980e1a52011-01-22 06:10:07 +02002476 case HCI_OP_PIN_CODE_REPLY:
2477 hci_cc_pin_code_reply(hdev, skb);
2478 break;
2479
2480 case HCI_OP_PIN_CODE_NEG_REPLY:
2481 hci_cc_pin_code_neg_reply(hdev, skb);
2482 break;
2483
Szymon Jancc35938b2011-03-22 13:12:21 +01002484 case HCI_OP_READ_LOCAL_OOB_DATA:
2485 hci_cc_read_local_oob_data_reply(hdev, skb);
2486 break;
2487
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002488 case HCI_OP_LE_READ_BUFFER_SIZE:
2489 hci_cc_le_read_buffer_size(hdev, skb);
2490 break;
2491
Johan Hedberga5c29682011-02-19 12:05:57 -03002492 case HCI_OP_USER_CONFIRM_REPLY:
2493 hci_cc_user_confirm_reply(hdev, skb);
2494 break;
2495
2496 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2497 hci_cc_user_confirm_neg_reply(hdev, skb);
2498 break;
2499
Brian Gix1143d452011-11-23 08:28:34 -08002500 case HCI_OP_USER_PASSKEY_REPLY:
2501 hci_cc_user_passkey_reply(hdev, skb);
2502 break;
2503
2504 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2505 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002506 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002507
2508 case HCI_OP_LE_SET_SCAN_PARAM:
2509 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002510 break;
2511
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002512 case HCI_OP_LE_SET_SCAN_ENABLE:
2513 hci_cc_le_set_scan_enable(hdev, skb);
2514 break;
2515
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002516 case HCI_OP_LE_LTK_REPLY:
2517 hci_cc_le_ltk_reply(hdev, skb);
2518 break;
2519
2520 case HCI_OP_LE_LTK_NEG_REPLY:
2521 hci_cc_le_ltk_neg_reply(hdev, skb);
2522 break;
2523
Andre Guedesf9b49302011-06-30 19:20:53 -03002524 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2525 hci_cc_write_le_host_supported(hdev, skb);
2526 break;
2527
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002528 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2529 hci_cc_write_remote_amp_assoc(hdev, skb);
2530 break;
2531
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002532 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002533 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002534 break;
2535 }
2536
Ville Tervo6bd32322011-02-16 16:32:41 +02002537 if (ev->opcode != HCI_OP_NOP)
2538 del_timer(&hdev->cmd_timer);
2539
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002540 if (ev->ncmd) {
2541 atomic_set(&hdev->cmd_cnt, 1);
2542 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002543 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002544 }
2545}
2546
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002547static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002548{
2549 struct hci_ev_cmd_status *ev = (void *) skb->data;
2550 __u16 opcode;
2551
2552 skb_pull(skb, sizeof(*ev));
2553
2554 opcode = __le16_to_cpu(ev->opcode);
2555
2556 switch (opcode) {
2557 case HCI_OP_INQUIRY:
2558 hci_cs_inquiry(hdev, ev->status);
2559 break;
2560
2561 case HCI_OP_CREATE_CONN:
2562 hci_cs_create_conn(hdev, ev->status);
2563 break;
2564
2565 case HCI_OP_ADD_SCO:
2566 hci_cs_add_sco(hdev, ev->status);
2567 break;
2568
Marcel Holtmannf8558552008-07-14 20:13:49 +02002569 case HCI_OP_AUTH_REQUESTED:
2570 hci_cs_auth_requested(hdev, ev->status);
2571 break;
2572
2573 case HCI_OP_SET_CONN_ENCRYPT:
2574 hci_cs_set_conn_encrypt(hdev, ev->status);
2575 break;
2576
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002577 case HCI_OP_REMOTE_NAME_REQ:
2578 hci_cs_remote_name_req(hdev, ev->status);
2579 break;
2580
Marcel Holtmann769be972008-07-14 20:13:49 +02002581 case HCI_OP_READ_REMOTE_FEATURES:
2582 hci_cs_read_remote_features(hdev, ev->status);
2583 break;
2584
2585 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2586 hci_cs_read_remote_ext_features(hdev, ev->status);
2587 break;
2588
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002589 case HCI_OP_SETUP_SYNC_CONN:
2590 hci_cs_setup_sync_conn(hdev, ev->status);
2591 break;
2592
2593 case HCI_OP_SNIFF_MODE:
2594 hci_cs_sniff_mode(hdev, ev->status);
2595 break;
2596
2597 case HCI_OP_EXIT_SNIFF_MODE:
2598 hci_cs_exit_sniff_mode(hdev, ev->status);
2599 break;
2600
Johan Hedberg8962ee72011-01-20 12:40:27 +02002601 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002602 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002603 break;
2604
Ville Tervofcd89c02011-02-10 22:38:47 -03002605 case HCI_OP_LE_CREATE_CONN:
2606 hci_cs_le_create_conn(hdev, ev->status);
2607 break;
2608
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002609 case HCI_OP_LE_START_ENC:
2610 hci_cs_le_start_enc(hdev, ev->status);
2611 break;
2612
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002613 case HCI_OP_CREATE_PHY_LINK:
2614 hci_cs_create_phylink(hdev, ev->status);
2615 break;
2616
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002617 case HCI_OP_ACCEPT_PHY_LINK:
2618 hci_cs_accept_phylink(hdev, ev->status);
2619 break;
2620
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002621 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002622 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002623 break;
2624 }
2625
Ville Tervo6bd32322011-02-16 16:32:41 +02002626 if (ev->opcode != HCI_OP_NOP)
2627 del_timer(&hdev->cmd_timer);
2628
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002629 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002630 atomic_set(&hdev->cmd_cnt, 1);
2631 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002632 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002633 }
2634}
2635
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002636static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002637{
2638 struct hci_ev_role_change *ev = (void *) skb->data;
2639 struct hci_conn *conn;
2640
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002641 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002642
2643 hci_dev_lock(hdev);
2644
2645 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2646 if (conn) {
2647 if (!ev->status) {
2648 if (ev->role)
2649 conn->link_mode &= ~HCI_LM_MASTER;
2650 else
2651 conn->link_mode |= HCI_LM_MASTER;
2652 }
2653
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002654 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002655
2656 hci_role_switch_cfm(conn, ev->status, ev->role);
2657 }
2658
2659 hci_dev_unlock(hdev);
2660}
2661
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002662static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002664 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 int i;
2666
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002667 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2668 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2669 return;
2670 }
2671
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002672 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002673 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 BT_DBG("%s bad parameters", hdev->name);
2675 return;
2676 }
2677
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002678 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2679
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002680 for (i = 0; i < ev->num_hndl; i++) {
2681 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 struct hci_conn *conn;
2683 __u16 handle, count;
2684
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002685 handle = __le16_to_cpu(info->handle);
2686 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687
2688 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002689 if (!conn)
2690 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002692 conn->sent -= count;
2693
2694 switch (conn->type) {
2695 case ACL_LINK:
2696 hdev->acl_cnt += count;
2697 if (hdev->acl_cnt > hdev->acl_pkts)
2698 hdev->acl_cnt = hdev->acl_pkts;
2699 break;
2700
2701 case LE_LINK:
2702 if (hdev->le_pkts) {
2703 hdev->le_cnt += count;
2704 if (hdev->le_cnt > hdev->le_pkts)
2705 hdev->le_cnt = hdev->le_pkts;
2706 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002707 hdev->acl_cnt += count;
2708 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 hdev->acl_cnt = hdev->acl_pkts;
2710 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002711 break;
2712
2713 case SCO_LINK:
2714 hdev->sco_cnt += count;
2715 if (hdev->sco_cnt > hdev->sco_pkts)
2716 hdev->sco_cnt = hdev->sco_pkts;
2717 break;
2718
2719 default:
2720 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2721 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 }
2723 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002724
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002725 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726}
2727
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002728static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2729 __u16 handle)
2730{
2731 struct hci_chan *chan;
2732
2733 switch (hdev->dev_type) {
2734 case HCI_BREDR:
2735 return hci_conn_hash_lookup_handle(hdev, handle);
2736 case HCI_AMP:
2737 chan = hci_chan_lookup_handle(hdev, handle);
2738 if (chan)
2739 return chan->conn;
2740 break;
2741 default:
2742 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2743 break;
2744 }
2745
2746 return NULL;
2747}
2748
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002749static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002750{
2751 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2752 int i;
2753
2754 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2755 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2756 return;
2757 }
2758
2759 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002760 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002761 BT_DBG("%s bad parameters", hdev->name);
2762 return;
2763 }
2764
2765 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002766 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002767
2768 for (i = 0; i < ev->num_hndl; i++) {
2769 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002770 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002771 __u16 handle, block_count;
2772
2773 handle = __le16_to_cpu(info->handle);
2774 block_count = __le16_to_cpu(info->blocks);
2775
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002776 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002777 if (!conn)
2778 continue;
2779
2780 conn->sent -= block_count;
2781
2782 switch (conn->type) {
2783 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002784 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002785 hdev->block_cnt += block_count;
2786 if (hdev->block_cnt > hdev->num_blocks)
2787 hdev->block_cnt = hdev->num_blocks;
2788 break;
2789
2790 default:
2791 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2792 break;
2793 }
2794 }
2795
2796 queue_work(hdev->workqueue, &hdev->tx_work);
2797}
2798
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002799static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002801 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002802 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002804 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805
2806 hci_dev_lock(hdev);
2807
Marcel Holtmann04837f62006-07-03 10:02:33 +02002808 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2809 if (conn) {
2810 conn->mode = ev->mode;
2811 conn->interval = __le16_to_cpu(ev->interval);
2812
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002813 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2814 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002815 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002816 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002817 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002818 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002819 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002820
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002821 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002822 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002823 }
2824
2825 hci_dev_unlock(hdev);
2826}
2827
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002828static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002830 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2831 struct hci_conn *conn;
2832
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002833 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002834
2835 hci_dev_lock(hdev);
2836
2837 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002838 if (!conn)
2839 goto unlock;
2840
2841 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002842 hci_conn_hold(conn);
2843 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2844 hci_conn_put(conn);
2845 }
2846
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002847 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002848 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002849 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002850 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002851 u8 secure;
2852
2853 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2854 secure = 1;
2855 else
2856 secure = 0;
2857
Johan Hedberg744cf192011-11-08 20:40:14 +02002858 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002859 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002860
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002861unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002862 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863}
2864
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002865static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002867 struct hci_ev_link_key_req *ev = (void *) skb->data;
2868 struct hci_cp_link_key_reply cp;
2869 struct hci_conn *conn;
2870 struct link_key *key;
2871
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002872 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002873
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002874 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002875 return;
2876
2877 hci_dev_lock(hdev);
2878
2879 key = hci_find_link_key(hdev, &ev->bdaddr);
2880 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002881 BT_DBG("%s link key not found for %pMR", hdev->name,
2882 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002883 goto not_found;
2884 }
2885
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002886 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2887 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002888
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002889 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002890 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002891 BT_DBG("%s ignoring debug key", hdev->name);
2892 goto not_found;
2893 }
2894
2895 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002896 if (conn) {
2897 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002898 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002899 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2900 goto not_found;
2901 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002902
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002903 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002904 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002905 BT_DBG("%s ignoring key unauthenticated for high security",
2906 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002907 goto not_found;
2908 }
2909
2910 conn->key_type = key->type;
2911 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002912 }
2913
2914 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002915 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002916
2917 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2918
2919 hci_dev_unlock(hdev);
2920
2921 return;
2922
2923not_found:
2924 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2925 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926}
2927
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002928static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002930 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2931 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002932 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002933
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002934 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002935
2936 hci_dev_lock(hdev);
2937
2938 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2939 if (conn) {
2940 hci_conn_hold(conn);
2941 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002942 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002943
2944 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2945 conn->key_type = ev->key_type;
2946
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002947 hci_conn_put(conn);
2948 }
2949
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002950 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002951 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002952 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002953
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002954 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955}
2956
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002957static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002958{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002959 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002960 struct hci_conn *conn;
2961
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002962 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002963
2964 hci_dev_lock(hdev);
2965
2966 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 if (conn && !ev->status) {
2968 struct inquiry_entry *ie;
2969
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002970 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2971 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 ie->data.clock_offset = ev->clock_offset;
2973 ie->timestamp = jiffies;
2974 }
2975 }
2976
2977 hci_dev_unlock(hdev);
2978}
2979
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002980static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002981{
2982 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2983 struct hci_conn *conn;
2984
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002985 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002986
2987 hci_dev_lock(hdev);
2988
2989 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2990 if (conn && !ev->status)
2991 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2992
2993 hci_dev_unlock(hdev);
2994}
2995
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002996static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002997{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002998 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002999 struct inquiry_entry *ie;
3000
3001 BT_DBG("%s", hdev->name);
3002
3003 hci_dev_lock(hdev);
3004
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003005 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3006 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003007 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3008 ie->timestamp = jiffies;
3009 }
3010
3011 hci_dev_unlock(hdev);
3012}
3013
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003014static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3015 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003016{
3017 struct inquiry_data data;
3018 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003019 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003020
3021 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3022
3023 if (!num_rsp)
3024 return;
3025
Andre Guedes1519cc12012-03-21 00:03:38 -03003026 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3027 return;
3028
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003029 hci_dev_lock(hdev);
3030
3031 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003032 struct inquiry_info_with_rssi_and_pscan_mode *info;
3033 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003034
Johan Hedberge17acd42011-03-30 23:57:16 +03003035 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003036 bacpy(&data.bdaddr, &info->bdaddr);
3037 data.pscan_rep_mode = info->pscan_rep_mode;
3038 data.pscan_period_mode = info->pscan_period_mode;
3039 data.pscan_mode = info->pscan_mode;
3040 memcpy(data.dev_class, info->dev_class, 3);
3041 data.clock_offset = info->clock_offset;
3042 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003043 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003044
3045 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003046 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003047 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003048 info->dev_class, info->rssi,
3049 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003050 }
3051 } else {
3052 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3053
Johan Hedberge17acd42011-03-30 23:57:16 +03003054 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003055 bacpy(&data.bdaddr, &info->bdaddr);
3056 data.pscan_rep_mode = info->pscan_rep_mode;
3057 data.pscan_period_mode = info->pscan_period_mode;
3058 data.pscan_mode = 0x00;
3059 memcpy(data.dev_class, info->dev_class, 3);
3060 data.clock_offset = info->clock_offset;
3061 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003062 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003063 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003064 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003065 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003066 info->dev_class, info->rssi,
3067 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003068 }
3069 }
3070
3071 hci_dev_unlock(hdev);
3072}
3073
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003074static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3075 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003076{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003077 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3078 struct hci_conn *conn;
3079
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003080 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003081
Marcel Holtmann41a96212008-07-14 20:13:48 +02003082 hci_dev_lock(hdev);
3083
3084 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003085 if (!conn)
3086 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003087
Johan Hedbergccd556f2010-11-10 17:11:51 +02003088 if (!ev->status && ev->page == 0x01) {
3089 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003090
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003091 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3092 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003093 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003094
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003095 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003096 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003097 }
3098
Johan Hedbergccd556f2010-11-10 17:11:51 +02003099 if (conn->state != BT_CONFIG)
3100 goto unlock;
3101
Johan Hedberg671267b2012-05-12 16:11:50 -03003102 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003103 struct hci_cp_remote_name_req cp;
3104 memset(&cp, 0, sizeof(cp));
3105 bacpy(&cp.bdaddr, &conn->dst);
3106 cp.pscan_rep_mode = 0x02;
3107 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003108 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3109 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003110 conn->dst_type, 0, NULL, 0,
3111 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003112
Johan Hedberg127178d2010-11-18 22:22:29 +02003113 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003114 conn->state = BT_CONNECTED;
3115 hci_proto_connect_cfm(conn, ev->status);
3116 hci_conn_put(conn);
3117 }
3118
3119unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003120 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003121}
3122
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003123static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3124 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003125{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003126 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3127 struct hci_conn *conn;
3128
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003129 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003130
3131 hci_dev_lock(hdev);
3132
3133 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003134 if (!conn) {
3135 if (ev->link_type == ESCO_LINK)
3136 goto unlock;
3137
3138 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3139 if (!conn)
3140 goto unlock;
3141
3142 conn->type = SCO_LINK;
3143 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003144
Marcel Holtmann732547f2009-04-19 19:14:14 +02003145 switch (ev->status) {
3146 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003147 conn->handle = __le16_to_cpu(ev->handle);
3148 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003149
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003150 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003151 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003152 break;
3153
Stephen Coe705e5712010-02-16 11:29:44 -05003154 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003155 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003156 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003157 case 0x1f: /* Unspecified error */
3158 if (conn->out && conn->attempt < 2) {
3159 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3160 (hdev->esco_type & EDR_ESCO_MASK);
3161 hci_setup_sync(conn, conn->link->handle);
3162 goto unlock;
3163 }
3164 /* fall through */
3165
3166 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003167 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003168 break;
3169 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003170
3171 hci_proto_connect_cfm(conn, ev->status);
3172 if (ev->status)
3173 hci_conn_del(conn);
3174
3175unlock:
3176 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003177}
3178
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003179static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003180{
3181 BT_DBG("%s", hdev->name);
3182}
3183
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003184static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003185{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003186 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003187
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003188 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003189}
3190
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003191static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3192 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003193{
3194 struct inquiry_data data;
3195 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3196 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303197 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003198
3199 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3200
3201 if (!num_rsp)
3202 return;
3203
Andre Guedes1519cc12012-03-21 00:03:38 -03003204 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3205 return;
3206
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003207 hci_dev_lock(hdev);
3208
Johan Hedberge17acd42011-03-30 23:57:16 +03003209 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003210 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003211
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003212 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003213 data.pscan_rep_mode = info->pscan_rep_mode;
3214 data.pscan_period_mode = info->pscan_period_mode;
3215 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003216 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003217 data.clock_offset = info->clock_offset;
3218 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003219 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003220
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003221 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003222 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003223 sizeof(info->data),
3224 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003225 else
3226 name_known = true;
3227
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003228 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003229 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303230 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003231 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003232 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303233 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003234 }
3235
3236 hci_dev_unlock(hdev);
3237}
3238
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003239static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3240 struct sk_buff *skb)
3241{
3242 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3243 struct hci_conn *conn;
3244
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003245 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003246 __le16_to_cpu(ev->handle));
3247
3248 hci_dev_lock(hdev);
3249
3250 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3251 if (!conn)
3252 goto unlock;
3253
3254 if (!ev->status)
3255 conn->sec_level = conn->pending_sec_level;
3256
3257 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3258
3259 if (ev->status && conn->state == BT_CONNECTED) {
3260 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3261 hci_conn_put(conn);
3262 goto unlock;
3263 }
3264
3265 if (conn->state == BT_CONFIG) {
3266 if (!ev->status)
3267 conn->state = BT_CONNECTED;
3268
3269 hci_proto_connect_cfm(conn, ev->status);
3270 hci_conn_put(conn);
3271 } else {
3272 hci_auth_cfm(conn, ev->status);
3273
3274 hci_conn_hold(conn);
3275 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3276 hci_conn_put(conn);
3277 }
3278
3279unlock:
3280 hci_dev_unlock(hdev);
3281}
3282
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003283static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003284{
3285 /* If remote requests dedicated bonding follow that lead */
3286 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3287 /* If both remote and local IO capabilities allow MITM
3288 * protection then require it, otherwise don't */
3289 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3290 return 0x02;
3291 else
3292 return 0x03;
3293 }
3294
3295 /* If remote requests no-bonding follow that lead */
3296 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003297 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003298
3299 return conn->auth_type;
3300}
3301
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003302static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003303{
3304 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3305 struct hci_conn *conn;
3306
3307 BT_DBG("%s", hdev->name);
3308
3309 hci_dev_lock(hdev);
3310
3311 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003312 if (!conn)
3313 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003314
Johan Hedberg03b555e2011-01-04 15:40:05 +02003315 hci_conn_hold(conn);
3316
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003317 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003318 goto unlock;
3319
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003320 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003321 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003322 struct hci_cp_io_capability_reply cp;
3323
3324 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303325 /* Change the IO capability from KeyboardDisplay
3326 * to DisplayYesNo as it is not supported by BT spec. */
3327 cp.capability = (conn->io_capability == 0x04) ?
3328 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003329 conn->auth_type = hci_get_auth_req(conn);
3330 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003331
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003332 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3333 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003334 cp.oob_data = 0x01;
3335 else
3336 cp.oob_data = 0x00;
3337
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003338 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003339 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003340 } else {
3341 struct hci_cp_io_capability_neg_reply cp;
3342
3343 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003344 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003345
3346 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003347 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003348 }
3349
3350unlock:
3351 hci_dev_unlock(hdev);
3352}
3353
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003354static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003355{
3356 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3357 struct hci_conn *conn;
3358
3359 BT_DBG("%s", hdev->name);
3360
3361 hci_dev_lock(hdev);
3362
3363 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3364 if (!conn)
3365 goto unlock;
3366
Johan Hedberg03b555e2011-01-04 15:40:05 +02003367 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003368 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003369 if (ev->oob_data)
3370 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003371
3372unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003373 hci_dev_unlock(hdev);
3374}
3375
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003376static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3377 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003378{
3379 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003380 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003381 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003382
3383 BT_DBG("%s", hdev->name);
3384
3385 hci_dev_lock(hdev);
3386
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003387 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003388 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003389
Johan Hedberg7a828902011-04-28 11:28:53 -07003390 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3391 if (!conn)
3392 goto unlock;
3393
3394 loc_mitm = (conn->auth_type & 0x01);
3395 rem_mitm = (conn->remote_auth & 0x01);
3396
3397 /* If we require MITM but the remote device can't provide that
3398 * (it has NoInputNoOutput) then reject the confirmation
3399 * request. The only exception is when we're dedicated bonding
3400 * initiators (connect_cfm_cb set) since then we always have the MITM
3401 * bit set. */
3402 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3403 BT_DBG("Rejecting request: remote device can't provide MITM");
3404 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003405 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003406 goto unlock;
3407 }
3408
3409 /* If no side requires MITM protection; auto-accept */
3410 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003411 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003412
3413 /* If we're not the initiators request authorization to
3414 * proceed from user space (mgmt_user_confirm with
3415 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003416 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003417 BT_DBG("Confirming auto-accept as acceptor");
3418 confirm_hint = 1;
3419 goto confirm;
3420 }
3421
Johan Hedberg9f616562011-04-28 11:28:54 -07003422 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003423 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003424
3425 if (hdev->auto_accept_delay > 0) {
3426 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3427 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3428 goto unlock;
3429 }
3430
Johan Hedberg7a828902011-04-28 11:28:53 -07003431 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003432 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003433 goto unlock;
3434 }
3435
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003436confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003437 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003438 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003439
3440unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003441 hci_dev_unlock(hdev);
3442}
3443
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003444static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3445 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003446{
3447 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3448
3449 BT_DBG("%s", hdev->name);
3450
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003451 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003452 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003453}
3454
Johan Hedberg92a25252012-09-06 18:39:26 +03003455static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3456 struct sk_buff *skb)
3457{
3458 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3459 struct hci_conn *conn;
3460
3461 BT_DBG("%s", hdev->name);
3462
3463 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3464 if (!conn)
3465 return;
3466
3467 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3468 conn->passkey_entered = 0;
3469
3470 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3471 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3472 conn->dst_type, conn->passkey_notify,
3473 conn->passkey_entered);
3474}
3475
3476static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3477{
3478 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3479 struct hci_conn *conn;
3480
3481 BT_DBG("%s", hdev->name);
3482
3483 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3484 if (!conn)
3485 return;
3486
3487 switch (ev->type) {
3488 case HCI_KEYPRESS_STARTED:
3489 conn->passkey_entered = 0;
3490 return;
3491
3492 case HCI_KEYPRESS_ENTERED:
3493 conn->passkey_entered++;
3494 break;
3495
3496 case HCI_KEYPRESS_ERASED:
3497 conn->passkey_entered--;
3498 break;
3499
3500 case HCI_KEYPRESS_CLEARED:
3501 conn->passkey_entered = 0;
3502 break;
3503
3504 case HCI_KEYPRESS_COMPLETED:
3505 return;
3506 }
3507
3508 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3509 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3510 conn->dst_type, conn->passkey_notify,
3511 conn->passkey_entered);
3512}
3513
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003514static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3515 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003516{
3517 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3518 struct hci_conn *conn;
3519
3520 BT_DBG("%s", hdev->name);
3521
3522 hci_dev_lock(hdev);
3523
3524 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003525 if (!conn)
3526 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003527
Johan Hedberg2a611692011-02-19 12:06:00 -03003528 /* To avoid duplicate auth_failed events to user space we check
3529 * the HCI_CONN_AUTH_PEND flag which will be set if we
3530 * initiated the authentication. A traditional auth_complete
3531 * event gets always produced as initiator and is also mapped to
3532 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003533 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003534 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003535 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003536
3537 hci_conn_put(conn);
3538
3539unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003540 hci_dev_unlock(hdev);
3541}
3542
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003543static void hci_remote_host_features_evt(struct hci_dev *hdev,
3544 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003545{
3546 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3547 struct inquiry_entry *ie;
3548
3549 BT_DBG("%s", hdev->name);
3550
3551 hci_dev_lock(hdev);
3552
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003553 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3554 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003555 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003556
3557 hci_dev_unlock(hdev);
3558}
3559
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003560static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3561 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003562{
3563 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3564 struct oob_data *data;
3565
3566 BT_DBG("%s", hdev->name);
3567
3568 hci_dev_lock(hdev);
3569
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003570 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003571 goto unlock;
3572
Szymon Janc2763eda2011-03-22 13:12:22 +01003573 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3574 if (data) {
3575 struct hci_cp_remote_oob_data_reply cp;
3576
3577 bacpy(&cp.bdaddr, &ev->bdaddr);
3578 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3579 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3580
3581 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003582 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003583 } else {
3584 struct hci_cp_remote_oob_data_neg_reply cp;
3585
3586 bacpy(&cp.bdaddr, &ev->bdaddr);
3587 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003588 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003589 }
3590
Szymon Jance1ba1f12011-04-06 13:01:59 +02003591unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003592 hci_dev_unlock(hdev);
3593}
3594
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003595static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003596{
3597 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3598 struct hci_conn *conn;
3599
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003600 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003601
3602 hci_dev_lock(hdev);
3603
Andre Guedesb47a09b2012-07-27 15:10:15 -03003604 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003605 if (!conn) {
3606 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3607 if (!conn) {
3608 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003609 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003610 }
Andre Guedes29b79882011-05-31 14:20:54 -03003611
3612 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003613
3614 if (ev->role == LE_CONN_ROLE_MASTER) {
3615 conn->out = true;
3616 conn->link_mode |= HCI_LM_MASTER;
3617 }
Ville Tervob62f3282011-02-10 22:38:50 -03003618 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003619
Andre Guedescd17dec2012-07-27 15:10:16 -03003620 if (ev->status) {
3621 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3622 conn->dst_type, ev->status);
3623 hci_proto_connect_cfm(conn, ev->status);
3624 conn->state = BT_CLOSED;
3625 hci_conn_del(conn);
3626 goto unlock;
3627 }
3628
Johan Hedbergb644ba32012-01-17 21:48:47 +02003629 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3630 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003631 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003632
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003633 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003634 conn->handle = __le16_to_cpu(ev->handle);
3635 conn->state = BT_CONNECTED;
3636
3637 hci_conn_hold_device(conn);
3638 hci_conn_add_sysfs(conn);
3639
3640 hci_proto_connect_cfm(conn, ev->status);
3641
3642unlock:
3643 hci_dev_unlock(hdev);
3644}
3645
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003646static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003647{
Andre Guedese95beb42011-09-26 20:48:35 -03003648 u8 num_reports = skb->data[0];
3649 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003650 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003651
3652 hci_dev_lock(hdev);
3653
Andre Guedese95beb42011-09-26 20:48:35 -03003654 while (num_reports--) {
3655 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003656
Andre Guedes3c9e9192012-01-10 18:20:50 -03003657 rssi = ev->data[ev->length];
3658 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003659 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003660
Andre Guedese95beb42011-09-26 20:48:35 -03003661 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003662 }
3663
3664 hci_dev_unlock(hdev);
3665}
3666
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003667static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003668{
3669 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3670 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003671 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003672 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003673 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003674
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003675 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003676
3677 hci_dev_lock(hdev);
3678
3679 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003680 if (conn == NULL)
3681 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003682
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003683 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3684 if (ltk == NULL)
3685 goto not_found;
3686
3687 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003688 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003689
3690 if (ltk->authenticated)
3691 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003692
3693 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3694
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003695 if (ltk->type & HCI_SMP_STK) {
3696 list_del(&ltk->list);
3697 kfree(ltk);
3698 }
3699
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003700 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003701
3702 return;
3703
3704not_found:
3705 neg.handle = ev->handle;
3706 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3707 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003708}
3709
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003710static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003711{
3712 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3713
3714 skb_pull(skb, sizeof(*le_ev));
3715
3716 switch (le_ev->subevent) {
3717 case HCI_EV_LE_CONN_COMPLETE:
3718 hci_le_conn_complete_evt(hdev, skb);
3719 break;
3720
Andre Guedes9aa04c92011-05-26 16:23:51 -03003721 case HCI_EV_LE_ADVERTISING_REPORT:
3722 hci_le_adv_report_evt(hdev, skb);
3723 break;
3724
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003725 case HCI_EV_LE_LTK_REQ:
3726 hci_le_ltk_request_evt(hdev, skb);
3727 break;
3728
Ville Tervofcd89c02011-02-10 22:38:47 -03003729 default:
3730 break;
3731 }
3732}
3733
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003734static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3735{
3736 struct hci_ev_channel_selected *ev = (void *) skb->data;
3737 struct hci_conn *hcon;
3738
3739 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3740
3741 skb_pull(skb, sizeof(*ev));
3742
3743 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3744 if (!hcon)
3745 return;
3746
3747 amp_read_loc_assoc_final_data(hdev, hcon);
3748}
3749
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3751{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003752 struct hci_event_hdr *hdr = (void *) skb->data;
3753 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754
3755 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3756
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003757 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 case HCI_EV_INQUIRY_COMPLETE:
3759 hci_inquiry_complete_evt(hdev, skb);
3760 break;
3761
3762 case HCI_EV_INQUIRY_RESULT:
3763 hci_inquiry_result_evt(hdev, skb);
3764 break;
3765
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003766 case HCI_EV_CONN_COMPLETE:
3767 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003768 break;
3769
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 case HCI_EV_CONN_REQUEST:
3771 hci_conn_request_evt(hdev, skb);
3772 break;
3773
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 case HCI_EV_DISCONN_COMPLETE:
3775 hci_disconn_complete_evt(hdev, skb);
3776 break;
3777
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 case HCI_EV_AUTH_COMPLETE:
3779 hci_auth_complete_evt(hdev, skb);
3780 break;
3781
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003782 case HCI_EV_REMOTE_NAME:
3783 hci_remote_name_evt(hdev, skb);
3784 break;
3785
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 case HCI_EV_ENCRYPT_CHANGE:
3787 hci_encrypt_change_evt(hdev, skb);
3788 break;
3789
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003790 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3791 hci_change_link_key_complete_evt(hdev, skb);
3792 break;
3793
3794 case HCI_EV_REMOTE_FEATURES:
3795 hci_remote_features_evt(hdev, skb);
3796 break;
3797
3798 case HCI_EV_REMOTE_VERSION:
3799 hci_remote_version_evt(hdev, skb);
3800 break;
3801
3802 case HCI_EV_QOS_SETUP_COMPLETE:
3803 hci_qos_setup_complete_evt(hdev, skb);
3804 break;
3805
3806 case HCI_EV_CMD_COMPLETE:
3807 hci_cmd_complete_evt(hdev, skb);
3808 break;
3809
3810 case HCI_EV_CMD_STATUS:
3811 hci_cmd_status_evt(hdev, skb);
3812 break;
3813
3814 case HCI_EV_ROLE_CHANGE:
3815 hci_role_change_evt(hdev, skb);
3816 break;
3817
3818 case HCI_EV_NUM_COMP_PKTS:
3819 hci_num_comp_pkts_evt(hdev, skb);
3820 break;
3821
3822 case HCI_EV_MODE_CHANGE:
3823 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 break;
3825
3826 case HCI_EV_PIN_CODE_REQ:
3827 hci_pin_code_request_evt(hdev, skb);
3828 break;
3829
3830 case HCI_EV_LINK_KEY_REQ:
3831 hci_link_key_request_evt(hdev, skb);
3832 break;
3833
3834 case HCI_EV_LINK_KEY_NOTIFY:
3835 hci_link_key_notify_evt(hdev, skb);
3836 break;
3837
3838 case HCI_EV_CLOCK_OFFSET:
3839 hci_clock_offset_evt(hdev, skb);
3840 break;
3841
Marcel Holtmanna8746412008-07-14 20:13:46 +02003842 case HCI_EV_PKT_TYPE_CHANGE:
3843 hci_pkt_type_change_evt(hdev, skb);
3844 break;
3845
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003846 case HCI_EV_PSCAN_REP_MODE:
3847 hci_pscan_rep_mode_evt(hdev, skb);
3848 break;
3849
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003850 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3851 hci_inquiry_result_with_rssi_evt(hdev, skb);
3852 break;
3853
3854 case HCI_EV_REMOTE_EXT_FEATURES:
3855 hci_remote_ext_features_evt(hdev, skb);
3856 break;
3857
3858 case HCI_EV_SYNC_CONN_COMPLETE:
3859 hci_sync_conn_complete_evt(hdev, skb);
3860 break;
3861
3862 case HCI_EV_SYNC_CONN_CHANGED:
3863 hci_sync_conn_changed_evt(hdev, skb);
3864 break;
3865
Marcel Holtmann04837f62006-07-03 10:02:33 +02003866 case HCI_EV_SNIFF_SUBRATE:
3867 hci_sniff_subrate_evt(hdev, skb);
3868 break;
3869
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003870 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3871 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 break;
3873
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003874 case HCI_EV_KEY_REFRESH_COMPLETE:
3875 hci_key_refresh_complete_evt(hdev, skb);
3876 break;
3877
Marcel Holtmann04936842008-07-14 20:13:48 +02003878 case HCI_EV_IO_CAPA_REQUEST:
3879 hci_io_capa_request_evt(hdev, skb);
3880 break;
3881
Johan Hedberg03b555e2011-01-04 15:40:05 +02003882 case HCI_EV_IO_CAPA_REPLY:
3883 hci_io_capa_reply_evt(hdev, skb);
3884 break;
3885
Johan Hedberga5c29682011-02-19 12:05:57 -03003886 case HCI_EV_USER_CONFIRM_REQUEST:
3887 hci_user_confirm_request_evt(hdev, skb);
3888 break;
3889
Brian Gix1143d452011-11-23 08:28:34 -08003890 case HCI_EV_USER_PASSKEY_REQUEST:
3891 hci_user_passkey_request_evt(hdev, skb);
3892 break;
3893
Johan Hedberg92a25252012-09-06 18:39:26 +03003894 case HCI_EV_USER_PASSKEY_NOTIFY:
3895 hci_user_passkey_notify_evt(hdev, skb);
3896 break;
3897
3898 case HCI_EV_KEYPRESS_NOTIFY:
3899 hci_keypress_notify_evt(hdev, skb);
3900 break;
3901
Marcel Holtmann04936842008-07-14 20:13:48 +02003902 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3903 hci_simple_pair_complete_evt(hdev, skb);
3904 break;
3905
Marcel Holtmann41a96212008-07-14 20:13:48 +02003906 case HCI_EV_REMOTE_HOST_FEATURES:
3907 hci_remote_host_features_evt(hdev, skb);
3908 break;
3909
Ville Tervofcd89c02011-02-10 22:38:47 -03003910 case HCI_EV_LE_META:
3911 hci_le_meta_evt(hdev, skb);
3912 break;
3913
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003914 case HCI_EV_CHANNEL_SELECTED:
3915 hci_chan_selected_evt(hdev, skb);
3916 break;
3917
Szymon Janc2763eda2011-03-22 13:12:22 +01003918 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3919 hci_remote_oob_data_request_evt(hdev, skb);
3920 break;
3921
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003922 case HCI_EV_NUM_COMP_BLOCKS:
3923 hci_num_comp_blocks_evt(hdev, skb);
3924 break;
3925
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003926 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003927 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 break;
3929 }
3930
3931 kfree_skb(skb);
3932 hdev->stat.evt_rx++;
3933}