blob: d2c45591f06d01afce9ae4b936938bc579c32a6f [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);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300443 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200444
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 Hedberg5ed8eb22012-10-25 00:09:51 +0300451 if (!status) {
452 if (sent->mode)
453 hdev->host_features[0] |= LMP_HOST_SSP;
454 else
455 hdev->host_features[0] &= ~LMP_HOST_SSP;
456 }
457
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200458 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300459 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200460 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300461 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200462 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
463 else
464 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
465 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200466}
467
Johan Hedbergd5859e22011-01-25 01:19:58 +0200468static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
469{
Johan Hedberg976eb202012-10-24 21:12:01 +0300470 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200471 return 2;
472
Johan Hedberg976eb202012-10-24 21:12:01 +0300473 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200474 return 1;
475
476 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300477 hdev->lmp_subver == 0x0757)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200478 return 1;
479
480 if (hdev->manufacturer == 15) {
481 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
482 return 1;
483 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
484 return 1;
485 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
486 return 1;
487 }
488
489 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -0300490 hdev->lmp_subver == 0x1805)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200491 return 1;
492
493 return 0;
494}
495
496static void hci_setup_inquiry_mode(struct hci_dev *hdev)
497{
498 u8 mode;
499
500 mode = hci_get_inquiry_mode(hdev);
501
502 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
503}
504
505static void hci_setup_event_mask(struct hci_dev *hdev)
506{
507 /* The second byte is 0xff instead of 0x9f (two reserved bits
508 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
509 * command otherwise */
510 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
511
Ville Tervo6de6c182011-05-27 11:16:21 +0300512 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
513 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200514 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300515 return;
516
Johan Hedberge1171e82012-10-19 20:57:45 +0300517 if (lmp_bredr_capable(hdev)) {
518 events[4] |= 0x01; /* Flow Specification Complete */
519 events[4] |= 0x02; /* Inquiry Result with RSSI */
520 events[4] |= 0x04; /* Read Remote Extended Features Complete */
521 events[5] |= 0x08; /* Synchronous Connection Complete */
522 events[5] |= 0x10; /* Synchronous Connection Changed */
523 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200524
Johan Hedberg976eb202012-10-24 21:12:01 +0300525 if (lmp_inq_rssi_capable(hdev))
Johan Hedberga24299e2012-04-26 09:47:46 +0300526 events[4] |= 0x02; /* Inquiry Result with RSSI */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200527
Andre Guedes999dcd12012-07-24 15:03:52 -0300528 if (lmp_sniffsubr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200529 events[5] |= 0x20; /* Sniff Subrating */
530
Johan Hedberg976eb202012-10-24 21:12:01 +0300531 if (lmp_pause_enc_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200532 events[5] |= 0x80; /* Encryption Key Refresh Complete */
533
Johan Hedberg976eb202012-10-24 21:12:01 +0300534 if (lmp_ext_inq_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200535 events[5] |= 0x40; /* Extended Inquiry Result */
536
Andre Guedesc58e8102012-07-24 15:03:53 -0300537 if (lmp_no_flush_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200538 events[7] |= 0x01; /* Enhanced Flush Complete */
539
Johan Hedberg976eb202012-10-24 21:12:01 +0300540 if (lmp_lsto_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200541 events[6] |= 0x80; /* Link Supervision Timeout Changed */
542
Andre Guedes9a1a1992012-07-24 15:03:48 -0300543 if (lmp_ssp_capable(hdev)) {
Johan Hedbergd5859e22011-01-25 01:19:58 +0200544 events[6] |= 0x01; /* IO Capability Request */
545 events[6] |= 0x02; /* IO Capability Response */
546 events[6] |= 0x04; /* User Confirmation Request */
547 events[6] |= 0x08; /* User Passkey Request */
548 events[6] |= 0x10; /* Remote OOB Data Request */
549 events[6] |= 0x20; /* Simple Pairing Complete */
550 events[7] |= 0x04; /* User Passkey Notification */
551 events[7] |= 0x08; /* Keypress Notification */
552 events[7] |= 0x10; /* Remote Host Supported
553 * Features Notification */
554 }
555
Andre Guedesc383ddc2012-07-24 15:03:47 -0300556 if (lmp_le_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200557 events[7] |= 0x20; /* LE Meta-Event */
558
559 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
Johan Hedberge36b04c2012-10-19 20:57:47 +0300560
561 if (lmp_le_capable(hdev)) {
562 memset(events, 0, sizeof(events));
563 events[0] = 0x1f;
564 hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
565 sizeof(events), events);
566 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200567}
568
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200569static void bredr_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300570{
571 struct hci_cp_delete_stored_link_key cp;
572 __le16 param;
573 __u8 flt_type;
574
575 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
576 hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
577
578 /* Read Class of Device */
579 hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
580
581 /* Read Local Name */
582 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
583
584 /* Read Voice Setting */
585 hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
586
587 /* Clear Event Filters */
588 flt_type = HCI_FLT_CLEAR_ALL;
589 hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
590
591 /* Connection accept timeout ~20 secs */
592 param = __constant_cpu_to_le16(0x7d00);
593 hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
594
595 bacpy(&cp.bdaddr, BDADDR_ANY);
596 cp.delete_all = 1;
597 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
598}
599
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200600static void le_setup(struct hci_dev *hdev)
Johan Hedberge1171e82012-10-19 20:57:45 +0300601{
602 /* Read LE Buffer Size */
603 hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
Johan Hedberg8fa19092012-10-19 20:57:49 +0300604
605 /* Read LE Advertising Channel TX Power */
606 hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
Johan Hedberge1171e82012-10-19 20:57:45 +0300607}
608
Johan Hedbergd5859e22011-01-25 01:19:58 +0200609static void hci_setup(struct hci_dev *hdev)
610{
Andrei Emeltchenkoe61ef492011-12-19 16:31:27 +0200611 if (hdev->dev_type != HCI_BREDR)
612 return;
613
Johan Hedberge1171e82012-10-19 20:57:45 +0300614 /* Read BD Address */
615 hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
616
617 if (lmp_bredr_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200618 bredr_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300619
620 if (lmp_le_capable(hdev))
Gustavo Padovan4611dfa2012-10-24 11:18:41 -0200621 le_setup(hdev);
Johan Hedberge1171e82012-10-19 20:57:45 +0300622
Johan Hedbergd5859e22011-01-25 01:19:58 +0200623 hci_setup_event_mask(hdev);
624
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200625 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200626 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
627
Gustavo Padovan6d3c7302012-05-24 03:36:37 -0300628 if (lmp_ssp_capable(hdev)) {
Johan Hedberg54d04db2012-02-22 15:47:48 +0200629 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
630 u8 mode = 0x01;
631 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300632 sizeof(mode), &mode);
Johan Hedberg54d04db2012-02-22 15:47:48 +0200633 } else {
634 struct hci_cp_write_eir cp;
635
636 memset(hdev->eir, 0, sizeof(hdev->eir));
637 memset(&cp, 0, sizeof(cp));
638
639 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
640 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200641 }
642
Johan Hedberg976eb202012-10-24 21:12:01 +0300643 if (lmp_inq_rssi_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200644 hci_setup_inquiry_mode(hdev);
645
Johan Hedberg976eb202012-10-24 21:12:01 +0300646 if (lmp_inq_tx_pwr_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200647 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300648
Johan Hedberg976eb202012-10-24 21:12:01 +0300649 if (lmp_ext_feat_capable(hdev)) {
Andre Guedes971e3a42011-06-30 19:20:52 -0300650 struct hci_cp_read_local_ext_features cp;
651
652 cp.page = 0x01;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300653 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
654 &cp);
Andre Guedes971e3a42011-06-30 19:20:52 -0300655 }
Andre Guedese6100a22011-06-30 19:20:54 -0300656
Johan Hedberg47990ea2012-02-22 11:58:37 +0200657 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
658 u8 enable = 1;
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300659 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
660 &enable);
Johan Hedberg47990ea2012-02-22 11:58:37 +0200661 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200662}
663
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200664static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
665{
666 struct hci_rp_read_local_version *rp = (void *) skb->data;
667
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300668 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200669
670 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200671 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200672
673 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200674 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200675 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200676 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200677 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200678
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300679 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300680 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200681
682 if (test_bit(HCI_INIT, &hdev->flags))
683 hci_setup(hdev);
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200684
685done:
686 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200687}
688
689static void hci_setup_link_policy(struct hci_dev *hdev)
690{
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200691 struct hci_cp_write_def_link_policy cp;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200692 u16 link_policy = 0;
693
Andre Guedes9f92ebf2012-07-24 15:03:50 -0300694 if (lmp_rswitch_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200695 link_policy |= HCI_LP_RSWITCH;
Johan Hedberg976eb202012-10-24 21:12:01 +0300696 if (lmp_hold_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200697 link_policy |= HCI_LP_HOLD;
Andre Guedes6eded102012-07-24 15:03:51 -0300698 if (lmp_sniff_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200699 link_policy |= HCI_LP_SNIFF;
Johan Hedberg976eb202012-10-24 21:12:01 +0300700 if (lmp_park_capable(hdev))
Johan Hedbergd5859e22011-01-25 01:19:58 +0200701 link_policy |= HCI_LP_PARK;
702
Andrei Emeltchenko035100c2012-03-12 15:59:32 +0200703 cp.policy = cpu_to_le16(link_policy);
704 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200705}
706
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300707static void hci_cc_read_local_commands(struct hci_dev *hdev,
708 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200709{
710 struct hci_rp_read_local_commands *rp = (void *) skb->data;
711
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300712 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200713
714 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200715 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200716
717 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200718
719 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
720 hci_setup_link_policy(hdev);
721
722done:
723 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200724}
725
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300726static void hci_cc_read_local_features(struct hci_dev *hdev,
727 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200728{
729 struct hci_rp_read_local_features *rp = (void *) skb->data;
730
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300731 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200732
733 if (rp->status)
734 return;
735
736 memcpy(hdev->features, rp->features, 8);
737
738 /* Adjust default settings according to features
739 * supported by device. */
740
741 if (hdev->features[0] & LMP_3SLOT)
742 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
743
744 if (hdev->features[0] & LMP_5SLOT)
745 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
746
747 if (hdev->features[1] & LMP_HV2) {
748 hdev->pkt_type |= (HCI_HV2);
749 hdev->esco_type |= (ESCO_HV2);
750 }
751
752 if (hdev->features[1] & LMP_HV3) {
753 hdev->pkt_type |= (HCI_HV3);
754 hdev->esco_type |= (ESCO_HV3);
755 }
756
Andre Guedes45db810f2012-07-24 15:03:49 -0300757 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200758 hdev->esco_type |= (ESCO_EV3);
759
760 if (hdev->features[4] & LMP_EV4)
761 hdev->esco_type |= (ESCO_EV4);
762
763 if (hdev->features[4] & LMP_EV5)
764 hdev->esco_type |= (ESCO_EV5);
765
Marcel Holtmannefc76882009-02-06 09:13:37 +0100766 if (hdev->features[5] & LMP_EDR_ESCO_2M)
767 hdev->esco_type |= (ESCO_2EV3);
768
769 if (hdev->features[5] & LMP_EDR_ESCO_3M)
770 hdev->esco_type |= (ESCO_3EV3);
771
772 if (hdev->features[5] & LMP_EDR_3S_ESCO)
773 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
774
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200775 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300776 hdev->features[0], hdev->features[1],
777 hdev->features[2], hdev->features[3],
778 hdev->features[4], hdev->features[5],
779 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200780}
781
Johan Hedberg8f984df2012-02-28 01:07:22 +0200782static void hci_set_le_support(struct hci_dev *hdev)
783{
784 struct hci_cp_write_le_host_supported cp;
785
786 memset(&cp, 0, sizeof(cp));
787
Marcel Holtmann9d428202012-05-03 07:12:31 +0200788 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Johan Hedberg8f984df2012-02-28 01:07:22 +0200789 cp.le = 1;
Johan Hedberg976eb202012-10-24 21:12:01 +0300790 cp.simul = !!lmp_le_br_capable(hdev);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200791 }
792
Johan Hedberg976eb202012-10-24 21:12:01 +0300793 if (cp.le != !!lmp_host_le_capable(hdev))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300794 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
795 &cp);
Johan Hedberg8f984df2012-02-28 01:07:22 +0200796}
797
Andre Guedes971e3a42011-06-30 19:20:52 -0300798static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300799 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300800{
801 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
802
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300803 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300804
805 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200806 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300807
Andre Guedesb5b32b62011-12-30 10:34:04 -0300808 switch (rp->page) {
809 case 0:
810 memcpy(hdev->features, rp->features, 8);
811 break;
812 case 1:
813 memcpy(hdev->host_features, rp->features, 8);
814 break;
815 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300816
Andre Guedesc383ddc2012-07-24 15:03:47 -0300817 if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
Johan Hedberg8f984df2012-02-28 01:07:22 +0200818 hci_set_le_support(hdev);
819
820done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300821 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
822}
823
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200824static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300825 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200826{
827 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
828
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300829 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200830
831 if (rp->status)
832 return;
833
834 hdev->flow_ctl_mode = rp->mode;
835
836 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
837}
838
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200839static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
840{
841 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
842
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300843 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200844
845 if (rp->status)
846 return;
847
848 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
849 hdev->sco_mtu = rp->sco_mtu;
850 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
851 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
852
853 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
854 hdev->sco_mtu = 64;
855 hdev->sco_pkts = 8;
856 }
857
858 hdev->acl_cnt = hdev->acl_pkts;
859 hdev->sco_cnt = hdev->sco_pkts;
860
Gustavo Padovan807deac2012-05-17 00:36:24 -0300861 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
862 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200863}
864
865static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
866{
867 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
868
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300869 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200870
871 if (!rp->status)
872 bacpy(&hdev->bdaddr, &rp->bdaddr);
873
Johan Hedberg23bb5762010-12-21 23:01:27 +0200874 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
875}
876
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200877static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300878 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200879{
880 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
881
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300882 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200883
884 if (rp->status)
885 return;
886
887 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
888 hdev->block_len = __le16_to_cpu(rp->block_len);
889 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
890
891 hdev->block_cnt = hdev->num_blocks;
892
893 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300894 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200895
896 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
897}
898
Johan Hedberg23bb5762010-12-21 23:01:27 +0200899static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
900{
901 __u8 status = *((__u8 *) skb->data);
902
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300903 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200904
905 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200906}
907
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300908static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300909 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300910{
911 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
912
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300913 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300914
915 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300916 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300917
918 hdev->amp_status = rp->amp_status;
919 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
920 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
921 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
922 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
923 hdev->amp_type = rp->amp_type;
924 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
925 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
926 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
927 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
928
929 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300930
931a2mp_rsp:
932 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300933}
934
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300935static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
936 struct sk_buff *skb)
937{
938 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
939 struct amp_assoc *assoc = &hdev->loc_assoc;
940 size_t rem_len, frag_len;
941
942 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
943
944 if (rp->status)
945 goto a2mp_rsp;
946
947 frag_len = skb->len - sizeof(*rp);
948 rem_len = __le16_to_cpu(rp->rem_len);
949
950 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300951 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300952
953 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
954 assoc->offset += frag_len;
955
956 /* Read other fragments */
957 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
958
959 return;
960 }
961
962 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
963 assoc->len = assoc->offset + rem_len;
964 assoc->offset = 0;
965
966a2mp_rsp:
967 /* Send A2MP Rsp when all fragments are received */
968 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300969 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300970}
971
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200972static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300973 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200974{
975 __u8 status = *((__u8 *) skb->data);
976
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300977 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200978
979 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
980}
981
Johan Hedbergd5859e22011-01-25 01:19:58 +0200982static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
983{
984 __u8 status = *((__u8 *) skb->data);
985
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300986 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200987
988 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
989}
990
991static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300992 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200993{
994 __u8 status = *((__u8 *) skb->data);
995
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300996 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200997
998 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
999}
1000
1001static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001002 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +02001003{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001004 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +02001005
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001006 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001007
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001008 if (!rp->status)
1009 hdev->inq_tx_power = rp->tx_power;
1010
1011 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001012}
1013
1014static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1015{
1016 __u8 status = *((__u8 *) skb->data);
1017
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001018 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +02001019
1020 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1021}
1022
Johan Hedberg980e1a52011-01-22 06:10:07 +02001023static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1024{
1025 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1026 struct hci_cp_pin_code_reply *cp;
1027 struct hci_conn *conn;
1028
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001029 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001030
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001031 hci_dev_lock(hdev);
1032
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001033 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001034 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001035
Mikel Astizfa1bd912012-08-09 09:52:29 +02001036 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001037 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001038
1039 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1040 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001041 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001042
1043 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1044 if (conn)
1045 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001046
1047unlock:
1048 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001049}
1050
1051static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1052{
1053 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1054
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001055 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001056
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001057 hci_dev_lock(hdev);
1058
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001059 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001060 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001061 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001062
1063 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001064}
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001065
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001066static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
1067 struct sk_buff *skb)
1068{
1069 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
1070
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001071 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001072
1073 if (rp->status)
1074 return;
1075
1076 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
1077 hdev->le_pkts = rp->le_max_pkt;
1078
1079 hdev->le_cnt = hdev->le_pkts;
1080
1081 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
1082
1083 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
1084}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001085
Johan Hedberg8fa19092012-10-19 20:57:49 +03001086static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
1087 struct sk_buff *skb)
1088{
1089 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
1090
1091 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1092
1093 if (!rp->status)
1094 hdev->adv_tx_power = rp->tx_power;
1095
1096 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
1097}
1098
Johan Hedberge36b04c2012-10-19 20:57:47 +03001099static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1100{
1101 __u8 status = *((__u8 *) skb->data);
1102
1103 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1104
1105 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1106}
1107
Johan Hedberga5c29682011-02-19 12:05:57 -03001108static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1109{
1110 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1111
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001112 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001113
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001114 hci_dev_lock(hdev);
1115
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001116 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001117 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
1118 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001119
1120 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001121}
1122
1123static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001124 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03001125{
1126 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1127
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001128 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -03001129
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001130 hci_dev_lock(hdev);
1131
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001132 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +02001133 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001134 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001135
1136 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001137}
1138
Brian Gix1143d452011-11-23 08:28:34 -08001139static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
1140{
1141 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1142
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001143 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001144
1145 hci_dev_lock(hdev);
1146
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001147 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02001148 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001149 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001150
1151 hci_dev_unlock(hdev);
1152}
1153
1154static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001155 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08001156{
1157 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1158
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001159 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001160
1161 hci_dev_lock(hdev);
1162
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001163 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001164 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001165 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -08001166
1167 hci_dev_unlock(hdev);
1168}
1169
Szymon Jancc35938b2011-03-22 13:12:21 +01001170static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001171 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +01001172{
1173 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1174
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001175 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +01001176
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001177 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001178 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001179 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001180 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001181}
1182
Andre Guedes07f7fa52011-12-02 21:13:31 +09001183static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1184{
1185 __u8 status = *((__u8 *) skb->data);
1186
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001187 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001188
1189 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001190
1191 if (status) {
1192 hci_dev_lock(hdev);
1193 mgmt_start_discovery_failed(hdev, status);
1194 hci_dev_unlock(hdev);
1195 return;
1196 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001197}
1198
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001199static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001200 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001201{
1202 struct hci_cp_le_set_scan_enable *cp;
1203 __u8 status = *((__u8 *) skb->data);
1204
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001205 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001206
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001207 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1208 if (!cp)
1209 return;
1210
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001211 switch (cp->enable) {
1212 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001213 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1214
Andre Guedes3fd24152012-02-03 17:48:01 -03001215 if (status) {
1216 hci_dev_lock(hdev);
1217 mgmt_start_discovery_failed(hdev, status);
1218 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001219 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001220 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001221
Andre Guedesd23264a2011-11-25 20:53:38 -03001222 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1223
Andre Guedesa8f13c82011-09-09 18:56:24 -03001224 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001225 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001226 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001227 break;
1228
1229 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001230 if (status) {
1231 hci_dev_lock(hdev);
1232 mgmt_stop_discovery_failed(hdev, status);
1233 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001234 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001235 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001236
Andre Guedesd23264a2011-11-25 20:53:38 -03001237 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1238
Andre Guedesbc3dd332012-03-06 19:37:06 -03001239 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1240 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001241 mgmt_interleaved_discovery(hdev);
1242 } else {
1243 hci_dev_lock(hdev);
1244 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1245 hci_dev_unlock(hdev);
1246 }
1247
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001248 break;
1249
1250 default:
1251 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1252 break;
Andre Guedes35815082011-05-26 16:23:53 -03001253 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001254}
1255
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001256static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1257{
1258 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1259
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001260 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001261
1262 if (rp->status)
1263 return;
1264
1265 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1266}
1267
1268static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1269{
1270 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1271
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001272 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001273
1274 if (rp->status)
1275 return;
1276
1277 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1278}
1279
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001280static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1281 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001282{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001283 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001284 __u8 status = *((__u8 *) skb->data);
1285
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001286 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001287
Johan Hedberg06199cf2012-02-22 16:37:11 +02001288 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001289 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001290 return;
1291
Johan Hedberg8f984df2012-02-28 01:07:22 +02001292 if (!status) {
1293 if (sent->le)
1294 hdev->host_features[0] |= LMP_HOST_LE;
1295 else
1296 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001297
1298 if (sent->simul)
1299 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1300 else
1301 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001302 }
1303
1304 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001305 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001306 mgmt_le_enable_complete(hdev, sent->le, status);
1307
1308 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001309}
1310
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001311static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1312 struct sk_buff *skb)
1313{
1314 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1315
1316 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1317 hdev->name, rp->status, rp->phy_handle);
1318
1319 if (rp->status)
1320 return;
1321
1322 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1323}
1324
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001325static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001326{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001327 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001328
1329 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001330 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001331 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001332 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001333 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001334 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001335 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001336 return;
1337 }
1338
Andre Guedes89352e72011-11-04 14:16:53 -03001339 set_bit(HCI_INQUIRY, &hdev->flags);
1340
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001341 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001342 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001343 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001344}
1345
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001346static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001348 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001351 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001352
1353 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 if (!cp)
1355 return;
1356
1357 hci_dev_lock(hdev);
1358
1359 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1360
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001361 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363 if (status) {
1364 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001365 if (status != 0x0c || conn->attempt > 2) {
1366 conn->state = BT_CLOSED;
1367 hci_proto_connect_cfm(conn, status);
1368 hci_conn_del(conn);
1369 } else
1370 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 }
1372 } else {
1373 if (!conn) {
1374 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1375 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001376 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 conn->link_mode |= HCI_LM_MASTER;
1378 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001379 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 }
1381 }
1382
1383 hci_dev_unlock(hdev);
1384}
1385
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001386static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001388 struct hci_cp_add_sco *cp;
1389 struct hci_conn *acl, *sco;
1390 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001392 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001393
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001394 if (!status)
1395 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001397 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1398 if (!cp)
1399 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001401 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001403 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001404
1405 hci_dev_lock(hdev);
1406
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001407 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001408 if (acl) {
1409 sco = acl->link;
1410 if (sco) {
1411 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001412
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001413 hci_proto_connect_cfm(sco, status);
1414 hci_conn_del(sco);
1415 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001416 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001417
1418 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419}
1420
Marcel Holtmannf8558552008-07-14 20:13:49 +02001421static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1422{
1423 struct hci_cp_auth_requested *cp;
1424 struct hci_conn *conn;
1425
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001426 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001427
1428 if (!status)
1429 return;
1430
1431 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1432 if (!cp)
1433 return;
1434
1435 hci_dev_lock(hdev);
1436
1437 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1438 if (conn) {
1439 if (conn->state == BT_CONFIG) {
1440 hci_proto_connect_cfm(conn, status);
1441 hci_conn_put(conn);
1442 }
1443 }
1444
1445 hci_dev_unlock(hdev);
1446}
1447
1448static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1449{
1450 struct hci_cp_set_conn_encrypt *cp;
1451 struct hci_conn *conn;
1452
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001453 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001454
1455 if (!status)
1456 return;
1457
1458 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1459 if (!cp)
1460 return;
1461
1462 hci_dev_lock(hdev);
1463
1464 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1465 if (conn) {
1466 if (conn->state == BT_CONFIG) {
1467 hci_proto_connect_cfm(conn, status);
1468 hci_conn_put(conn);
1469 }
1470 }
1471
1472 hci_dev_unlock(hdev);
1473}
1474
Johan Hedberg127178d2010-11-18 22:22:29 +02001475static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001476 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001477{
Johan Hedberg392599b2010-11-18 22:22:28 +02001478 if (conn->state != BT_CONFIG || !conn->out)
1479 return 0;
1480
Johan Hedberg765c2a92011-01-19 12:06:52 +05301481 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001482 return 0;
1483
1484 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001485 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001486 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1487 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001488 return 0;
1489
Johan Hedberg392599b2010-11-18 22:22:28 +02001490 return 1;
1491}
1492
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001493static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001494 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001495{
1496 struct hci_cp_remote_name_req cp;
1497
1498 memset(&cp, 0, sizeof(cp));
1499
1500 bacpy(&cp.bdaddr, &e->data.bdaddr);
1501 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1502 cp.pscan_mode = e->data.pscan_mode;
1503 cp.clock_offset = e->data.clock_offset;
1504
1505 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1506}
1507
Johan Hedbergb644ba32012-01-17 21:48:47 +02001508static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001509{
1510 struct discovery_state *discov = &hdev->discovery;
1511 struct inquiry_entry *e;
1512
Johan Hedbergb644ba32012-01-17 21:48:47 +02001513 if (list_empty(&discov->resolve))
1514 return false;
1515
1516 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001517 if (!e)
1518 return false;
1519
Johan Hedbergb644ba32012-01-17 21:48:47 +02001520 if (hci_resolve_name(hdev, e) == 0) {
1521 e->name_state = NAME_PENDING;
1522 return true;
1523 }
1524
1525 return false;
1526}
1527
1528static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001529 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001530{
1531 struct discovery_state *discov = &hdev->discovery;
1532 struct inquiry_entry *e;
1533
1534 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001535 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1536 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001537
1538 if (discov->state == DISCOVERY_STOPPED)
1539 return;
1540
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001541 if (discov->state == DISCOVERY_STOPPING)
1542 goto discov_complete;
1543
1544 if (discov->state != DISCOVERY_RESOLVING)
1545 return;
1546
1547 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001548 /* If the device was not found in a list of found devices names of which
1549 * are pending. there is no need to continue resolving a next name as it
1550 * will be done upon receiving another Remote Name Request Complete
1551 * Event */
1552 if (!e)
1553 return;
1554
1555 list_del(&e->list);
1556 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001557 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001558 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1559 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001560 } else {
1561 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001562 }
1563
Johan Hedbergb644ba32012-01-17 21:48:47 +02001564 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001565 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001566
1567discov_complete:
1568 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1569}
1570
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001571static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1572{
Johan Hedberg127178d2010-11-18 22:22:29 +02001573 struct hci_cp_remote_name_req *cp;
1574 struct hci_conn *conn;
1575
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001576 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001577
1578 /* If successful wait for the name req complete event before
1579 * checking for the need to do authentication */
1580 if (!status)
1581 return;
1582
1583 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1584 if (!cp)
1585 return;
1586
1587 hci_dev_lock(hdev);
1588
1589 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001590
1591 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1592 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1593
Johan Hedberg79c6c702011-04-28 11:28:55 -07001594 if (!conn)
1595 goto unlock;
1596
1597 if (!hci_outgoing_auth_needed(hdev, conn))
1598 goto unlock;
1599
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001600 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001601 struct hci_cp_auth_requested cp;
1602 cp.handle = __cpu_to_le16(conn->handle);
1603 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1604 }
1605
Johan Hedberg79c6c702011-04-28 11:28:55 -07001606unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001607 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001608}
1609
Marcel Holtmann769be972008-07-14 20:13:49 +02001610static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1611{
1612 struct hci_cp_read_remote_features *cp;
1613 struct hci_conn *conn;
1614
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001615 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001616
1617 if (!status)
1618 return;
1619
1620 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1621 if (!cp)
1622 return;
1623
1624 hci_dev_lock(hdev);
1625
1626 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1627 if (conn) {
1628 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001629 hci_proto_connect_cfm(conn, status);
1630 hci_conn_put(conn);
1631 }
1632 }
1633
1634 hci_dev_unlock(hdev);
1635}
1636
1637static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1638{
1639 struct hci_cp_read_remote_ext_features *cp;
1640 struct hci_conn *conn;
1641
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001642 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001643
1644 if (!status)
1645 return;
1646
1647 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1648 if (!cp)
1649 return;
1650
1651 hci_dev_lock(hdev);
1652
1653 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1654 if (conn) {
1655 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001656 hci_proto_connect_cfm(conn, status);
1657 hci_conn_put(conn);
1658 }
1659 }
1660
1661 hci_dev_unlock(hdev);
1662}
1663
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001664static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1665{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001666 struct hci_cp_setup_sync_conn *cp;
1667 struct hci_conn *acl, *sco;
1668 __u16 handle;
1669
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001670 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001671
1672 if (!status)
1673 return;
1674
1675 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1676 if (!cp)
1677 return;
1678
1679 handle = __le16_to_cpu(cp->handle);
1680
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001681 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001682
1683 hci_dev_lock(hdev);
1684
1685 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001686 if (acl) {
1687 sco = acl->link;
1688 if (sco) {
1689 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001690
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001691 hci_proto_connect_cfm(sco, status);
1692 hci_conn_del(sco);
1693 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001694 }
1695
1696 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001697}
1698
1699static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1700{
1701 struct hci_cp_sniff_mode *cp;
1702 struct hci_conn *conn;
1703
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001704 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001705
1706 if (!status)
1707 return;
1708
1709 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1710 if (!cp)
1711 return;
1712
1713 hci_dev_lock(hdev);
1714
1715 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001716 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001717 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001718
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001719 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001720 hci_sco_setup(conn, status);
1721 }
1722
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001723 hci_dev_unlock(hdev);
1724}
1725
1726static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1727{
1728 struct hci_cp_exit_sniff_mode *cp;
1729 struct hci_conn *conn;
1730
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001731 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001732
1733 if (!status)
1734 return;
1735
1736 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1737 if (!cp)
1738 return;
1739
1740 hci_dev_lock(hdev);
1741
1742 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001743 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001744 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001745
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001746 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001747 hci_sco_setup(conn, status);
1748 }
1749
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001750 hci_dev_unlock(hdev);
1751}
1752
Johan Hedberg88c3df12012-02-09 14:27:38 +02001753static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1754{
1755 struct hci_cp_disconnect *cp;
1756 struct hci_conn *conn;
1757
1758 if (!status)
1759 return;
1760
1761 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1762 if (!cp)
1763 return;
1764
1765 hci_dev_lock(hdev);
1766
1767 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1768 if (conn)
1769 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001770 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001771
1772 hci_dev_unlock(hdev);
1773}
1774
Ville Tervofcd89c02011-02-10 22:38:47 -03001775static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1776{
Ville Tervofcd89c02011-02-10 22:38:47 -03001777 struct hci_conn *conn;
1778
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001779 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001780
Ville Tervofcd89c02011-02-10 22:38:47 -03001781 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001782 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001783
Andre Guedes0c95ab72012-07-27 15:10:14 -03001784 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001785 if (!conn) {
1786 hci_dev_unlock(hdev);
1787 return;
1788 }
1789
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001790 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001791
1792 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001793 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001794 conn->dst_type, status);
1795 hci_proto_connect_cfm(conn, status);
1796 hci_conn_del(conn);
1797
1798 hci_dev_unlock(hdev);
1799 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001800}
1801
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001802static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1803{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001804 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001805}
1806
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001807static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1808{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001809 struct hci_cp_create_phy_link *cp;
1810
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001811 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001812
1813 if (status)
1814 return;
1815
1816 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1817 if (!cp)
1818 return;
1819
1820 amp_write_remote_assoc(hdev, cp->phy_handle);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001821}
1822
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001823static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1824{
1825 struct hci_cp_accept_phy_link *cp;
1826
1827 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1828
1829 if (status)
1830 return;
1831
1832 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1833 if (!cp)
1834 return;
1835
1836 amp_write_remote_assoc(hdev, cp->phy_handle);
1837}
1838
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001839static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001840{
1841 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001842 struct discovery_state *discov = &hdev->discovery;
1843 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001844
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001845 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001846
Johan Hedberg23bb5762010-12-21 23:01:27 +02001847 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001848
1849 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001850
1851 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1852 return;
1853
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001854 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001855 return;
1856
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001857 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001858
Andre Guedes343f9352012-02-17 20:39:37 -03001859 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001860 goto unlock;
1861
1862 if (list_empty(&discov->resolve)) {
1863 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1864 goto unlock;
1865 }
1866
1867 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1868 if (e && hci_resolve_name(hdev, e) == 0) {
1869 e->name_state = NAME_PENDING;
1870 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1871 } else {
1872 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1873 }
1874
1875unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001876 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001877}
1878
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001879static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001881 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001882 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 int num_rsp = *((__u8 *) skb->data);
1884
1885 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1886
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001887 if (!num_rsp)
1888 return;
1889
Andre Guedes1519cc12012-03-21 00:03:38 -03001890 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1891 return;
1892
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001894
Johan Hedberge17acd42011-03-30 23:57:16 +03001895 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001896 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001897
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 bacpy(&data.bdaddr, &info->bdaddr);
1899 data.pscan_rep_mode = info->pscan_rep_mode;
1900 data.pscan_period_mode = info->pscan_period_mode;
1901 data.pscan_mode = info->pscan_mode;
1902 memcpy(data.dev_class, info->dev_class, 3);
1903 data.clock_offset = info->clock_offset;
1904 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001905 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001906
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001907 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001908 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001909 info->dev_class, 0, !name_known, ssp, NULL,
1910 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001912
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 hci_dev_unlock(hdev);
1914}
1915
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001916static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001918 struct hci_ev_conn_complete *ev = (void *) skb->data;
1919 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001921 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001922
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001924
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001925 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001926 if (!conn) {
1927 if (ev->link_type != SCO_LINK)
1928 goto unlock;
1929
1930 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1931 if (!conn)
1932 goto unlock;
1933
1934 conn->type = SCO_LINK;
1935 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001936
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001937 if (!ev->status) {
1938 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001939
1940 if (conn->type == ACL_LINK) {
1941 conn->state = BT_CONFIG;
1942 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001943
1944 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1945 !hci_find_link_key(hdev, &ev->bdaddr))
1946 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1947 else
1948 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001949 } else
1950 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001951
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001952 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001953 hci_conn_add_sysfs(conn);
1954
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001955 if (test_bit(HCI_AUTH, &hdev->flags))
1956 conn->link_mode |= HCI_LM_AUTH;
1957
1958 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1959 conn->link_mode |= HCI_LM_ENCRYPT;
1960
1961 /* Get remote features */
1962 if (conn->type == ACL_LINK) {
1963 struct hci_cp_read_remote_features cp;
1964 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001965 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001966 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001967 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001968
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001969 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001970 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001971 struct hci_cp_change_conn_ptype cp;
1972 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001973 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001974 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1975 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001976 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001977 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001978 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001979 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001980 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001981 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001982 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001983
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001984 if (conn->type == ACL_LINK)
1985 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001986
Marcel Holtmann769be972008-07-14 20:13:49 +02001987 if (ev->status) {
1988 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001989 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001990 } else if (ev->link_type != ACL_LINK)
1991 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001992
1993unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001995
1996 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997}
1998
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001999static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002001 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 int mask = hdev->link_mode;
2003
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002004 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002005 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
2007 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
2008
Szymon Janc138d22e2011-02-17 16:44:23 +01002009 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002010 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002012 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
2015 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002016
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002017 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2018 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02002019 memcpy(ie->data.dev_class, ev->dev_class, 3);
2020
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002021 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
2022 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002024 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2025 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03002026 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 hci_dev_unlock(hdev);
2028 return;
2029 }
2030 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 memcpy(conn->dev_class, ev->dev_class, 3);
2033 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 hci_dev_unlock(hdev);
2036
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002037 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2038 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002040 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002042 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2043 cp.role = 0x00; /* Become master */
2044 else
2045 cp.role = 0x01; /* Remain slave */
2046
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002047 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2048 &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002049 } else {
2050 struct hci_cp_accept_sync_conn_req cp;
2051
2052 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002053 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002054
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03002055 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2056 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2057 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002058 cp.content_format = cpu_to_le16(hdev->voice_setting);
2059 cp.retrans_effort = 0xff;
2060
2061 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002062 sizeof(cp), &cp);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002063 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 } else {
2065 /* Connection rejected */
2066 struct hci_cp_reject_conn_req cp;
2067
2068 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002069 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002070 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 }
2072}
2073
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002074static u8 hci_to_mgmt_reason(u8 err)
2075{
2076 switch (err) {
2077 case HCI_ERROR_CONNECTION_TIMEOUT:
2078 return MGMT_DEV_DISCONN_TIMEOUT;
2079 case HCI_ERROR_REMOTE_USER_TERM:
2080 case HCI_ERROR_REMOTE_LOW_RESOURCES:
2081 case HCI_ERROR_REMOTE_POWER_OFF:
2082 return MGMT_DEV_DISCONN_REMOTE;
2083 case HCI_ERROR_LOCAL_HOST_TERM:
2084 return MGMT_DEV_DISCONN_LOCAL_HOST;
2085 default:
2086 return MGMT_DEV_DISCONN_UNKNOWN;
2087 }
2088}
2089
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002090static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002092 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002093 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002095 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 hci_dev_lock(hdev);
2098
Marcel Holtmann04837f62006-07-03 10:02:33 +02002099 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02002100 if (!conn)
2101 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002102
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002103 if (ev->status == 0)
2104 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Johan Hedbergb644ba32012-01-17 21:48:47 +02002106 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002107 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002108 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002109 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002110 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002111 } else {
2112 u8 reason = hci_to_mgmt_reason(ev->reason);
2113
Johan Hedbergafc747a2012-01-15 18:11:07 +02002114 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002115 conn->dst_type, reason);
2116 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002117 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002118
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002119 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302120 if (conn->type == ACL_LINK && conn->flush_key)
2121 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002122 hci_proto_disconn_cfm(conn, ev->reason);
2123 hci_conn_del(conn);
2124 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002125
2126unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 hci_dev_unlock(hdev);
2128}
2129
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002130static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002131{
2132 struct hci_ev_auth_complete *ev = (void *) skb->data;
2133 struct hci_conn *conn;
2134
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002135 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002136
2137 hci_dev_lock(hdev);
2138
2139 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002140 if (!conn)
2141 goto unlock;
2142
2143 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002144 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002145 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002146 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002147 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002148 conn->link_mode |= HCI_LM_AUTH;
2149 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002150 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002151 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002152 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002153 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002154 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002155
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002156 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2157 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002158
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002159 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002160 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002161 struct hci_cp_set_conn_encrypt cp;
2162 cp.handle = ev->handle;
2163 cp.encrypt = 0x01;
2164 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002165 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002166 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002167 conn->state = BT_CONNECTED;
2168 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002169 hci_conn_put(conn);
2170 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002171 } else {
2172 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002173
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002174 hci_conn_hold(conn);
2175 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2176 hci_conn_put(conn);
2177 }
2178
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002179 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002180 if (!ev->status) {
2181 struct hci_cp_set_conn_encrypt cp;
2182 cp.handle = ev->handle;
2183 cp.encrypt = 0x01;
2184 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002185 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002186 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002187 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002188 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002189 }
2190 }
2191
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002192unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002193 hci_dev_unlock(hdev);
2194}
2195
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002196static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002197{
Johan Hedberg127178d2010-11-18 22:22:29 +02002198 struct hci_ev_remote_name *ev = (void *) skb->data;
2199 struct hci_conn *conn;
2200
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002201 BT_DBG("%s", hdev->name);
2202
2203 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002204
2205 hci_dev_lock(hdev);
2206
2207 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002208
2209 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2210 goto check_auth;
2211
2212 if (ev->status == 0)
2213 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002214 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002215 else
2216 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2217
2218check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002219 if (!conn)
2220 goto unlock;
2221
2222 if (!hci_outgoing_auth_needed(hdev, conn))
2223 goto unlock;
2224
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002225 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002226 struct hci_cp_auth_requested cp;
2227 cp.handle = __cpu_to_le16(conn->handle);
2228 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2229 }
2230
Johan Hedberg79c6c702011-04-28 11:28:55 -07002231unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002232 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002233}
2234
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002235static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002236{
2237 struct hci_ev_encrypt_change *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) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002247 if (ev->encrypt) {
2248 /* Encryption implies authentication */
2249 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002250 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002251 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002252 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002253 conn->link_mode &= ~HCI_LM_ENCRYPT;
2254 }
2255
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002256 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002257
Gustavo Padovana7d77232012-05-13 03:20:07 -03002258 if (ev->status && conn->state == BT_CONNECTED) {
Gustavo Padovand839c812012-05-16 12:17:12 -03002259 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002260 hci_conn_put(conn);
2261 goto unlock;
2262 }
2263
Marcel Holtmannf8558552008-07-14 20:13:49 +02002264 if (conn->state == BT_CONFIG) {
2265 if (!ev->status)
2266 conn->state = BT_CONNECTED;
2267
2268 hci_proto_connect_cfm(conn, ev->status);
2269 hci_conn_put(conn);
2270 } else
2271 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002272 }
2273
Gustavo Padovana7d77232012-05-13 03:20:07 -03002274unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002275 hci_dev_unlock(hdev);
2276}
2277
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002278static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2279 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002280{
2281 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2282 struct hci_conn *conn;
2283
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002284 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002285
2286 hci_dev_lock(hdev);
2287
2288 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2289 if (conn) {
2290 if (!ev->status)
2291 conn->link_mode |= HCI_LM_SECURE;
2292
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002293 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002294
2295 hci_key_change_cfm(conn, ev->status);
2296 }
2297
2298 hci_dev_unlock(hdev);
2299}
2300
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002301static void hci_remote_features_evt(struct hci_dev *hdev,
2302 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002303{
2304 struct hci_ev_remote_features *ev = (void *) skb->data;
2305 struct hci_conn *conn;
2306
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002307 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002308
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002309 hci_dev_lock(hdev);
2310
2311 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002312 if (!conn)
2313 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002314
Johan Hedbergccd556f2010-11-10 17:11:51 +02002315 if (!ev->status)
2316 memcpy(conn->features, ev->features, 8);
2317
2318 if (conn->state != BT_CONFIG)
2319 goto unlock;
2320
2321 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2322 struct hci_cp_read_remote_ext_features cp;
2323 cp.handle = ev->handle;
2324 cp.page = 0x01;
2325 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002326 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002327 goto unlock;
2328 }
2329
Johan Hedberg671267b2012-05-12 16:11:50 -03002330 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002331 struct hci_cp_remote_name_req cp;
2332 memset(&cp, 0, sizeof(cp));
2333 bacpy(&cp.bdaddr, &conn->dst);
2334 cp.pscan_rep_mode = 0x02;
2335 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002336 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2337 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002338 conn->dst_type, 0, NULL, 0,
2339 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002340
Johan Hedberg127178d2010-11-18 22:22:29 +02002341 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002342 conn->state = BT_CONNECTED;
2343 hci_proto_connect_cfm(conn, ev->status);
2344 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002345 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002346
Johan Hedbergccd556f2010-11-10 17:11:51 +02002347unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002348 hci_dev_unlock(hdev);
2349}
2350
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002351static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002352{
2353 BT_DBG("%s", hdev->name);
2354}
2355
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002356static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2357 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002358{
2359 BT_DBG("%s", hdev->name);
2360}
2361
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002362static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002363{
2364 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2365 __u16 opcode;
2366
2367 skb_pull(skb, sizeof(*ev));
2368
2369 opcode = __le16_to_cpu(ev->opcode);
2370
2371 switch (opcode) {
2372 case HCI_OP_INQUIRY_CANCEL:
2373 hci_cc_inquiry_cancel(hdev, skb);
2374 break;
2375
Andre Guedes4d934832012-03-21 00:03:35 -03002376 case HCI_OP_PERIODIC_INQ:
2377 hci_cc_periodic_inq(hdev, skb);
2378 break;
2379
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002380 case HCI_OP_EXIT_PERIODIC_INQ:
2381 hci_cc_exit_periodic_inq(hdev, skb);
2382 break;
2383
2384 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2385 hci_cc_remote_name_req_cancel(hdev, skb);
2386 break;
2387
2388 case HCI_OP_ROLE_DISCOVERY:
2389 hci_cc_role_discovery(hdev, skb);
2390 break;
2391
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002392 case HCI_OP_READ_LINK_POLICY:
2393 hci_cc_read_link_policy(hdev, skb);
2394 break;
2395
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002396 case HCI_OP_WRITE_LINK_POLICY:
2397 hci_cc_write_link_policy(hdev, skb);
2398 break;
2399
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002400 case HCI_OP_READ_DEF_LINK_POLICY:
2401 hci_cc_read_def_link_policy(hdev, skb);
2402 break;
2403
2404 case HCI_OP_WRITE_DEF_LINK_POLICY:
2405 hci_cc_write_def_link_policy(hdev, skb);
2406 break;
2407
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002408 case HCI_OP_RESET:
2409 hci_cc_reset(hdev, skb);
2410 break;
2411
2412 case HCI_OP_WRITE_LOCAL_NAME:
2413 hci_cc_write_local_name(hdev, skb);
2414 break;
2415
2416 case HCI_OP_READ_LOCAL_NAME:
2417 hci_cc_read_local_name(hdev, skb);
2418 break;
2419
2420 case HCI_OP_WRITE_AUTH_ENABLE:
2421 hci_cc_write_auth_enable(hdev, skb);
2422 break;
2423
2424 case HCI_OP_WRITE_ENCRYPT_MODE:
2425 hci_cc_write_encrypt_mode(hdev, skb);
2426 break;
2427
2428 case HCI_OP_WRITE_SCAN_ENABLE:
2429 hci_cc_write_scan_enable(hdev, skb);
2430 break;
2431
2432 case HCI_OP_READ_CLASS_OF_DEV:
2433 hci_cc_read_class_of_dev(hdev, skb);
2434 break;
2435
2436 case HCI_OP_WRITE_CLASS_OF_DEV:
2437 hci_cc_write_class_of_dev(hdev, skb);
2438 break;
2439
2440 case HCI_OP_READ_VOICE_SETTING:
2441 hci_cc_read_voice_setting(hdev, skb);
2442 break;
2443
2444 case HCI_OP_WRITE_VOICE_SETTING:
2445 hci_cc_write_voice_setting(hdev, skb);
2446 break;
2447
2448 case HCI_OP_HOST_BUFFER_SIZE:
2449 hci_cc_host_buffer_size(hdev, skb);
2450 break;
2451
Marcel Holtmann333140b2008-07-14 20:13:48 +02002452 case HCI_OP_WRITE_SSP_MODE:
2453 hci_cc_write_ssp_mode(hdev, skb);
2454 break;
2455
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002456 case HCI_OP_READ_LOCAL_VERSION:
2457 hci_cc_read_local_version(hdev, skb);
2458 break;
2459
2460 case HCI_OP_READ_LOCAL_COMMANDS:
2461 hci_cc_read_local_commands(hdev, skb);
2462 break;
2463
2464 case HCI_OP_READ_LOCAL_FEATURES:
2465 hci_cc_read_local_features(hdev, skb);
2466 break;
2467
Andre Guedes971e3a42011-06-30 19:20:52 -03002468 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2469 hci_cc_read_local_ext_features(hdev, skb);
2470 break;
2471
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002472 case HCI_OP_READ_BUFFER_SIZE:
2473 hci_cc_read_buffer_size(hdev, skb);
2474 break;
2475
2476 case HCI_OP_READ_BD_ADDR:
2477 hci_cc_read_bd_addr(hdev, skb);
2478 break;
2479
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002480 case HCI_OP_READ_DATA_BLOCK_SIZE:
2481 hci_cc_read_data_block_size(hdev, skb);
2482 break;
2483
Johan Hedberg23bb5762010-12-21 23:01:27 +02002484 case HCI_OP_WRITE_CA_TIMEOUT:
2485 hci_cc_write_ca_timeout(hdev, skb);
2486 break;
2487
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002488 case HCI_OP_READ_FLOW_CONTROL_MODE:
2489 hci_cc_read_flow_control_mode(hdev, skb);
2490 break;
2491
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002492 case HCI_OP_READ_LOCAL_AMP_INFO:
2493 hci_cc_read_local_amp_info(hdev, skb);
2494 break;
2495
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002496 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2497 hci_cc_read_local_amp_assoc(hdev, skb);
2498 break;
2499
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002500 case HCI_OP_DELETE_STORED_LINK_KEY:
2501 hci_cc_delete_stored_link_key(hdev, skb);
2502 break;
2503
Johan Hedbergd5859e22011-01-25 01:19:58 +02002504 case HCI_OP_SET_EVENT_MASK:
2505 hci_cc_set_event_mask(hdev, skb);
2506 break;
2507
2508 case HCI_OP_WRITE_INQUIRY_MODE:
2509 hci_cc_write_inquiry_mode(hdev, skb);
2510 break;
2511
2512 case HCI_OP_READ_INQ_RSP_TX_POWER:
2513 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2514 break;
2515
2516 case HCI_OP_SET_EVENT_FLT:
2517 hci_cc_set_event_flt(hdev, skb);
2518 break;
2519
Johan Hedberg980e1a52011-01-22 06:10:07 +02002520 case HCI_OP_PIN_CODE_REPLY:
2521 hci_cc_pin_code_reply(hdev, skb);
2522 break;
2523
2524 case HCI_OP_PIN_CODE_NEG_REPLY:
2525 hci_cc_pin_code_neg_reply(hdev, skb);
2526 break;
2527
Szymon Jancc35938b2011-03-22 13:12:21 +01002528 case HCI_OP_READ_LOCAL_OOB_DATA:
2529 hci_cc_read_local_oob_data_reply(hdev, skb);
2530 break;
2531
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002532 case HCI_OP_LE_READ_BUFFER_SIZE:
2533 hci_cc_le_read_buffer_size(hdev, skb);
2534 break;
2535
Johan Hedberg8fa19092012-10-19 20:57:49 +03002536 case HCI_OP_LE_READ_ADV_TX_POWER:
2537 hci_cc_le_read_adv_tx_power(hdev, skb);
2538 break;
2539
Johan Hedberge36b04c2012-10-19 20:57:47 +03002540 case HCI_OP_LE_SET_EVENT_MASK:
2541 hci_cc_le_set_event_mask(hdev, skb);
2542 break;
2543
Johan Hedberga5c29682011-02-19 12:05:57 -03002544 case HCI_OP_USER_CONFIRM_REPLY:
2545 hci_cc_user_confirm_reply(hdev, skb);
2546 break;
2547
2548 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2549 hci_cc_user_confirm_neg_reply(hdev, skb);
2550 break;
2551
Brian Gix1143d452011-11-23 08:28:34 -08002552 case HCI_OP_USER_PASSKEY_REPLY:
2553 hci_cc_user_passkey_reply(hdev, skb);
2554 break;
2555
2556 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2557 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002558 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002559
2560 case HCI_OP_LE_SET_SCAN_PARAM:
2561 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002562 break;
2563
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002564 case HCI_OP_LE_SET_SCAN_ENABLE:
2565 hci_cc_le_set_scan_enable(hdev, skb);
2566 break;
2567
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002568 case HCI_OP_LE_LTK_REPLY:
2569 hci_cc_le_ltk_reply(hdev, skb);
2570 break;
2571
2572 case HCI_OP_LE_LTK_NEG_REPLY:
2573 hci_cc_le_ltk_neg_reply(hdev, skb);
2574 break;
2575
Andre Guedesf9b49302011-06-30 19:20:53 -03002576 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2577 hci_cc_write_le_host_supported(hdev, skb);
2578 break;
2579
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002580 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2581 hci_cc_write_remote_amp_assoc(hdev, skb);
2582 break;
2583
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002584 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002585 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002586 break;
2587 }
2588
Ville Tervo6bd32322011-02-16 16:32:41 +02002589 if (ev->opcode != HCI_OP_NOP)
2590 del_timer(&hdev->cmd_timer);
2591
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002592 if (ev->ncmd) {
2593 atomic_set(&hdev->cmd_cnt, 1);
2594 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002595 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002596 }
2597}
2598
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002599static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002600{
2601 struct hci_ev_cmd_status *ev = (void *) skb->data;
2602 __u16 opcode;
2603
2604 skb_pull(skb, sizeof(*ev));
2605
2606 opcode = __le16_to_cpu(ev->opcode);
2607
2608 switch (opcode) {
2609 case HCI_OP_INQUIRY:
2610 hci_cs_inquiry(hdev, ev->status);
2611 break;
2612
2613 case HCI_OP_CREATE_CONN:
2614 hci_cs_create_conn(hdev, ev->status);
2615 break;
2616
2617 case HCI_OP_ADD_SCO:
2618 hci_cs_add_sco(hdev, ev->status);
2619 break;
2620
Marcel Holtmannf8558552008-07-14 20:13:49 +02002621 case HCI_OP_AUTH_REQUESTED:
2622 hci_cs_auth_requested(hdev, ev->status);
2623 break;
2624
2625 case HCI_OP_SET_CONN_ENCRYPT:
2626 hci_cs_set_conn_encrypt(hdev, ev->status);
2627 break;
2628
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002629 case HCI_OP_REMOTE_NAME_REQ:
2630 hci_cs_remote_name_req(hdev, ev->status);
2631 break;
2632
Marcel Holtmann769be972008-07-14 20:13:49 +02002633 case HCI_OP_READ_REMOTE_FEATURES:
2634 hci_cs_read_remote_features(hdev, ev->status);
2635 break;
2636
2637 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2638 hci_cs_read_remote_ext_features(hdev, ev->status);
2639 break;
2640
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002641 case HCI_OP_SETUP_SYNC_CONN:
2642 hci_cs_setup_sync_conn(hdev, ev->status);
2643 break;
2644
2645 case HCI_OP_SNIFF_MODE:
2646 hci_cs_sniff_mode(hdev, ev->status);
2647 break;
2648
2649 case HCI_OP_EXIT_SNIFF_MODE:
2650 hci_cs_exit_sniff_mode(hdev, ev->status);
2651 break;
2652
Johan Hedberg8962ee72011-01-20 12:40:27 +02002653 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002654 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002655 break;
2656
Ville Tervofcd89c02011-02-10 22:38:47 -03002657 case HCI_OP_LE_CREATE_CONN:
2658 hci_cs_le_create_conn(hdev, ev->status);
2659 break;
2660
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002661 case HCI_OP_LE_START_ENC:
2662 hci_cs_le_start_enc(hdev, ev->status);
2663 break;
2664
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002665 case HCI_OP_CREATE_PHY_LINK:
2666 hci_cs_create_phylink(hdev, ev->status);
2667 break;
2668
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002669 case HCI_OP_ACCEPT_PHY_LINK:
2670 hci_cs_accept_phylink(hdev, ev->status);
2671 break;
2672
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002673 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002674 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002675 break;
2676 }
2677
Ville Tervo6bd32322011-02-16 16:32:41 +02002678 if (ev->opcode != HCI_OP_NOP)
2679 del_timer(&hdev->cmd_timer);
2680
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002681 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002682 atomic_set(&hdev->cmd_cnt, 1);
2683 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002684 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002685 }
2686}
2687
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002688static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002689{
2690 struct hci_ev_role_change *ev = (void *) skb->data;
2691 struct hci_conn *conn;
2692
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002693 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002694
2695 hci_dev_lock(hdev);
2696
2697 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2698 if (conn) {
2699 if (!ev->status) {
2700 if (ev->role)
2701 conn->link_mode &= ~HCI_LM_MASTER;
2702 else
2703 conn->link_mode |= HCI_LM_MASTER;
2704 }
2705
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002706 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002707
2708 hci_role_switch_cfm(conn, ev->status, ev->role);
2709 }
2710
2711 hci_dev_unlock(hdev);
2712}
2713
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002714static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002716 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 int i;
2718
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002719 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2720 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2721 return;
2722 }
2723
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002724 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002725 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 BT_DBG("%s bad parameters", hdev->name);
2727 return;
2728 }
2729
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002730 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2731
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002732 for (i = 0; i < ev->num_hndl; i++) {
2733 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 struct hci_conn *conn;
2735 __u16 handle, count;
2736
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002737 handle = __le16_to_cpu(info->handle);
2738 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
2740 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002741 if (!conn)
2742 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002744 conn->sent -= count;
2745
2746 switch (conn->type) {
2747 case ACL_LINK:
2748 hdev->acl_cnt += count;
2749 if (hdev->acl_cnt > hdev->acl_pkts)
2750 hdev->acl_cnt = hdev->acl_pkts;
2751 break;
2752
2753 case LE_LINK:
2754 if (hdev->le_pkts) {
2755 hdev->le_cnt += count;
2756 if (hdev->le_cnt > hdev->le_pkts)
2757 hdev->le_cnt = hdev->le_pkts;
2758 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002759 hdev->acl_cnt += count;
2760 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 hdev->acl_cnt = hdev->acl_pkts;
2762 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002763 break;
2764
2765 case SCO_LINK:
2766 hdev->sco_cnt += count;
2767 if (hdev->sco_cnt > hdev->sco_pkts)
2768 hdev->sco_cnt = hdev->sco_pkts;
2769 break;
2770
2771 default:
2772 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2773 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 }
2775 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002776
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002777 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778}
2779
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002780static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2781 __u16 handle)
2782{
2783 struct hci_chan *chan;
2784
2785 switch (hdev->dev_type) {
2786 case HCI_BREDR:
2787 return hci_conn_hash_lookup_handle(hdev, handle);
2788 case HCI_AMP:
2789 chan = hci_chan_lookup_handle(hdev, handle);
2790 if (chan)
2791 return chan->conn;
2792 break;
2793 default:
2794 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2795 break;
2796 }
2797
2798 return NULL;
2799}
2800
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002801static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002802{
2803 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2804 int i;
2805
2806 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2807 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2808 return;
2809 }
2810
2811 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002812 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002813 BT_DBG("%s bad parameters", hdev->name);
2814 return;
2815 }
2816
2817 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002818 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002819
2820 for (i = 0; i < ev->num_hndl; i++) {
2821 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002822 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002823 __u16 handle, block_count;
2824
2825 handle = __le16_to_cpu(info->handle);
2826 block_count = __le16_to_cpu(info->blocks);
2827
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002828 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002829 if (!conn)
2830 continue;
2831
2832 conn->sent -= block_count;
2833
2834 switch (conn->type) {
2835 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002836 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002837 hdev->block_cnt += block_count;
2838 if (hdev->block_cnt > hdev->num_blocks)
2839 hdev->block_cnt = hdev->num_blocks;
2840 break;
2841
2842 default:
2843 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2844 break;
2845 }
2846 }
2847
2848 queue_work(hdev->workqueue, &hdev->tx_work);
2849}
2850
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002851static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002853 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002854 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002856 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857
2858 hci_dev_lock(hdev);
2859
Marcel Holtmann04837f62006-07-03 10:02:33 +02002860 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2861 if (conn) {
2862 conn->mode = ev->mode;
2863 conn->interval = __le16_to_cpu(ev->interval);
2864
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002865 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2866 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002867 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002868 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002869 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002870 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002871 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002872
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002873 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002874 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002875 }
2876
2877 hci_dev_unlock(hdev);
2878}
2879
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002880static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002882 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2883 struct hci_conn *conn;
2884
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002885 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002886
2887 hci_dev_lock(hdev);
2888
2889 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002890 if (!conn)
2891 goto unlock;
2892
2893 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002894 hci_conn_hold(conn);
2895 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2896 hci_conn_put(conn);
2897 }
2898
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002899 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002900 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002901 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002902 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002903 u8 secure;
2904
2905 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2906 secure = 1;
2907 else
2908 secure = 0;
2909
Johan Hedberg744cf192011-11-08 20:40:14 +02002910 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002911 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002912
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002913unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002914 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915}
2916
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002917static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918{
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002919 struct hci_ev_link_key_req *ev = (void *) skb->data;
2920 struct hci_cp_link_key_reply cp;
2921 struct hci_conn *conn;
2922 struct link_key *key;
2923
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002924 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002925
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002926 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002927 return;
2928
2929 hci_dev_lock(hdev);
2930
2931 key = hci_find_link_key(hdev, &ev->bdaddr);
2932 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002933 BT_DBG("%s link key not found for %pMR", hdev->name,
2934 &ev->bdaddr);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002935 goto not_found;
2936 }
2937
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002938 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2939 &ev->bdaddr);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002940
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002941 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002942 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002943 BT_DBG("%s ignoring debug key", hdev->name);
2944 goto not_found;
2945 }
2946
2947 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002948 if (conn) {
2949 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002950 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002951 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2952 goto not_found;
2953 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002954
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002955 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002956 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002957 BT_DBG("%s ignoring key unauthenticated for high security",
2958 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002959 goto not_found;
2960 }
2961
2962 conn->key_type = key->type;
2963 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002964 }
2965
2966 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002967 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002968
2969 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2970
2971 hci_dev_unlock(hdev);
2972
2973 return;
2974
2975not_found:
2976 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2977 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978}
2979
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002980static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002982 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2983 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002984 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002985
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002986 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002987
2988 hci_dev_lock(hdev);
2989
2990 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2991 if (conn) {
2992 hci_conn_hold(conn);
2993 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002994 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002995
2996 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2997 conn->key_type = ev->key_type;
2998
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002999 hci_conn_put(conn);
3000 }
3001
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003002 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07003003 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003004 ev->key_type, pin_len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02003005
Marcel Holtmann052b30b2009-04-26 20:01:22 +02003006 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007}
3008
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003009static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003010{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003011 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003012 struct hci_conn *conn;
3013
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003014 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003015
3016 hci_dev_lock(hdev);
3017
3018 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 if (conn && !ev->status) {
3020 struct inquiry_entry *ie;
3021
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003022 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3023 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 ie->data.clock_offset = ev->clock_offset;
3025 ie->timestamp = jiffies;
3026 }
3027 }
3028
3029 hci_dev_unlock(hdev);
3030}
3031
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003032static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02003033{
3034 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3035 struct hci_conn *conn;
3036
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003037 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02003038
3039 hci_dev_lock(hdev);
3040
3041 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3042 if (conn && !ev->status)
3043 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3044
3045 hci_dev_unlock(hdev);
3046}
3047
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003048static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003049{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003050 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003051 struct inquiry_entry *ie;
3052
3053 BT_DBG("%s", hdev->name);
3054
3055 hci_dev_lock(hdev);
3056
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003057 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3058 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003059 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
3060 ie->timestamp = jiffies;
3061 }
3062
3063 hci_dev_unlock(hdev);
3064}
3065
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003066static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3067 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003068{
3069 struct inquiry_data data;
3070 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003071 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003072
3073 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3074
3075 if (!num_rsp)
3076 return;
3077
Andre Guedes1519cc12012-03-21 00:03:38 -03003078 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3079 return;
3080
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003081 hci_dev_lock(hdev);
3082
3083 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003084 struct inquiry_info_with_rssi_and_pscan_mode *info;
3085 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003086
Johan Hedberge17acd42011-03-30 23:57:16 +03003087 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003088 bacpy(&data.bdaddr, &info->bdaddr);
3089 data.pscan_rep_mode = info->pscan_rep_mode;
3090 data.pscan_period_mode = info->pscan_period_mode;
3091 data.pscan_mode = info->pscan_mode;
3092 memcpy(data.dev_class, info->dev_class, 3);
3093 data.clock_offset = info->clock_offset;
3094 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003095 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003096
3097 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003098 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003099 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003100 info->dev_class, info->rssi,
3101 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003102 }
3103 } else {
3104 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3105
Johan Hedberge17acd42011-03-30 23:57:16 +03003106 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003107 bacpy(&data.bdaddr, &info->bdaddr);
3108 data.pscan_rep_mode = info->pscan_rep_mode;
3109 data.pscan_period_mode = info->pscan_period_mode;
3110 data.pscan_mode = 0x00;
3111 memcpy(data.dev_class, info->dev_class, 3);
3112 data.clock_offset = info->clock_offset;
3113 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003114 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003115 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003116 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003117 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003118 info->dev_class, info->rssi,
3119 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003120 }
3121 }
3122
3123 hci_dev_unlock(hdev);
3124}
3125
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003126static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3127 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003128{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003129 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3130 struct hci_conn *conn;
3131
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003132 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003133
Marcel Holtmann41a96212008-07-14 20:13:48 +02003134 hci_dev_lock(hdev);
3135
3136 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003137 if (!conn)
3138 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003139
Johan Hedbergccd556f2010-11-10 17:11:51 +02003140 if (!ev->status && ev->page == 0x01) {
3141 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003142
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003143 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3144 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003145 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003146
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003147 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003148 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003149 }
3150
Johan Hedbergccd556f2010-11-10 17:11:51 +02003151 if (conn->state != BT_CONFIG)
3152 goto unlock;
3153
Johan Hedberg671267b2012-05-12 16:11:50 -03003154 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003155 struct hci_cp_remote_name_req cp;
3156 memset(&cp, 0, sizeof(cp));
3157 bacpy(&cp.bdaddr, &conn->dst);
3158 cp.pscan_rep_mode = 0x02;
3159 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003160 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3161 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003162 conn->dst_type, 0, NULL, 0,
3163 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003164
Johan Hedberg127178d2010-11-18 22:22:29 +02003165 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003166 conn->state = BT_CONNECTED;
3167 hci_proto_connect_cfm(conn, ev->status);
3168 hci_conn_put(conn);
3169 }
3170
3171unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003172 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003173}
3174
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003175static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3176 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003177{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003178 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3179 struct hci_conn *conn;
3180
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003181 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003182
3183 hci_dev_lock(hdev);
3184
3185 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003186 if (!conn) {
3187 if (ev->link_type == ESCO_LINK)
3188 goto unlock;
3189
3190 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3191 if (!conn)
3192 goto unlock;
3193
3194 conn->type = SCO_LINK;
3195 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003196
Marcel Holtmann732547f2009-04-19 19:14:14 +02003197 switch (ev->status) {
3198 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003199 conn->handle = __le16_to_cpu(ev->handle);
3200 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003201
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003202 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003203 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003204 break;
3205
Stephen Coe705e5712010-02-16 11:29:44 -05003206 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003207 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003208 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003209 case 0x1f: /* Unspecified error */
3210 if (conn->out && conn->attempt < 2) {
3211 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3212 (hdev->esco_type & EDR_ESCO_MASK);
3213 hci_setup_sync(conn, conn->link->handle);
3214 goto unlock;
3215 }
3216 /* fall through */
3217
3218 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003219 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003220 break;
3221 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003222
3223 hci_proto_connect_cfm(conn, ev->status);
3224 if (ev->status)
3225 hci_conn_del(conn);
3226
3227unlock:
3228 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003229}
3230
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003231static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003232{
3233 BT_DBG("%s", hdev->name);
3234}
3235
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003236static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003237{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003238 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003239
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003240 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003241}
3242
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003243static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3244 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003245{
3246 struct inquiry_data data;
3247 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3248 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303249 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003250
3251 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3252
3253 if (!num_rsp)
3254 return;
3255
Andre Guedes1519cc12012-03-21 00:03:38 -03003256 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3257 return;
3258
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003259 hci_dev_lock(hdev);
3260
Johan Hedberge17acd42011-03-30 23:57:16 +03003261 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003262 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003263
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003264 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003265 data.pscan_rep_mode = info->pscan_rep_mode;
3266 data.pscan_period_mode = info->pscan_period_mode;
3267 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003268 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003269 data.clock_offset = info->clock_offset;
3270 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003271 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003272
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003273 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003274 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003275 sizeof(info->data),
3276 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003277 else
3278 name_known = true;
3279
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003280 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003281 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303282 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003283 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003284 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303285 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003286 }
3287
3288 hci_dev_unlock(hdev);
3289}
3290
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003291static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3292 struct sk_buff *skb)
3293{
3294 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3295 struct hci_conn *conn;
3296
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003297 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003298 __le16_to_cpu(ev->handle));
3299
3300 hci_dev_lock(hdev);
3301
3302 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3303 if (!conn)
3304 goto unlock;
3305
3306 if (!ev->status)
3307 conn->sec_level = conn->pending_sec_level;
3308
3309 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3310
3311 if (ev->status && conn->state == BT_CONNECTED) {
3312 hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
3313 hci_conn_put(conn);
3314 goto unlock;
3315 }
3316
3317 if (conn->state == BT_CONFIG) {
3318 if (!ev->status)
3319 conn->state = BT_CONNECTED;
3320
3321 hci_proto_connect_cfm(conn, ev->status);
3322 hci_conn_put(conn);
3323 } else {
3324 hci_auth_cfm(conn, ev->status);
3325
3326 hci_conn_hold(conn);
3327 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3328 hci_conn_put(conn);
3329 }
3330
3331unlock:
3332 hci_dev_unlock(hdev);
3333}
3334
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003335static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003336{
3337 /* If remote requests dedicated bonding follow that lead */
3338 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3339 /* If both remote and local IO capabilities allow MITM
3340 * protection then require it, otherwise don't */
3341 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3342 return 0x02;
3343 else
3344 return 0x03;
3345 }
3346
3347 /* If remote requests no-bonding follow that lead */
3348 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003349 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003350
3351 return conn->auth_type;
3352}
3353
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003354static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003355{
3356 struct hci_ev_io_capa_request *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);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003364 if (!conn)
3365 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003366
Johan Hedberg03b555e2011-01-04 15:40:05 +02003367 hci_conn_hold(conn);
3368
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003369 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003370 goto unlock;
3371
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003372 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003373 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003374 struct hci_cp_io_capability_reply cp;
3375
3376 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303377 /* Change the IO capability from KeyboardDisplay
3378 * to DisplayYesNo as it is not supported by BT spec. */
3379 cp.capability = (conn->io_capability == 0x04) ?
3380 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003381 conn->auth_type = hci_get_auth_req(conn);
3382 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003383
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003384 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3385 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003386 cp.oob_data = 0x01;
3387 else
3388 cp.oob_data = 0x00;
3389
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003390 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003391 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003392 } else {
3393 struct hci_cp_io_capability_neg_reply cp;
3394
3395 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003396 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003397
3398 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003399 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003400 }
3401
3402unlock:
3403 hci_dev_unlock(hdev);
3404}
3405
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003406static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003407{
3408 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3409 struct hci_conn *conn;
3410
3411 BT_DBG("%s", hdev->name);
3412
3413 hci_dev_lock(hdev);
3414
3415 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3416 if (!conn)
3417 goto unlock;
3418
Johan Hedberg03b555e2011-01-04 15:40:05 +02003419 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003420 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003421 if (ev->oob_data)
3422 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003423
3424unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003425 hci_dev_unlock(hdev);
3426}
3427
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003428static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3429 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003430{
3431 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003432 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003433 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003434
3435 BT_DBG("%s", hdev->name);
3436
3437 hci_dev_lock(hdev);
3438
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003439 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003440 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003441
Johan Hedberg7a828902011-04-28 11:28:53 -07003442 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3443 if (!conn)
3444 goto unlock;
3445
3446 loc_mitm = (conn->auth_type & 0x01);
3447 rem_mitm = (conn->remote_auth & 0x01);
3448
3449 /* If we require MITM but the remote device can't provide that
3450 * (it has NoInputNoOutput) then reject the confirmation
3451 * request. The only exception is when we're dedicated bonding
3452 * initiators (connect_cfm_cb set) since then we always have the MITM
3453 * bit set. */
3454 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3455 BT_DBG("Rejecting request: remote device can't provide MITM");
3456 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003457 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003458 goto unlock;
3459 }
3460
3461 /* If no side requires MITM protection; auto-accept */
3462 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003463 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003464
3465 /* If we're not the initiators request authorization to
3466 * proceed from user space (mgmt_user_confirm with
3467 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003468 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003469 BT_DBG("Confirming auto-accept as acceptor");
3470 confirm_hint = 1;
3471 goto confirm;
3472 }
3473
Johan Hedberg9f616562011-04-28 11:28:54 -07003474 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003475 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003476
3477 if (hdev->auto_accept_delay > 0) {
3478 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3479 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3480 goto unlock;
3481 }
3482
Johan Hedberg7a828902011-04-28 11:28:53 -07003483 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003484 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003485 goto unlock;
3486 }
3487
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003488confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003489 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003490 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003491
3492unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003493 hci_dev_unlock(hdev);
3494}
3495
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003496static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3497 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003498{
3499 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3500
3501 BT_DBG("%s", hdev->name);
3502
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003503 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003504 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003505}
3506
Johan Hedberg92a25252012-09-06 18:39:26 +03003507static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3508 struct sk_buff *skb)
3509{
3510 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3511 struct hci_conn *conn;
3512
3513 BT_DBG("%s", hdev->name);
3514
3515 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3516 if (!conn)
3517 return;
3518
3519 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3520 conn->passkey_entered = 0;
3521
3522 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3523 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3524 conn->dst_type, conn->passkey_notify,
3525 conn->passkey_entered);
3526}
3527
3528static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3529{
3530 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3531 struct hci_conn *conn;
3532
3533 BT_DBG("%s", hdev->name);
3534
3535 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3536 if (!conn)
3537 return;
3538
3539 switch (ev->type) {
3540 case HCI_KEYPRESS_STARTED:
3541 conn->passkey_entered = 0;
3542 return;
3543
3544 case HCI_KEYPRESS_ENTERED:
3545 conn->passkey_entered++;
3546 break;
3547
3548 case HCI_KEYPRESS_ERASED:
3549 conn->passkey_entered--;
3550 break;
3551
3552 case HCI_KEYPRESS_CLEARED:
3553 conn->passkey_entered = 0;
3554 break;
3555
3556 case HCI_KEYPRESS_COMPLETED:
3557 return;
3558 }
3559
3560 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3561 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3562 conn->dst_type, conn->passkey_notify,
3563 conn->passkey_entered);
3564}
3565
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003566static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3567 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003568{
3569 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3570 struct hci_conn *conn;
3571
3572 BT_DBG("%s", hdev->name);
3573
3574 hci_dev_lock(hdev);
3575
3576 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003577 if (!conn)
3578 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003579
Johan Hedberg2a611692011-02-19 12:06:00 -03003580 /* To avoid duplicate auth_failed events to user space we check
3581 * the HCI_CONN_AUTH_PEND flag which will be set if we
3582 * initiated the authentication. A traditional auth_complete
3583 * event gets always produced as initiator and is also mapped to
3584 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003585 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003586 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003587 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003588
3589 hci_conn_put(conn);
3590
3591unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003592 hci_dev_unlock(hdev);
3593}
3594
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003595static void hci_remote_host_features_evt(struct hci_dev *hdev,
3596 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003597{
3598 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3599 struct inquiry_entry *ie;
3600
3601 BT_DBG("%s", hdev->name);
3602
3603 hci_dev_lock(hdev);
3604
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003605 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3606 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003607 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003608
3609 hci_dev_unlock(hdev);
3610}
3611
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003612static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3613 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003614{
3615 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3616 struct oob_data *data;
3617
3618 BT_DBG("%s", hdev->name);
3619
3620 hci_dev_lock(hdev);
3621
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003622 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003623 goto unlock;
3624
Szymon Janc2763eda2011-03-22 13:12:22 +01003625 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3626 if (data) {
3627 struct hci_cp_remote_oob_data_reply cp;
3628
3629 bacpy(&cp.bdaddr, &ev->bdaddr);
3630 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3631 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3632
3633 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003634 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003635 } else {
3636 struct hci_cp_remote_oob_data_neg_reply cp;
3637
3638 bacpy(&cp.bdaddr, &ev->bdaddr);
3639 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003640 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003641 }
3642
Szymon Jance1ba1f12011-04-06 13:01:59 +02003643unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003644 hci_dev_unlock(hdev);
3645}
3646
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003647static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3648 struct sk_buff *skb)
3649{
3650 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3651 struct hci_conn *hcon, *bredr_hcon;
3652
3653 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3654 ev->status);
3655
3656 hci_dev_lock(hdev);
3657
3658 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3659 if (!hcon) {
3660 hci_dev_unlock(hdev);
3661 return;
3662 }
3663
3664 if (ev->status) {
3665 hci_conn_del(hcon);
3666 hci_dev_unlock(hdev);
3667 return;
3668 }
3669
3670 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3671
3672 hcon->state = BT_CONNECTED;
3673 bacpy(&hcon->dst, &bredr_hcon->dst);
3674
3675 hci_conn_hold(hcon);
3676 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3677 hci_conn_put(hcon);
3678
3679 hci_conn_hold_device(hcon);
3680 hci_conn_add_sysfs(hcon);
3681
3682 hci_dev_unlock(hdev);
3683
3684 if (hcon->out) {
3685 struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
3686
3687 if (!bredr_hdev)
3688 return;
3689
3690 /* Placeholder - create chan req
3691 l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id);
3692 */
3693
3694 hci_dev_put(bredr_hdev);
3695 }
3696}
3697
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003698static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003699{
3700 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3701 struct hci_conn *conn;
3702
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003703 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003704
3705 hci_dev_lock(hdev);
3706
Andre Guedesb47a09b2012-07-27 15:10:15 -03003707 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003708 if (!conn) {
3709 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3710 if (!conn) {
3711 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003712 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003713 }
Andre Guedes29b79882011-05-31 14:20:54 -03003714
3715 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003716
3717 if (ev->role == LE_CONN_ROLE_MASTER) {
3718 conn->out = true;
3719 conn->link_mode |= HCI_LM_MASTER;
3720 }
Ville Tervob62f3282011-02-10 22:38:50 -03003721 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003722
Andre Guedescd17dec2012-07-27 15:10:16 -03003723 if (ev->status) {
3724 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3725 conn->dst_type, ev->status);
3726 hci_proto_connect_cfm(conn, ev->status);
3727 conn->state = BT_CLOSED;
3728 hci_conn_del(conn);
3729 goto unlock;
3730 }
3731
Johan Hedbergb644ba32012-01-17 21:48:47 +02003732 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3733 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003734 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003735
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003736 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003737 conn->handle = __le16_to_cpu(ev->handle);
3738 conn->state = BT_CONNECTED;
3739
3740 hci_conn_hold_device(conn);
3741 hci_conn_add_sysfs(conn);
3742
3743 hci_proto_connect_cfm(conn, ev->status);
3744
3745unlock:
3746 hci_dev_unlock(hdev);
3747}
3748
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003749static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003750{
Andre Guedese95beb42011-09-26 20:48:35 -03003751 u8 num_reports = skb->data[0];
3752 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003753 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003754
3755 hci_dev_lock(hdev);
3756
Andre Guedese95beb42011-09-26 20:48:35 -03003757 while (num_reports--) {
3758 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003759
Andre Guedes3c9e9192012-01-10 18:20:50 -03003760 rssi = ev->data[ev->length];
3761 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003762 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003763
Andre Guedese95beb42011-09-26 20:48:35 -03003764 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003765 }
3766
3767 hci_dev_unlock(hdev);
3768}
3769
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003770static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003771{
3772 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3773 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003774 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003775 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003776 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003777
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003778 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003779
3780 hci_dev_lock(hdev);
3781
3782 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003783 if (conn == NULL)
3784 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003785
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003786 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3787 if (ltk == NULL)
3788 goto not_found;
3789
3790 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003791 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003792
3793 if (ltk->authenticated)
3794 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003795
3796 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3797
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003798 if (ltk->type & HCI_SMP_STK) {
3799 list_del(&ltk->list);
3800 kfree(ltk);
3801 }
3802
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003803 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003804
3805 return;
3806
3807not_found:
3808 neg.handle = ev->handle;
3809 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3810 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003811}
3812
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003813static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003814{
3815 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3816
3817 skb_pull(skb, sizeof(*le_ev));
3818
3819 switch (le_ev->subevent) {
3820 case HCI_EV_LE_CONN_COMPLETE:
3821 hci_le_conn_complete_evt(hdev, skb);
3822 break;
3823
Andre Guedes9aa04c92011-05-26 16:23:51 -03003824 case HCI_EV_LE_ADVERTISING_REPORT:
3825 hci_le_adv_report_evt(hdev, skb);
3826 break;
3827
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003828 case HCI_EV_LE_LTK_REQ:
3829 hci_le_ltk_request_evt(hdev, skb);
3830 break;
3831
Ville Tervofcd89c02011-02-10 22:38:47 -03003832 default:
3833 break;
3834 }
3835}
3836
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003837static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3838{
3839 struct hci_ev_channel_selected *ev = (void *) skb->data;
3840 struct hci_conn *hcon;
3841
3842 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3843
3844 skb_pull(skb, sizeof(*ev));
3845
3846 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3847 if (!hcon)
3848 return;
3849
3850 amp_read_loc_assoc_final_data(hdev, hcon);
3851}
3852
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3854{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003855 struct hci_event_hdr *hdr = (void *) skb->data;
3856 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857
3858 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3859
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003860 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 case HCI_EV_INQUIRY_COMPLETE:
3862 hci_inquiry_complete_evt(hdev, skb);
3863 break;
3864
3865 case HCI_EV_INQUIRY_RESULT:
3866 hci_inquiry_result_evt(hdev, skb);
3867 break;
3868
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003869 case HCI_EV_CONN_COMPLETE:
3870 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003871 break;
3872
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 case HCI_EV_CONN_REQUEST:
3874 hci_conn_request_evt(hdev, skb);
3875 break;
3876
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 case HCI_EV_DISCONN_COMPLETE:
3878 hci_disconn_complete_evt(hdev, skb);
3879 break;
3880
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 case HCI_EV_AUTH_COMPLETE:
3882 hci_auth_complete_evt(hdev, skb);
3883 break;
3884
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003885 case HCI_EV_REMOTE_NAME:
3886 hci_remote_name_evt(hdev, skb);
3887 break;
3888
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 case HCI_EV_ENCRYPT_CHANGE:
3890 hci_encrypt_change_evt(hdev, skb);
3891 break;
3892
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003893 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3894 hci_change_link_key_complete_evt(hdev, skb);
3895 break;
3896
3897 case HCI_EV_REMOTE_FEATURES:
3898 hci_remote_features_evt(hdev, skb);
3899 break;
3900
3901 case HCI_EV_REMOTE_VERSION:
3902 hci_remote_version_evt(hdev, skb);
3903 break;
3904
3905 case HCI_EV_QOS_SETUP_COMPLETE:
3906 hci_qos_setup_complete_evt(hdev, skb);
3907 break;
3908
3909 case HCI_EV_CMD_COMPLETE:
3910 hci_cmd_complete_evt(hdev, skb);
3911 break;
3912
3913 case HCI_EV_CMD_STATUS:
3914 hci_cmd_status_evt(hdev, skb);
3915 break;
3916
3917 case HCI_EV_ROLE_CHANGE:
3918 hci_role_change_evt(hdev, skb);
3919 break;
3920
3921 case HCI_EV_NUM_COMP_PKTS:
3922 hci_num_comp_pkts_evt(hdev, skb);
3923 break;
3924
3925 case HCI_EV_MODE_CHANGE:
3926 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 break;
3928
3929 case HCI_EV_PIN_CODE_REQ:
3930 hci_pin_code_request_evt(hdev, skb);
3931 break;
3932
3933 case HCI_EV_LINK_KEY_REQ:
3934 hci_link_key_request_evt(hdev, skb);
3935 break;
3936
3937 case HCI_EV_LINK_KEY_NOTIFY:
3938 hci_link_key_notify_evt(hdev, skb);
3939 break;
3940
3941 case HCI_EV_CLOCK_OFFSET:
3942 hci_clock_offset_evt(hdev, skb);
3943 break;
3944
Marcel Holtmanna8746412008-07-14 20:13:46 +02003945 case HCI_EV_PKT_TYPE_CHANGE:
3946 hci_pkt_type_change_evt(hdev, skb);
3947 break;
3948
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003949 case HCI_EV_PSCAN_REP_MODE:
3950 hci_pscan_rep_mode_evt(hdev, skb);
3951 break;
3952
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003953 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3954 hci_inquiry_result_with_rssi_evt(hdev, skb);
3955 break;
3956
3957 case HCI_EV_REMOTE_EXT_FEATURES:
3958 hci_remote_ext_features_evt(hdev, skb);
3959 break;
3960
3961 case HCI_EV_SYNC_CONN_COMPLETE:
3962 hci_sync_conn_complete_evt(hdev, skb);
3963 break;
3964
3965 case HCI_EV_SYNC_CONN_CHANGED:
3966 hci_sync_conn_changed_evt(hdev, skb);
3967 break;
3968
Marcel Holtmann04837f62006-07-03 10:02:33 +02003969 case HCI_EV_SNIFF_SUBRATE:
3970 hci_sniff_subrate_evt(hdev, skb);
3971 break;
3972
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003973 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3974 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 break;
3976
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003977 case HCI_EV_KEY_REFRESH_COMPLETE:
3978 hci_key_refresh_complete_evt(hdev, skb);
3979 break;
3980
Marcel Holtmann04936842008-07-14 20:13:48 +02003981 case HCI_EV_IO_CAPA_REQUEST:
3982 hci_io_capa_request_evt(hdev, skb);
3983 break;
3984
Johan Hedberg03b555e2011-01-04 15:40:05 +02003985 case HCI_EV_IO_CAPA_REPLY:
3986 hci_io_capa_reply_evt(hdev, skb);
3987 break;
3988
Johan Hedberga5c29682011-02-19 12:05:57 -03003989 case HCI_EV_USER_CONFIRM_REQUEST:
3990 hci_user_confirm_request_evt(hdev, skb);
3991 break;
3992
Brian Gix1143d452011-11-23 08:28:34 -08003993 case HCI_EV_USER_PASSKEY_REQUEST:
3994 hci_user_passkey_request_evt(hdev, skb);
3995 break;
3996
Johan Hedberg92a25252012-09-06 18:39:26 +03003997 case HCI_EV_USER_PASSKEY_NOTIFY:
3998 hci_user_passkey_notify_evt(hdev, skb);
3999 break;
4000
4001 case HCI_EV_KEYPRESS_NOTIFY:
4002 hci_keypress_notify_evt(hdev, skb);
4003 break;
4004
Marcel Holtmann04936842008-07-14 20:13:48 +02004005 case HCI_EV_SIMPLE_PAIR_COMPLETE:
4006 hci_simple_pair_complete_evt(hdev, skb);
4007 break;
4008
Marcel Holtmann41a96212008-07-14 20:13:48 +02004009 case HCI_EV_REMOTE_HOST_FEATURES:
4010 hci_remote_host_features_evt(hdev, skb);
4011 break;
4012
Ville Tervofcd89c02011-02-10 22:38:47 -03004013 case HCI_EV_LE_META:
4014 hci_le_meta_evt(hdev, skb);
4015 break;
4016
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004017 case HCI_EV_CHANNEL_SELECTED:
4018 hci_chan_selected_evt(hdev, skb);
4019 break;
4020
Szymon Janc2763eda2011-03-22 13:12:22 +01004021 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4022 hci_remote_oob_data_request_evt(hdev, skb);
4023 break;
4024
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004025 case HCI_EV_PHY_LINK_COMPLETE:
4026 hci_phy_link_complete_evt(hdev, skb);
4027 break;
4028
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02004029 case HCI_EV_NUM_COMP_BLOCKS:
4030 hci_num_comp_blocks_evt(hdev, skb);
4031 break;
4032
Marcel Holtmanna9de9242007-10-20 13:33:56 +02004033 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03004034 BT_DBG("%s event 0x%2.2x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 break;
4036 }
4037
4038 kfree_skb(skb);
4039 hdev->stat.evt_rx++;
4040}