blob: 8b878a3bdf69666628835ba148c988f7cdaae2ec [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI event handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
Mikel Astizf0d6a0e2012-08-09 09:52:30 +020031#include <net/bluetooth/mgmt.h>
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +030032#include <net/bluetooth/a2mp.h>
Andrei Emeltchenko903e4542012-09-27 17:26:09 +030033#include <net/bluetooth/amp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* Handle HCI Event packets */
36
Marcel Holtmanna9de9242007-10-20 13:33:56 +020037static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020039 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +030041 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Andre Guedese6d465c2011-11-09 17:14:26 -030043 if (status) {
44 hci_dev_lock(hdev);
45 mgmt_stop_discovery_failed(hdev, status);
46 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020047 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Andre Guedes89352e72011-11-04 14:16:53 -030050 clear_bit(HCI_INQUIRY, &hdev->flags);
51
Johan Hedberg56e5cb82011-11-08 20:40:16 +020052 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020053 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020054 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010055
Johan Hedberg9238f362013-03-05 20:37:48 +020056 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
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;
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100206 hdev->inq_tx_power = HCI_TX_POWER_INVALID;
207 hdev->adv_tx_power = HCI_TX_POWER_INVALID;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100208
209 memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
210 hdev->adv_data_len = 0;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200211}
212
213static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
214{
215 __u8 status = *((__u8 *) skb->data);
216 void *sent;
217
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300218 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200219
220 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
221 if (!sent)
222 return;
223
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200224 hci_dev_lock(hdev);
225
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200226 if (test_bit(HCI_MGMT, &hdev->dev_flags))
227 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +0200228 else if (!status)
229 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergf51d5b22012-02-22 18:17:32 +0200230
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200231 hci_dev_unlock(hdev);
Johan Hedberg3159d382012-02-24 13:47:56 +0200232
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100233 if (!status && !test_bit(HCI_INIT, &hdev->flags))
234 hci_update_ad(hdev);
235
Johan Hedberg3159d382012-02-24 13:47:56 +0200236 hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200237}
238
239static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
240{
241 struct hci_rp_read_local_name *rp = (void *) skb->data;
242
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300243 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200244
245 if (rp->status)
246 return;
247
Johan Hedbergdb99b5f2012-02-22 20:14:22 +0200248 if (test_bit(HCI_SETUP, &hdev->dev_flags))
249 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200250}
251
252static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
253{
254 __u8 status = *((__u8 *) skb->data);
255 void *sent;
256
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300257 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200258
259 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
260 if (!sent)
261 return;
262
263 if (!status) {
264 __u8 param = *((__u8 *) sent);
265
266 if (param == AUTH_ENABLED)
267 set_bit(HCI_AUTH, &hdev->flags);
268 else
269 clear_bit(HCI_AUTH, &hdev->flags);
270 }
271
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200272 if (test_bit(HCI_MGMT, &hdev->dev_flags))
273 mgmt_auth_enable_complete(hdev, status);
274
Johan Hedberg23bb5762010-12-21 23:01:27 +0200275 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200276}
277
278static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
279{
280 __u8 status = *((__u8 *) skb->data);
281 void *sent;
282
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300283 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200284
285 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
286 if (!sent)
287 return;
288
289 if (!status) {
290 __u8 param = *((__u8 *) sent);
291
292 if (param)
293 set_bit(HCI_ENCRYPT, &hdev->flags);
294 else
295 clear_bit(HCI_ENCRYPT, &hdev->flags);
296 }
297
Johan Hedberg23bb5762010-12-21 23:01:27 +0200298 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200299}
300
301static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
302{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200303 __u8 param, status = *((__u8 *) skb->data);
304 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200305 void *sent;
306
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300307 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200308
309 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
310 if (!sent)
311 return;
312
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200313 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200314
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200315 hci_dev_lock(hdev);
316
Mikel Astizfa1bd912012-08-09 09:52:29 +0200317 if (status) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200318 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200319 hdev->discov_timeout = 0;
320 goto done;
321 }
322
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200323 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
324 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200325
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200326 if (param & SCAN_INQUIRY) {
327 set_bit(HCI_ISCAN, &hdev->flags);
328 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200329 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200330 if (hdev->discov_timeout > 0) {
331 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
332 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300333 to);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200334 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200335 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200336 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200337
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200338 if (param & SCAN_PAGE) {
339 set_bit(HCI_PSCAN, &hdev->flags);
340 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200341 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200342 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200343 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200344
345done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200346 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200347 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200348}
349
350static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
351{
352 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
353
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300354 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200355
356 if (rp->status)
357 return;
358
359 memcpy(hdev->dev_class, rp->dev_class, 3);
360
361 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300362 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200363}
364
365static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
366{
367 __u8 status = *((__u8 *) skb->data);
368 void *sent;
369
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300370 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200371
372 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
373 if (!sent)
374 return;
375
Marcel Holtmann7f9a9032012-02-22 18:38:01 +0100376 hci_dev_lock(hdev);
377
378 if (status == 0)
379 memcpy(hdev->dev_class, sent, 3);
380
381 if (test_bit(HCI_MGMT, &hdev->dev_flags))
382 mgmt_set_class_of_dev_complete(hdev, sent, status);
383
384 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200385}
386
387static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
388{
389 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300392 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200393
394 if (rp->status)
395 return;
396
397 setting = __le16_to_cpu(rp->voice_setting);
398
Marcel Holtmannf383f272008-07-14 20:13:47 +0200399 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200400 return;
401
402 hdev->voice_setting = setting;
403
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300404 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200405
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200406 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200407 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200408}
409
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300410static void hci_cc_write_voice_setting(struct hci_dev *hdev,
411 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200412{
413 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200414 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 void *sent;
416
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300417 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Marcel Holtmannf383f272008-07-14 20:13:47 +0200419 if (status)
420 return;
421
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200422 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
423 if (!sent)
424 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Marcel Holtmannf383f272008-07-14 20:13:47 +0200426 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Marcel Holtmannf383f272008-07-14 20:13:47 +0200428 if (hdev->voice_setting == setting)
429 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Marcel Holtmannf383f272008-07-14 20:13:47 +0200431 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300433 BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200434
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200435 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200436 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437}
438
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200439static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200441 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300443 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Johan Hedberg23bb5762010-12-21 23:01:27 +0200445 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
Marcel Holtmann333140b2008-07-14 20:13:48 +0200448static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
449{
450 __u8 status = *((__u8 *) skb->data);
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300451 struct hci_cp_write_ssp_mode *sent;
Marcel Holtmann333140b2008-07-14 20:13:48 +0200452
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300453 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann333140b2008-07-14 20:13:48 +0200454
Marcel Holtmann333140b2008-07-14 20:13:48 +0200455 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
456 if (!sent)
457 return;
458
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300459 if (!status) {
460 if (sent->mode)
461 hdev->host_features[0] |= LMP_HOST_SSP;
462 else
463 hdev->host_features[0] &= ~LMP_HOST_SSP;
464 }
465
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200466 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300467 mgmt_ssp_enable_complete(hdev, sent->mode, status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200468 else if (!status) {
Johan Hedberg5ed8eb22012-10-25 00:09:51 +0300469 if (sent->mode)
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200470 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
471 else
472 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
473 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200474}
475
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200476static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
477{
478 struct hci_rp_read_local_version *rp = (void *) skb->data;
479
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300480 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200481
482 if (rp->status)
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200483 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200484
485 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200486 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200487 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200488 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200489 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200490
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300491 BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300492 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200493
Andrei Emeltchenko28b8df72012-02-24 12:45:44 +0200494done:
495 hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200496}
497
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300498static void hci_cc_read_local_commands(struct hci_dev *hdev,
499 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200500{
501 struct hci_rp_read_local_commands *rp = (void *) skb->data;
502
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300503 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200504
Johan Hedberg2177bab2013-03-05 20:37:43 +0200505 if (!rp->status)
506 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200507
Johan Hedbergd5859e22011-01-25 01:19:58 +0200508 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200509}
510
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300511static void hci_cc_read_local_features(struct hci_dev *hdev,
512 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200513{
514 struct hci_rp_read_local_features *rp = (void *) skb->data;
515
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300516 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200517
518 if (rp->status)
519 return;
520
521 memcpy(hdev->features, rp->features, 8);
522
523 /* Adjust default settings according to features
524 * supported by device. */
525
526 if (hdev->features[0] & LMP_3SLOT)
527 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
528
529 if (hdev->features[0] & LMP_5SLOT)
530 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
531
532 if (hdev->features[1] & LMP_HV2) {
533 hdev->pkt_type |= (HCI_HV2);
534 hdev->esco_type |= (ESCO_HV2);
535 }
536
537 if (hdev->features[1] & LMP_HV3) {
538 hdev->pkt_type |= (HCI_HV3);
539 hdev->esco_type |= (ESCO_HV3);
540 }
541
Andre Guedes45db810f2012-07-24 15:03:49 -0300542 if (lmp_esco_capable(hdev))
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200543 hdev->esco_type |= (ESCO_EV3);
544
545 if (hdev->features[4] & LMP_EV4)
546 hdev->esco_type |= (ESCO_EV4);
547
548 if (hdev->features[4] & LMP_EV5)
549 hdev->esco_type |= (ESCO_EV5);
550
Marcel Holtmannefc76882009-02-06 09:13:37 +0100551 if (hdev->features[5] & LMP_EDR_ESCO_2M)
552 hdev->esco_type |= (ESCO_2EV3);
553
554 if (hdev->features[5] & LMP_EDR_ESCO_3M)
555 hdev->esco_type |= (ESCO_3EV3);
556
557 if (hdev->features[5] & LMP_EDR_3S_ESCO)
558 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
559
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200560 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300561 hdev->features[0], hdev->features[1],
562 hdev->features[2], hdev->features[3],
563 hdev->features[4], hdev->features[5],
564 hdev->features[6], hdev->features[7]);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200565}
566
Andre Guedes971e3a42011-06-30 19:20:52 -0300567static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300568 struct sk_buff *skb)
Andre Guedes971e3a42011-06-30 19:20:52 -0300569{
570 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
571
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300572 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andre Guedes971e3a42011-06-30 19:20:52 -0300573
574 if (rp->status)
Johan Hedberg8f984df2012-02-28 01:07:22 +0200575 goto done;
Andre Guedes971e3a42011-06-30 19:20:52 -0300576
Andre Guedesb5b32b62011-12-30 10:34:04 -0300577 switch (rp->page) {
578 case 0:
579 memcpy(hdev->features, rp->features, 8);
580 break;
581 case 1:
582 memcpy(hdev->host_features, rp->features, 8);
583 break;
584 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300585
Johan Hedberg8f984df2012-02-28 01:07:22 +0200586done:
Andre Guedes971e3a42011-06-30 19:20:52 -0300587 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
588}
589
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200590static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300591 struct sk_buff *skb)
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200592{
593 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
594
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300595 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200596
597 if (rp->status)
598 return;
599
600 hdev->flow_ctl_mode = rp->mode;
601
602 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
603}
604
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200605static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
606{
607 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
608
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300609 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200610
611 if (rp->status)
612 return;
613
614 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
615 hdev->sco_mtu = rp->sco_mtu;
616 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
617 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
618
619 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
620 hdev->sco_mtu = 64;
621 hdev->sco_pkts = 8;
622 }
623
624 hdev->acl_cnt = hdev->acl_pkts;
625 hdev->sco_cnt = hdev->sco_pkts;
626
Gustavo Padovan807deac2012-05-17 00:36:24 -0300627 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
628 hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200629}
630
631static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
632{
633 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
634
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300635 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200636
637 if (!rp->status)
638 bacpy(&hdev->bdaddr, &rp->bdaddr);
639
Johan Hedberg23bb5762010-12-21 23:01:27 +0200640 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
641}
642
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200643static void hci_cc_read_data_block_size(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300644 struct sk_buff *skb)
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200645{
646 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
647
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300648 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200649
650 if (rp->status)
651 return;
652
653 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
654 hdev->block_len = __le16_to_cpu(rp->block_len);
655 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
656
657 hdev->block_cnt = hdev->num_blocks;
658
659 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300660 hdev->block_cnt, hdev->block_len);
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200661
662 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
663}
664
Johan Hedberg23bb5762010-12-21 23:01:27 +0200665static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
666{
667 __u8 status = *((__u8 *) skb->data);
668
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300669 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200670
671 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200672}
673
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300674static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300675 struct sk_buff *skb)
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300676{
677 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
678
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300679 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300680
681 if (rp->status)
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300682 goto a2mp_rsp;
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300683
684 hdev->amp_status = rp->amp_status;
685 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
686 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
687 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
688 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
689 hdev->amp_type = rp->amp_type;
690 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
691 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
692 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
693 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
694
695 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
Andrei Emeltchenko8e2a0d92012-09-27 17:26:08 +0300696
697a2mp_rsp:
698 a2mp_send_getinfo_rsp(hdev);
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300699}
700
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300701static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
702 struct sk_buff *skb)
703{
704 struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
705 struct amp_assoc *assoc = &hdev->loc_assoc;
706 size_t rem_len, frag_len;
707
708 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
709
710 if (rp->status)
711 goto a2mp_rsp;
712
713 frag_len = skb->len - sizeof(*rp);
714 rem_len = __le16_to_cpu(rp->rem_len);
715
716 if (rem_len > frag_len) {
Andrei Emeltchenko2e430be32012-09-28 14:44:23 +0300717 BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300718
719 memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
720 assoc->offset += frag_len;
721
722 /* Read other fragments */
723 amp_read_loc_assoc_frag(hdev, rp->phy_handle);
724
725 return;
726 }
727
728 memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
729 assoc->len = assoc->offset + rem_len;
730 assoc->offset = 0;
731
732a2mp_rsp:
733 /* Send A2MP Rsp when all fragments are received */
734 a2mp_send_getampassoc_rsp(hdev, rp->status);
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +0300735 a2mp_send_create_phy_link_req(hdev, rp->status);
Andrei Emeltchenko903e4542012-09-27 17:26:09 +0300736}
737
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200738static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300739 struct sk_buff *skb)
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200740{
741 __u8 status = *((__u8 *) skb->data);
742
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300743 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200744
745 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
746}
747
Johan Hedbergd5859e22011-01-25 01:19:58 +0200748static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
749{
750 __u8 status = *((__u8 *) skb->data);
751
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300752 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200753
754 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
755}
756
757static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300758 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200759{
760 __u8 status = *((__u8 *) skb->data);
761
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300762 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200763
764 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
765}
766
767static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300768 struct sk_buff *skb)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200769{
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700770 struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200771
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300772 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200773
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700774 if (!rp->status)
775 hdev->inq_tx_power = rp->tx_power;
776
777 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200778}
779
780static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
781{
782 __u8 status = *((__u8 *) skb->data);
783
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300784 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200785
786 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
787}
788
Johan Hedberg980e1a52011-01-22 06:10:07 +0200789static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
790{
791 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
792 struct hci_cp_pin_code_reply *cp;
793 struct hci_conn *conn;
794
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300795 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200796
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200797 hci_dev_lock(hdev);
798
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200799 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200800 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200801
Mikel Astizfa1bd912012-08-09 09:52:29 +0200802 if (rp->status)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200803 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200804
805 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
806 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200807 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200808
809 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
810 if (conn)
811 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200812
813unlock:
814 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200815}
816
817static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
818{
819 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
820
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300821 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200822
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200823 hci_dev_lock(hdev);
824
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200825 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200826 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300827 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200828
829 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200830}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200831
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300832static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
833 struct sk_buff *skb)
834{
835 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
836
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300837 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300838
839 if (rp->status)
840 return;
841
842 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
843 hdev->le_pkts = rp->le_max_pkt;
844
845 hdev->le_cnt = hdev->le_pkts;
846
847 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
848
849 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
850}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200851
Johan Hedberg60e77322013-01-22 14:01:59 +0200852static void hci_cc_le_read_local_features(struct hci_dev *hdev,
853 struct sk_buff *skb)
854{
855 struct hci_rp_le_read_local_features *rp = (void *) skb->data;
856
857 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
858
859 if (!rp->status)
860 memcpy(hdev->le_features, rp->features, 8);
861
862 hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
863}
864
Johan Hedberg8fa19092012-10-19 20:57:49 +0300865static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
866 struct sk_buff *skb)
867{
868 struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
869
870 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
871
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100872 if (!rp->status) {
Johan Hedberg8fa19092012-10-19 20:57:49 +0300873 hdev->adv_tx_power = rp->tx_power;
Johan Hedberg3f0f5242012-11-08 01:23:00 +0100874 if (!test_bit(HCI_INIT, &hdev->flags))
875 hci_update_ad(hdev);
876 }
Johan Hedberg8fa19092012-10-19 20:57:49 +0300877
878 hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
879}
880
Johan Hedberge36b04c2012-10-19 20:57:47 +0300881static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
882{
883 __u8 status = *((__u8 *) skb->data);
884
885 BT_DBG("%s status 0x%2.2x", hdev->name, status);
886
887 hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
888}
889
Johan Hedberga5c29682011-02-19 12:05:57 -0300890static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
891{
892 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
893
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300894 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300895
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200896 hci_dev_lock(hdev);
897
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200898 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300899 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
900 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200901
902 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300903}
904
905static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300906 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -0300907{
908 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
909
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300910 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Johan Hedberga5c29682011-02-19 12:05:57 -0300911
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200912 hci_dev_lock(hdev);
913
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200914 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200915 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300916 ACL_LINK, 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200917
918 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300919}
920
Brian Gix1143d452011-11-23 08:28:34 -0800921static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
922{
923 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
924
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300925 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800926
927 hci_dev_lock(hdev);
928
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200929 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200930 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300931 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800932
933 hci_dev_unlock(hdev);
934}
935
936static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300937 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -0800938{
939 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
940
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300941 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800942
943 hci_dev_lock(hdev);
944
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200945 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -0800946 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300947 ACL_LINK, 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800948
949 hci_dev_unlock(hdev);
950}
951
Szymon Jancc35938b2011-03-22 13:12:21 +0100952static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -0300953 struct sk_buff *skb)
Szymon Jancc35938b2011-03-22 13:12:21 +0100954{
955 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
956
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +0300957 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Szymon Jancc35938b2011-03-22 13:12:21 +0100958
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200959 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +0200960 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +0100961 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200962 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +0100963}
964
Johan Hedbergc1d5dc42012-11-08 01:23:01 +0100965static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
966{
967 __u8 *sent, status = *((__u8 *) skb->data);
968
969 BT_DBG("%s status 0x%2.2x", hdev->name, status);
970
971 sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
972 if (!sent)
973 return;
974
975 hci_dev_lock(hdev);
976
977 if (!status) {
978 if (*sent)
979 set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
980 else
981 clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
982 }
983
984 hci_dev_unlock(hdev);
985
986 if (!test_bit(HCI_INIT, &hdev->flags))
987 hci_update_ad(hdev);
988
989 hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
990}
991
Andre Guedes07f7fa52011-12-02 21:13:31 +0900992static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
993{
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);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -0300997
998 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -0300999
1000 if (status) {
1001 hci_dev_lock(hdev);
1002 mgmt_start_discovery_failed(hdev, status);
1003 hci_dev_unlock(hdev);
1004 return;
1005 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001006}
1007
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001008static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001009 struct sk_buff *skb)
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001010{
1011 struct hci_cp_le_set_scan_enable *cp;
1012 __u8 status = *((__u8 *) skb->data);
1013
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001014 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001015
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001016 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1017 if (!cp)
1018 return;
1019
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001020 switch (cp->enable) {
1021 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001022 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1023
Andre Guedes3fd24152012-02-03 17:48:01 -03001024 if (status) {
1025 hci_dev_lock(hdev);
1026 mgmt_start_discovery_failed(hdev, status);
1027 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001028 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001029 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001030
Andre Guedesd23264a2011-11-25 20:53:38 -03001031 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1032
Andre Guedesa8f13c82011-09-09 18:56:24 -03001033 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001034 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001035 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001036 break;
1037
1038 case LE_SCANNING_DISABLED:
Andre Guedesc9ecc482012-03-15 16:52:08 -03001039 if (status) {
1040 hci_dev_lock(hdev);
1041 mgmt_stop_discovery_failed(hdev, status);
1042 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001043 return;
Andre Guedesc9ecc482012-03-15 16:52:08 -03001044 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001045
Andre Guedesd23264a2011-11-25 20:53:38 -03001046 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1047
Andre Guedesbc3dd332012-03-06 19:37:06 -03001048 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1049 hdev->discovery.state == DISCOVERY_FINDING) {
Andre Guedes5e0452c2012-02-17 20:39:38 -03001050 mgmt_interleaved_discovery(hdev);
1051 } else {
1052 hci_dev_lock(hdev);
1053 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1054 hci_dev_unlock(hdev);
1055 }
1056
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001057 break;
1058
1059 default:
1060 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1061 break;
Andre Guedes35815082011-05-26 16:23:53 -03001062 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001063}
1064
Johan Hedbergcf1d0812013-01-22 14:02:00 +02001065static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1066 struct sk_buff *skb)
1067{
1068 struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1069
1070 BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1071
1072 if (!rp->status)
1073 hdev->le_white_list_size = rp->size;
1074
1075 hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
1076}
1077
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001078static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1079{
1080 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1081
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001082 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001083
1084 if (rp->status)
1085 return;
1086
1087 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1088}
1089
1090static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1091{
1092 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1093
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001094 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001095
1096 if (rp->status)
1097 return;
1098
1099 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1100}
1101
Johan Hedberg9b008c02013-01-22 14:02:01 +02001102static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
1103 struct sk_buff *skb)
1104{
1105 struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
1106
1107 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1108
1109 if (!rp->status)
1110 memcpy(hdev->le_states, rp->le_states, 8);
1111
1112 hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status);
1113}
1114
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001115static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1116 struct sk_buff *skb)
Andre Guedesf9b49302011-06-30 19:20:53 -03001117{
Johan Hedberg06199cf2012-02-22 16:37:11 +02001118 struct hci_cp_write_le_host_supported *sent;
Andre Guedesf9b49302011-06-30 19:20:53 -03001119 __u8 status = *((__u8 *) skb->data);
1120
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001121 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001122
Johan Hedberg06199cf2012-02-22 16:37:11 +02001123 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
Johan Hedberg8f984df2012-02-28 01:07:22 +02001124 if (!sent)
Andre Guedesf9b49302011-06-30 19:20:53 -03001125 return;
1126
Johan Hedberg8f984df2012-02-28 01:07:22 +02001127 if (!status) {
1128 if (sent->le)
1129 hdev->host_features[0] |= LMP_HOST_LE;
1130 else
1131 hdev->host_features[0] &= ~LMP_HOST_LE;
Johan Hedberg53b2caa2012-10-24 21:11:59 +03001132
1133 if (sent->simul)
1134 hdev->host_features[0] |= LMP_HOST_LE_BREDR;
1135 else
1136 hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
Johan Hedberg8f984df2012-02-28 01:07:22 +02001137 }
1138
1139 if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001140 !test_bit(HCI_INIT, &hdev->flags))
Johan Hedberg8f984df2012-02-28 01:07:22 +02001141 mgmt_le_enable_complete(hdev, sent->le, status);
1142
1143 hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
Andre Guedesf9b49302011-06-30 19:20:53 -03001144}
1145
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001146static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
1147 struct sk_buff *skb)
1148{
1149 struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
1150
1151 BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
1152 hdev->name, rp->status, rp->phy_handle);
1153
1154 if (rp->status)
1155 return;
1156
1157 amp_write_rem_assoc_continue(hdev, rp->phy_handle);
1158}
1159
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001160static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001161{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001162 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001163
1164 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001165 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001166 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001167 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001168 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001169 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001170 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001171 return;
1172 }
1173
Andre Guedes89352e72011-11-04 14:16:53 -03001174 set_bit(HCI_INQUIRY, &hdev->flags);
1175
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001176 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001177 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001178 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001179}
1180
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001181static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001183 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001186 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001187
1188 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 if (!cp)
1190 return;
1191
1192 hci_dev_lock(hdev);
1193
1194 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1195
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001196 BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198 if (status) {
1199 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001200 if (status != 0x0c || conn->attempt > 2) {
1201 conn->state = BT_CLOSED;
1202 hci_proto_connect_cfm(conn, status);
1203 hci_conn_del(conn);
1204 } else
1205 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 }
1207 } else {
1208 if (!conn) {
1209 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1210 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001211 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 conn->link_mode |= HCI_LM_MASTER;
1213 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001214 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 }
1216 }
1217
1218 hci_dev_unlock(hdev);
1219}
1220
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001221static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001223 struct hci_cp_add_sco *cp;
1224 struct hci_conn *acl, *sco;
1225 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001227 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001228
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001229 if (!status)
1230 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001232 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1233 if (!cp)
1234 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001236 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001238 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001239
1240 hci_dev_lock(hdev);
1241
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001242 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001243 if (acl) {
1244 sco = acl->link;
1245 if (sco) {
1246 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001247
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001248 hci_proto_connect_cfm(sco, status);
1249 hci_conn_del(sco);
1250 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001251 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001252
1253 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254}
1255
Marcel Holtmannf8558552008-07-14 20:13:49 +02001256static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1257{
1258 struct hci_cp_auth_requested *cp;
1259 struct hci_conn *conn;
1260
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001261 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001262
1263 if (!status)
1264 return;
1265
1266 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1267 if (!cp)
1268 return;
1269
1270 hci_dev_lock(hdev);
1271
1272 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1273 if (conn) {
1274 if (conn->state == BT_CONFIG) {
1275 hci_proto_connect_cfm(conn, status);
1276 hci_conn_put(conn);
1277 }
1278 }
1279
1280 hci_dev_unlock(hdev);
1281}
1282
1283static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1284{
1285 struct hci_cp_set_conn_encrypt *cp;
1286 struct hci_conn *conn;
1287
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001288 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannf8558552008-07-14 20:13:49 +02001289
1290 if (!status)
1291 return;
1292
1293 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1294 if (!cp)
1295 return;
1296
1297 hci_dev_lock(hdev);
1298
1299 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1300 if (conn) {
1301 if (conn->state == BT_CONFIG) {
1302 hci_proto_connect_cfm(conn, status);
1303 hci_conn_put(conn);
1304 }
1305 }
1306
1307 hci_dev_unlock(hdev);
1308}
1309
Johan Hedberg127178d2010-11-18 22:22:29 +02001310static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001311 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001312{
Johan Hedberg392599b2010-11-18 22:22:28 +02001313 if (conn->state != BT_CONFIG || !conn->out)
1314 return 0;
1315
Johan Hedberg765c2a92011-01-19 12:06:52 +05301316 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001317 return 0;
1318
1319 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001320 * devices with sec_level HIGH or if MITM protection is requested */
Gustavo Padovan807deac2012-05-17 00:36:24 -03001321 if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1322 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +02001323 return 0;
1324
Johan Hedberg392599b2010-11-18 22:22:28 +02001325 return 1;
1326}
1327
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001328static int hci_resolve_name(struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001329 struct inquiry_entry *e)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001330{
1331 struct hci_cp_remote_name_req cp;
1332
1333 memset(&cp, 0, sizeof(cp));
1334
1335 bacpy(&cp.bdaddr, &e->data.bdaddr);
1336 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1337 cp.pscan_mode = e->data.pscan_mode;
1338 cp.clock_offset = e->data.clock_offset;
1339
1340 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1341}
1342
Johan Hedbergb644ba32012-01-17 21:48:47 +02001343static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001344{
1345 struct discovery_state *discov = &hdev->discovery;
1346 struct inquiry_entry *e;
1347
Johan Hedbergb644ba32012-01-17 21:48:47 +02001348 if (list_empty(&discov->resolve))
1349 return false;
1350
1351 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
Ram Malovanyc8100892012-07-19 10:26:09 +03001352 if (!e)
1353 return false;
1354
Johan Hedbergb644ba32012-01-17 21:48:47 +02001355 if (hci_resolve_name(hdev, e) == 0) {
1356 e->name_state = NAME_PENDING;
1357 return true;
1358 }
1359
1360 return false;
1361}
1362
1363static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001364 bdaddr_t *bdaddr, u8 *name, u8 name_len)
Johan Hedbergb644ba32012-01-17 21:48:47 +02001365{
1366 struct discovery_state *discov = &hdev->discovery;
1367 struct inquiry_entry *e;
1368
1369 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001370 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
1371 name_len, conn->dev_class);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001372
1373 if (discov->state == DISCOVERY_STOPPED)
1374 return;
1375
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001376 if (discov->state == DISCOVERY_STOPPING)
1377 goto discov_complete;
1378
1379 if (discov->state != DISCOVERY_RESOLVING)
1380 return;
1381
1382 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
Ram Malovany7cc83802012-07-19 10:26:10 +03001383 /* If the device was not found in a list of found devices names of which
1384 * are pending. there is no need to continue resolving a next name as it
1385 * will be done upon receiving another Remote Name Request Complete
1386 * Event */
1387 if (!e)
1388 return;
1389
1390 list_del(&e->list);
1391 if (name) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001392 e->name_state = NAME_KNOWN;
Ram Malovany7cc83802012-07-19 10:26:10 +03001393 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1394 e->data.rssi, name, name_len);
Ram Malovanyc3e7c0d2012-07-19 10:26:11 +03001395 } else {
1396 e->name_state = NAME_NOT_KNOWN;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001397 }
1398
Johan Hedbergb644ba32012-01-17 21:48:47 +02001399 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001400 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001401
1402discov_complete:
1403 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1404}
1405
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001406static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1407{
Johan Hedberg127178d2010-11-18 22:22:29 +02001408 struct hci_cp_remote_name_req *cp;
1409 struct hci_conn *conn;
1410
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001411 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001412
1413 /* If successful wait for the name req complete event before
1414 * checking for the need to do authentication */
1415 if (!status)
1416 return;
1417
1418 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1419 if (!cp)
1420 return;
1421
1422 hci_dev_lock(hdev);
1423
1424 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001425
1426 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1427 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1428
Johan Hedberg79c6c702011-04-28 11:28:55 -07001429 if (!conn)
1430 goto unlock;
1431
1432 if (!hci_outgoing_auth_needed(hdev, conn))
1433 goto unlock;
1434
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001435 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001436 struct hci_cp_auth_requested cp;
1437 cp.handle = __cpu_to_le16(conn->handle);
1438 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1439 }
1440
Johan Hedberg79c6c702011-04-28 11:28:55 -07001441unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001442 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001443}
1444
Marcel Holtmann769be972008-07-14 20:13:49 +02001445static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1446{
1447 struct hci_cp_read_remote_features *cp;
1448 struct hci_conn *conn;
1449
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001450 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001451
1452 if (!status)
1453 return;
1454
1455 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1456 if (!cp)
1457 return;
1458
1459 hci_dev_lock(hdev);
1460
1461 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1462 if (conn) {
1463 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001464 hci_proto_connect_cfm(conn, status);
1465 hci_conn_put(conn);
1466 }
1467 }
1468
1469 hci_dev_unlock(hdev);
1470}
1471
1472static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1473{
1474 struct hci_cp_read_remote_ext_features *cp;
1475 struct hci_conn *conn;
1476
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001477 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmann769be972008-07-14 20:13:49 +02001478
1479 if (!status)
1480 return;
1481
1482 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1483 if (!cp)
1484 return;
1485
1486 hci_dev_lock(hdev);
1487
1488 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1489 if (conn) {
1490 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001491 hci_proto_connect_cfm(conn, status);
1492 hci_conn_put(conn);
1493 }
1494 }
1495
1496 hci_dev_unlock(hdev);
1497}
1498
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001499static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1500{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001501 struct hci_cp_setup_sync_conn *cp;
1502 struct hci_conn *acl, *sco;
1503 __u16 handle;
1504
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001505 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001506
1507 if (!status)
1508 return;
1509
1510 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1511 if (!cp)
1512 return;
1513
1514 handle = __le16_to_cpu(cp->handle);
1515
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001516 BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001517
1518 hci_dev_lock(hdev);
1519
1520 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001521 if (acl) {
1522 sco = acl->link;
1523 if (sco) {
1524 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001525
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001526 hci_proto_connect_cfm(sco, status);
1527 hci_conn_del(sco);
1528 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001529 }
1530
1531 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001532}
1533
1534static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1535{
1536 struct hci_cp_sniff_mode *cp;
1537 struct hci_conn *conn;
1538
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001539 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001540
1541 if (!status)
1542 return;
1543
1544 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1545 if (!cp)
1546 return;
1547
1548 hci_dev_lock(hdev);
1549
1550 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001551 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001552 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001553
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001554 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001555 hci_sco_setup(conn, status);
1556 }
1557
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001558 hci_dev_unlock(hdev);
1559}
1560
1561static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1562{
1563 struct hci_cp_exit_sniff_mode *cp;
1564 struct hci_conn *conn;
1565
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001566 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001567
1568 if (!status)
1569 return;
1570
1571 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1572 if (!cp)
1573 return;
1574
1575 hci_dev_lock(hdev);
1576
1577 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001578 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001579 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001580
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001581 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001582 hci_sco_setup(conn, status);
1583 }
1584
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001585 hci_dev_unlock(hdev);
1586}
1587
Johan Hedberg88c3df12012-02-09 14:27:38 +02001588static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1589{
1590 struct hci_cp_disconnect *cp;
1591 struct hci_conn *conn;
1592
1593 if (!status)
1594 return;
1595
1596 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1597 if (!cp)
1598 return;
1599
1600 hci_dev_lock(hdev);
1601
1602 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1603 if (conn)
1604 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001605 conn->dst_type, status);
Johan Hedberg88c3df12012-02-09 14:27:38 +02001606
1607 hci_dev_unlock(hdev);
1608}
1609
Ville Tervofcd89c02011-02-10 22:38:47 -03001610static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1611{
Ville Tervofcd89c02011-02-10 22:38:47 -03001612 struct hci_conn *conn;
1613
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001614 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Ville Tervofcd89c02011-02-10 22:38:47 -03001615
Ville Tervofcd89c02011-02-10 22:38:47 -03001616 if (status) {
Andre Guedesf00a06a2012-07-27 15:10:13 -03001617 hci_dev_lock(hdev);
Ville Tervofcd89c02011-02-10 22:38:47 -03001618
Andre Guedes0c95ab72012-07-27 15:10:14 -03001619 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001620 if (!conn) {
1621 hci_dev_unlock(hdev);
1622 return;
1623 }
1624
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001625 BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
Andre Guedesf00a06a2012-07-27 15:10:13 -03001626
1627 conn->state = BT_CLOSED;
Andre Guedes0c95ab72012-07-27 15:10:14 -03001628 mgmt_connect_failed(hdev, &conn->dst, conn->type,
Andre Guedesf00a06a2012-07-27 15:10:13 -03001629 conn->dst_type, status);
1630 hci_proto_connect_cfm(conn, status);
1631 hci_conn_del(conn);
1632
1633 hci_dev_unlock(hdev);
1634 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001635}
1636
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001637static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1638{
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001639 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001640}
1641
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001642static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1643{
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001644 struct hci_cp_create_phy_link *cp;
1645
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001646 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001647
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03001648 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
1649 if (!cp)
1650 return;
1651
Andrei Emeltchenkoe58917b2012-10-31 15:46:33 +02001652 hci_dev_lock(hdev);
1653
1654 if (status) {
1655 struct hci_conn *hcon;
1656
1657 hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1658 if (hcon)
1659 hci_conn_del(hcon);
1660 } else {
1661 amp_write_remote_assoc(hdev, cp->phy_handle);
1662 }
1663
1664 hci_dev_unlock(hdev);
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03001665}
1666
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03001667static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1668{
1669 struct hci_cp_accept_phy_link *cp;
1670
1671 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1672
1673 if (status)
1674 return;
1675
1676 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1677 if (!cp)
1678 return;
1679
1680 amp_write_remote_assoc(hdev, cp->phy_handle);
1681}
1682
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02001683static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
1684{
1685 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1686}
1687
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001688static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001689{
1690 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001691 struct discovery_state *discov = &hdev->discovery;
1692 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001693
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001694 BT_DBG("%s status 0x%2.2x", hdev->name, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001695
Johan Hedberg9238f362013-03-05 20:37:48 +02001696 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
Johan Hedberg23bb5762010-12-21 23:01:27 +02001697 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001698
1699 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001700
1701 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1702 return;
1703
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001704 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001705 return;
1706
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001707 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001708
Andre Guedes343f9352012-02-17 20:39:37 -03001709 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001710 goto unlock;
1711
1712 if (list_empty(&discov->resolve)) {
1713 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1714 goto unlock;
1715 }
1716
1717 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1718 if (e && hci_resolve_name(hdev, e) == 0) {
1719 e->name_state = NAME_PENDING;
1720 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1721 } else {
1722 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1723 }
1724
1725unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001726 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001727}
1728
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001729static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001731 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001732 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 int num_rsp = *((__u8 *) skb->data);
1734
1735 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1736
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001737 if (!num_rsp)
1738 return;
1739
Andre Guedes1519cc12012-03-21 00:03:38 -03001740 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
1741 return;
1742
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001744
Johan Hedberge17acd42011-03-30 23:57:16 +03001745 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001746 bool name_known, ssp;
Johan Hedberg31754052012-01-04 13:39:52 +02001747
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 bacpy(&data.bdaddr, &info->bdaddr);
1749 data.pscan_rep_mode = info->pscan_rep_mode;
1750 data.pscan_period_mode = info->pscan_period_mode;
1751 data.pscan_mode = info->pscan_mode;
1752 memcpy(data.dev_class, info->dev_class, 3);
1753 data.clock_offset = info->clock_offset;
1754 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001755 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001756
Johan Hedberg388fc8f2012-02-23 00:38:59 +02001757 name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02001758 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001759 info->dev_class, 0, !name_known, ssp, NULL,
1760 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001762
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 hci_dev_unlock(hdev);
1764}
1765
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001766static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001768 struct hci_ev_conn_complete *ev = (void *) skb->data;
1769 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001771 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001772
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001774
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001775 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001776 if (!conn) {
1777 if (ev->link_type != SCO_LINK)
1778 goto unlock;
1779
1780 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1781 if (!conn)
1782 goto unlock;
1783
1784 conn->type = SCO_LINK;
1785 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001786
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001787 if (!ev->status) {
1788 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001789
1790 if (conn->type == ACL_LINK) {
1791 conn->state = BT_CONFIG;
1792 hci_conn_hold(conn);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001793
1794 if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1795 !hci_find_link_key(hdev, &ev->bdaddr))
1796 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1797 else
1798 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001799 } else
1800 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001801
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001802 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001803 hci_conn_add_sysfs(conn);
1804
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001805 if (test_bit(HCI_AUTH, &hdev->flags))
1806 conn->link_mode |= HCI_LM_AUTH;
1807
1808 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1809 conn->link_mode |= HCI_LM_ENCRYPT;
1810
1811 /* Get remote features */
1812 if (conn->type == ACL_LINK) {
1813 struct hci_cp_read_remote_features cp;
1814 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001815 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001816 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001817 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001818
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001819 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001820 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001821 struct hci_cp_change_conn_ptype cp;
1822 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001823 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001824 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
1825 &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001826 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001827 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001828 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001829 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001830 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001831 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001832 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001833
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001834 if (conn->type == ACL_LINK)
1835 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001836
Marcel Holtmann769be972008-07-14 20:13:49 +02001837 if (ev->status) {
1838 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001839 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001840 } else if (ev->link_type != ACL_LINK)
1841 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001842
1843unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001845
1846 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847}
1848
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001849void hci_conn_accept(struct hci_conn *conn, int mask)
1850{
1851 struct hci_dev *hdev = conn->hdev;
1852
1853 BT_DBG("conn %p", conn);
1854
1855 conn->state = BT_CONFIG;
1856
1857 if (!lmp_esco_capable(hdev)) {
1858 struct hci_cp_accept_conn_req cp;
1859
1860 bacpy(&cp.bdaddr, &conn->dst);
1861
1862 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1863 cp.role = 0x00; /* Become master */
1864 else
1865 cp.role = 0x01; /* Remain slave */
1866
1867 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
1868 } else /* lmp_esco_capable(hdev)) */ {
1869 struct hci_cp_accept_sync_conn_req cp;
1870
1871 bacpy(&cp.bdaddr, &conn->dst);
1872 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1873
1874 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1875 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1876 cp.max_latency = __constant_cpu_to_le16(0xffff);
1877 cp.content_format = cpu_to_le16(hdev->voice_setting);
1878 cp.retrans_effort = 0xff;
1879
1880 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1881 sizeof(cp), &cp);
1882 }
1883}
1884
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001885static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001887 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 int mask = hdev->link_mode;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001889 __u8 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001891 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
Gustavo Padovan807deac2012-05-17 00:36:24 -03001892 ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001894 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
1895 &flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Szymon Janc138d22e2011-02-17 16:44:23 +01001897 if ((mask & HCI_LM_ACCEPT) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03001898 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001900 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902
1903 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001904
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001905 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1906 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001907 memcpy(ie->data.dev_class, ev->dev_class, 3);
1908
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001909 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
1910 &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001912 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1913 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001914 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 hci_dev_unlock(hdev);
1916 return;
1917 }
1918 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001919
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 memcpy(conn->dev_class, ev->dev_class, 3);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 hci_dev_unlock(hdev);
1923
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001924 if (ev->link_type == ACL_LINK ||
1925 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001926 struct hci_cp_accept_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001927 conn->state = BT_CONNECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001929 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001931 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1932 cp.role = 0x00; /* Become master */
1933 else
1934 cp.role = 0x01; /* Remain slave */
1935
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001936 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
1937 &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001938 } else if (!(flags & HCI_PROTO_DEFER)) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001939 struct hci_cp_accept_sync_conn_req cp;
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001940 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001941
1942 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001943 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001944
Andrei Emeltchenko82781e62012-05-25 11:38:27 +03001945 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1946 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
1947 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001948 cp.content_format = cpu_to_le16(hdev->voice_setting);
1949 cp.retrans_effort = 0xff;
1950
1951 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001952 sizeof(cp), &cp);
Frédéric Dalleau20714bf2012-11-21 10:51:12 +01001953 } else {
1954 conn->state = BT_CONNECT2;
1955 hci_proto_connect_cfm(conn, 0);
1956 hci_conn_put(conn);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 } else {
1959 /* Connection rejected */
1960 struct hci_cp_reject_conn_req cp;
1961
1962 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001963 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001964 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 }
1966}
1967
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02001968static u8 hci_to_mgmt_reason(u8 err)
1969{
1970 switch (err) {
1971 case HCI_ERROR_CONNECTION_TIMEOUT:
1972 return MGMT_DEV_DISCONN_TIMEOUT;
1973 case HCI_ERROR_REMOTE_USER_TERM:
1974 case HCI_ERROR_REMOTE_LOW_RESOURCES:
1975 case HCI_ERROR_REMOTE_POWER_OFF:
1976 return MGMT_DEV_DISCONN_REMOTE;
1977 case HCI_ERROR_LOCAL_HOST_TERM:
1978 return MGMT_DEV_DISCONN_LOCAL_HOST;
1979 default:
1980 return MGMT_DEV_DISCONN_UNKNOWN;
1981 }
1982}
1983
Gustavo Padovan6039aa72012-05-23 04:04:18 -03001984static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001986 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001987 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03001989 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 hci_dev_lock(hdev);
1992
Marcel Holtmann04837f62006-07-03 10:02:33 +02001993 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001994 if (!conn)
1995 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001996
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001997 if (ev->status == 0)
1998 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
Johan Hedbergb644ba32012-01-17 21:48:47 +02002000 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002001 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002002 if (ev->status) {
Johan Hedberg88c3df12012-02-09 14:27:38 +02002003 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002004 conn->dst_type, ev->status);
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002005 } else {
2006 u8 reason = hci_to_mgmt_reason(ev->reason);
2007
Johan Hedbergafc747a2012-01-15 18:11:07 +02002008 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02002009 conn->dst_type, reason);
2010 }
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002011 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002012
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002013 if (ev->status == 0) {
Vishal Agarwal6ec5bca2012-04-16 14:44:44 +05302014 if (conn->type == ACL_LINK && conn->flush_key)
2015 hci_remove_link_key(hdev, &conn->dst);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02002016 hci_proto_disconn_cfm(conn, ev->reason);
2017 hci_conn_del(conn);
2018 }
Johan Hedbergf7520542011-01-20 12:34:39 +02002019
2020unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 hci_dev_unlock(hdev);
2022}
2023
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002024static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002025{
2026 struct hci_ev_auth_complete *ev = (void *) skb->data;
2027 struct hci_conn *conn;
2028
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002029 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002030
2031 hci_dev_lock(hdev);
2032
2033 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002034 if (!conn)
2035 goto unlock;
2036
2037 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002038 if (!hci_conn_ssp_enabled(conn) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002039 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002040 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03002041 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002042 conn->link_mode |= HCI_LM_AUTH;
2043 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03002044 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002045 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02002046 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002047 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002048 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002049
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002050 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2051 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002052
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002053 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02002054 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002055 struct hci_cp_set_conn_encrypt cp;
2056 cp.handle = ev->handle;
2057 cp.encrypt = 0x01;
2058 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002059 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002060 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002061 conn->state = BT_CONNECTED;
2062 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002063 hci_conn_put(conn);
2064 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002065 } else {
2066 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002067
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002068 hci_conn_hold(conn);
2069 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2070 hci_conn_put(conn);
2071 }
2072
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002073 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002074 if (!ev->status) {
2075 struct hci_cp_set_conn_encrypt cp;
2076 cp.handle = ev->handle;
2077 cp.encrypt = 0x01;
2078 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03002079 &cp);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002080 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002081 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002082 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002083 }
2084 }
2085
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02002086unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002087 hci_dev_unlock(hdev);
2088}
2089
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002090static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002091{
Johan Hedberg127178d2010-11-18 22:22:29 +02002092 struct hci_ev_remote_name *ev = (void *) skb->data;
2093 struct hci_conn *conn;
2094
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002095 BT_DBG("%s", hdev->name);
2096
2097 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02002098
2099 hci_dev_lock(hdev);
2100
2101 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002102
2103 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2104 goto check_auth;
2105
2106 if (ev->status == 0)
2107 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002108 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
Johan Hedbergb644ba32012-01-17 21:48:47 +02002109 else
2110 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2111
2112check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07002113 if (!conn)
2114 goto unlock;
2115
2116 if (!hci_outgoing_auth_needed(hdev, conn))
2117 goto unlock;
2118
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002119 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002120 struct hci_cp_auth_requested cp;
2121 cp.handle = __cpu_to_le16(conn->handle);
2122 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2123 }
2124
Johan Hedberg79c6c702011-04-28 11:28:55 -07002125unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02002126 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002127}
2128
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002129static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002130{
2131 struct hci_ev_encrypt_change *ev = (void *) skb->data;
2132 struct hci_conn *conn;
2133
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002134 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002135
2136 hci_dev_lock(hdev);
2137
2138 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2139 if (conn) {
2140 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002141 if (ev->encrypt) {
2142 /* Encryption implies authentication */
2143 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002144 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002145 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002146 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002147 conn->link_mode &= ~HCI_LM_ENCRYPT;
2148 }
2149
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002150 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002151
Gustavo Padovana7d77232012-05-13 03:20:07 -03002152 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03002153 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Gustavo Padovana7d77232012-05-13 03:20:07 -03002154 hci_conn_put(conn);
2155 goto unlock;
2156 }
2157
Marcel Holtmannf8558552008-07-14 20:13:49 +02002158 if (conn->state == BT_CONFIG) {
2159 if (!ev->status)
2160 conn->state = BT_CONNECTED;
2161
2162 hci_proto_connect_cfm(conn, ev->status);
2163 hci_conn_put(conn);
2164 } else
2165 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002166 }
2167
Gustavo Padovana7d77232012-05-13 03:20:07 -03002168unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002169 hci_dev_unlock(hdev);
2170}
2171
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002172static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2173 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002174{
2175 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2176 struct hci_conn *conn;
2177
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002178 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002179
2180 hci_dev_lock(hdev);
2181
2182 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2183 if (conn) {
2184 if (!ev->status)
2185 conn->link_mode |= HCI_LM_SECURE;
2186
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002187 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002188
2189 hci_key_change_cfm(conn, ev->status);
2190 }
2191
2192 hci_dev_unlock(hdev);
2193}
2194
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002195static void hci_remote_features_evt(struct hci_dev *hdev,
2196 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002197{
2198 struct hci_ev_remote_features *ev = (void *) skb->data;
2199 struct hci_conn *conn;
2200
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002201 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002202
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002203 hci_dev_lock(hdev);
2204
2205 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002206 if (!conn)
2207 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002208
Johan Hedbergccd556f2010-11-10 17:11:51 +02002209 if (!ev->status)
2210 memcpy(conn->features, ev->features, 8);
2211
2212 if (conn->state != BT_CONFIG)
2213 goto unlock;
2214
2215 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2216 struct hci_cp_read_remote_ext_features cp;
2217 cp.handle = ev->handle;
2218 cp.page = 0x01;
2219 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002220 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002221 goto unlock;
2222 }
2223
Johan Hedberg671267b2012-05-12 16:11:50 -03002224 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02002225 struct hci_cp_remote_name_req cp;
2226 memset(&cp, 0, sizeof(cp));
2227 bacpy(&cp.bdaddr, &conn->dst);
2228 cp.pscan_rep_mode = 0x02;
2229 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002230 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2231 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002232 conn->dst_type, 0, NULL, 0,
2233 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002234
Johan Hedberg127178d2010-11-18 22:22:29 +02002235 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002236 conn->state = BT_CONNECTED;
2237 hci_proto_connect_cfm(conn, ev->status);
2238 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002239 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002240
Johan Hedbergccd556f2010-11-10 17:11:51 +02002241unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002242 hci_dev_unlock(hdev);
2243}
2244
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002245static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002246{
2247 BT_DBG("%s", hdev->name);
2248}
2249
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002250static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2251 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002252{
2253 BT_DBG("%s", hdev->name);
2254}
2255
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002256static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002257{
2258 struct hci_ev_cmd_complete *ev = (void *) skb->data;
Johan Hedberg9238f362013-03-05 20:37:48 +02002259 u8 status = skb->data[sizeof(*ev)];
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002260 __u16 opcode;
2261
2262 skb_pull(skb, sizeof(*ev));
2263
2264 opcode = __le16_to_cpu(ev->opcode);
2265
2266 switch (opcode) {
2267 case HCI_OP_INQUIRY_CANCEL:
2268 hci_cc_inquiry_cancel(hdev, skb);
2269 break;
2270
Andre Guedes4d934832012-03-21 00:03:35 -03002271 case HCI_OP_PERIODIC_INQ:
2272 hci_cc_periodic_inq(hdev, skb);
2273 break;
2274
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002275 case HCI_OP_EXIT_PERIODIC_INQ:
2276 hci_cc_exit_periodic_inq(hdev, skb);
2277 break;
2278
2279 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2280 hci_cc_remote_name_req_cancel(hdev, skb);
2281 break;
2282
2283 case HCI_OP_ROLE_DISCOVERY:
2284 hci_cc_role_discovery(hdev, skb);
2285 break;
2286
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002287 case HCI_OP_READ_LINK_POLICY:
2288 hci_cc_read_link_policy(hdev, skb);
2289 break;
2290
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002291 case HCI_OP_WRITE_LINK_POLICY:
2292 hci_cc_write_link_policy(hdev, skb);
2293 break;
2294
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002295 case HCI_OP_READ_DEF_LINK_POLICY:
2296 hci_cc_read_def_link_policy(hdev, skb);
2297 break;
2298
2299 case HCI_OP_WRITE_DEF_LINK_POLICY:
2300 hci_cc_write_def_link_policy(hdev, skb);
2301 break;
2302
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002303 case HCI_OP_RESET:
2304 hci_cc_reset(hdev, skb);
2305 break;
2306
2307 case HCI_OP_WRITE_LOCAL_NAME:
2308 hci_cc_write_local_name(hdev, skb);
2309 break;
2310
2311 case HCI_OP_READ_LOCAL_NAME:
2312 hci_cc_read_local_name(hdev, skb);
2313 break;
2314
2315 case HCI_OP_WRITE_AUTH_ENABLE:
2316 hci_cc_write_auth_enable(hdev, skb);
2317 break;
2318
2319 case HCI_OP_WRITE_ENCRYPT_MODE:
2320 hci_cc_write_encrypt_mode(hdev, skb);
2321 break;
2322
2323 case HCI_OP_WRITE_SCAN_ENABLE:
2324 hci_cc_write_scan_enable(hdev, skb);
2325 break;
2326
2327 case HCI_OP_READ_CLASS_OF_DEV:
2328 hci_cc_read_class_of_dev(hdev, skb);
2329 break;
2330
2331 case HCI_OP_WRITE_CLASS_OF_DEV:
2332 hci_cc_write_class_of_dev(hdev, skb);
2333 break;
2334
2335 case HCI_OP_READ_VOICE_SETTING:
2336 hci_cc_read_voice_setting(hdev, skb);
2337 break;
2338
2339 case HCI_OP_WRITE_VOICE_SETTING:
2340 hci_cc_write_voice_setting(hdev, skb);
2341 break;
2342
2343 case HCI_OP_HOST_BUFFER_SIZE:
2344 hci_cc_host_buffer_size(hdev, skb);
2345 break;
2346
Marcel Holtmann333140b2008-07-14 20:13:48 +02002347 case HCI_OP_WRITE_SSP_MODE:
2348 hci_cc_write_ssp_mode(hdev, skb);
2349 break;
2350
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002351 case HCI_OP_READ_LOCAL_VERSION:
2352 hci_cc_read_local_version(hdev, skb);
2353 break;
2354
2355 case HCI_OP_READ_LOCAL_COMMANDS:
2356 hci_cc_read_local_commands(hdev, skb);
2357 break;
2358
2359 case HCI_OP_READ_LOCAL_FEATURES:
2360 hci_cc_read_local_features(hdev, skb);
2361 break;
2362
Andre Guedes971e3a42011-06-30 19:20:52 -03002363 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2364 hci_cc_read_local_ext_features(hdev, skb);
2365 break;
2366
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002367 case HCI_OP_READ_BUFFER_SIZE:
2368 hci_cc_read_buffer_size(hdev, skb);
2369 break;
2370
2371 case HCI_OP_READ_BD_ADDR:
2372 hci_cc_read_bd_addr(hdev, skb);
2373 break;
2374
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002375 case HCI_OP_READ_DATA_BLOCK_SIZE:
2376 hci_cc_read_data_block_size(hdev, skb);
2377 break;
2378
Johan Hedberg23bb5762010-12-21 23:01:27 +02002379 case HCI_OP_WRITE_CA_TIMEOUT:
2380 hci_cc_write_ca_timeout(hdev, skb);
2381 break;
2382
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002383 case HCI_OP_READ_FLOW_CONTROL_MODE:
2384 hci_cc_read_flow_control_mode(hdev, skb);
2385 break;
2386
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002387 case HCI_OP_READ_LOCAL_AMP_INFO:
2388 hci_cc_read_local_amp_info(hdev, skb);
2389 break;
2390
Andrei Emeltchenko903e4542012-09-27 17:26:09 +03002391 case HCI_OP_READ_LOCAL_AMP_ASSOC:
2392 hci_cc_read_local_amp_assoc(hdev, skb);
2393 break;
2394
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002395 case HCI_OP_DELETE_STORED_LINK_KEY:
2396 hci_cc_delete_stored_link_key(hdev, skb);
2397 break;
2398
Johan Hedbergd5859e22011-01-25 01:19:58 +02002399 case HCI_OP_SET_EVENT_MASK:
2400 hci_cc_set_event_mask(hdev, skb);
2401 break;
2402
2403 case HCI_OP_WRITE_INQUIRY_MODE:
2404 hci_cc_write_inquiry_mode(hdev, skb);
2405 break;
2406
2407 case HCI_OP_READ_INQ_RSP_TX_POWER:
2408 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2409 break;
2410
2411 case HCI_OP_SET_EVENT_FLT:
2412 hci_cc_set_event_flt(hdev, skb);
2413 break;
2414
Johan Hedberg980e1a52011-01-22 06:10:07 +02002415 case HCI_OP_PIN_CODE_REPLY:
2416 hci_cc_pin_code_reply(hdev, skb);
2417 break;
2418
2419 case HCI_OP_PIN_CODE_NEG_REPLY:
2420 hci_cc_pin_code_neg_reply(hdev, skb);
2421 break;
2422
Szymon Jancc35938b2011-03-22 13:12:21 +01002423 case HCI_OP_READ_LOCAL_OOB_DATA:
2424 hci_cc_read_local_oob_data_reply(hdev, skb);
2425 break;
2426
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002427 case HCI_OP_LE_READ_BUFFER_SIZE:
2428 hci_cc_le_read_buffer_size(hdev, skb);
2429 break;
2430
Johan Hedberg60e77322013-01-22 14:01:59 +02002431 case HCI_OP_LE_READ_LOCAL_FEATURES:
2432 hci_cc_le_read_local_features(hdev, skb);
2433 break;
2434
Johan Hedberg8fa19092012-10-19 20:57:49 +03002435 case HCI_OP_LE_READ_ADV_TX_POWER:
2436 hci_cc_le_read_adv_tx_power(hdev, skb);
2437 break;
2438
Johan Hedberge36b04c2012-10-19 20:57:47 +03002439 case HCI_OP_LE_SET_EVENT_MASK:
2440 hci_cc_le_set_event_mask(hdev, skb);
2441 break;
2442
Johan Hedberga5c29682011-02-19 12:05:57 -03002443 case HCI_OP_USER_CONFIRM_REPLY:
2444 hci_cc_user_confirm_reply(hdev, skb);
2445 break;
2446
2447 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2448 hci_cc_user_confirm_neg_reply(hdev, skb);
2449 break;
2450
Brian Gix1143d452011-11-23 08:28:34 -08002451 case HCI_OP_USER_PASSKEY_REPLY:
2452 hci_cc_user_passkey_reply(hdev, skb);
2453 break;
2454
2455 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2456 hci_cc_user_passkey_neg_reply(hdev, skb);
Szymon Janc16cde992012-04-13 12:32:42 +02002457 break;
Andre Guedes07f7fa52011-12-02 21:13:31 +09002458
2459 case HCI_OP_LE_SET_SCAN_PARAM:
2460 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002461 break;
2462
Johan Hedbergc1d5dc42012-11-08 01:23:01 +01002463 case HCI_OP_LE_SET_ADV_ENABLE:
2464 hci_cc_le_set_adv_enable(hdev, skb);
2465 break;
2466
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002467 case HCI_OP_LE_SET_SCAN_ENABLE:
2468 hci_cc_le_set_scan_enable(hdev, skb);
2469 break;
2470
Johan Hedbergcf1d0812013-01-22 14:02:00 +02002471 case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2472 hci_cc_le_read_white_list_size(hdev, skb);
2473 break;
2474
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002475 case HCI_OP_LE_LTK_REPLY:
2476 hci_cc_le_ltk_reply(hdev, skb);
2477 break;
2478
2479 case HCI_OP_LE_LTK_NEG_REPLY:
2480 hci_cc_le_ltk_neg_reply(hdev, skb);
2481 break;
2482
Johan Hedberg9b008c02013-01-22 14:02:01 +02002483 case HCI_OP_LE_READ_SUPPORTED_STATES:
2484 hci_cc_le_read_supported_states(hdev, skb);
2485 break;
2486
Andre Guedesf9b49302011-06-30 19:20:53 -03002487 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2488 hci_cc_write_le_host_supported(hdev, skb);
2489 break;
2490
Andrei Emeltchenko93c284e2012-09-27 17:26:20 +03002491 case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
2492 hci_cc_write_remote_amp_assoc(hdev, skb);
2493 break;
2494
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002495 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002496 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002497 break;
2498 }
2499
Ville Tervo6bd32322011-02-16 16:32:41 +02002500 if (ev->opcode != HCI_OP_NOP)
2501 del_timer(&hdev->cmd_timer);
2502
Johan Hedberg9238f362013-03-05 20:37:48 +02002503 hci_req_cmd_complete(hdev, ev->opcode, status);
2504
Szymon Jancdbccd792012-12-11 08:51:19 +01002505 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002506 atomic_set(&hdev->cmd_cnt, 1);
2507 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002508 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002509 }
2510}
2511
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002512static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002513{
2514 struct hci_ev_cmd_status *ev = (void *) skb->data;
2515 __u16 opcode;
2516
2517 skb_pull(skb, sizeof(*ev));
2518
2519 opcode = __le16_to_cpu(ev->opcode);
2520
2521 switch (opcode) {
2522 case HCI_OP_INQUIRY:
2523 hci_cs_inquiry(hdev, ev->status);
2524 break;
2525
2526 case HCI_OP_CREATE_CONN:
2527 hci_cs_create_conn(hdev, ev->status);
2528 break;
2529
2530 case HCI_OP_ADD_SCO:
2531 hci_cs_add_sco(hdev, ev->status);
2532 break;
2533
Marcel Holtmannf8558552008-07-14 20:13:49 +02002534 case HCI_OP_AUTH_REQUESTED:
2535 hci_cs_auth_requested(hdev, ev->status);
2536 break;
2537
2538 case HCI_OP_SET_CONN_ENCRYPT:
2539 hci_cs_set_conn_encrypt(hdev, ev->status);
2540 break;
2541
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002542 case HCI_OP_REMOTE_NAME_REQ:
2543 hci_cs_remote_name_req(hdev, ev->status);
2544 break;
2545
Marcel Holtmann769be972008-07-14 20:13:49 +02002546 case HCI_OP_READ_REMOTE_FEATURES:
2547 hci_cs_read_remote_features(hdev, ev->status);
2548 break;
2549
2550 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2551 hci_cs_read_remote_ext_features(hdev, ev->status);
2552 break;
2553
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002554 case HCI_OP_SETUP_SYNC_CONN:
2555 hci_cs_setup_sync_conn(hdev, ev->status);
2556 break;
2557
2558 case HCI_OP_SNIFF_MODE:
2559 hci_cs_sniff_mode(hdev, ev->status);
2560 break;
2561
2562 case HCI_OP_EXIT_SNIFF_MODE:
2563 hci_cs_exit_sniff_mode(hdev, ev->status);
2564 break;
2565
Johan Hedberg8962ee72011-01-20 12:40:27 +02002566 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002567 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002568 break;
2569
Ville Tervofcd89c02011-02-10 22:38:47 -03002570 case HCI_OP_LE_CREATE_CONN:
2571 hci_cs_le_create_conn(hdev, ev->status);
2572 break;
2573
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002574 case HCI_OP_LE_START_ENC:
2575 hci_cs_le_start_enc(hdev, ev->status);
2576 break;
2577
Andrei Emeltchenkoa02226d2012-09-27 17:26:19 +03002578 case HCI_OP_CREATE_PHY_LINK:
2579 hci_cs_create_phylink(hdev, ev->status);
2580 break;
2581
Andrei Emeltchenko0b26ab92012-09-27 17:26:24 +03002582 case HCI_OP_ACCEPT_PHY_LINK:
2583 hci_cs_accept_phylink(hdev, ev->status);
2584 break;
2585
Andrei Emeltchenko5ce66b52012-10-31 15:46:30 +02002586 case HCI_OP_CREATE_LOGICAL_LINK:
2587 hci_cs_create_logical_link(hdev, ev->status);
2588 break;
2589
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002590 default:
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002591 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002592 break;
2593 }
2594
Ville Tervo6bd32322011-02-16 16:32:41 +02002595 if (ev->opcode != HCI_OP_NOP)
2596 del_timer(&hdev->cmd_timer);
2597
Johan Hedberg9238f362013-03-05 20:37:48 +02002598 hci_req_cmd_status(hdev, ev->opcode, ev->status);
2599
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002600 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002601 atomic_set(&hdev->cmd_cnt, 1);
2602 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002603 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002604 }
2605}
2606
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002607static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002608{
2609 struct hci_ev_role_change *ev = (void *) skb->data;
2610 struct hci_conn *conn;
2611
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002612 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002613
2614 hci_dev_lock(hdev);
2615
2616 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2617 if (conn) {
2618 if (!ev->status) {
2619 if (ev->role)
2620 conn->link_mode &= ~HCI_LM_MASTER;
2621 else
2622 conn->link_mode |= HCI_LM_MASTER;
2623 }
2624
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002625 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002626
2627 hci_role_switch_cfm(conn, ev->status, ev->role);
2628 }
2629
2630 hci_dev_unlock(hdev);
2631}
2632
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002633static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002635 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 int i;
2637
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002638 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2639 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2640 return;
2641 }
2642
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002643 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002644 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 BT_DBG("%s bad parameters", hdev->name);
2646 return;
2647 }
2648
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002649 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2650
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002651 for (i = 0; i < ev->num_hndl; i++) {
2652 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 struct hci_conn *conn;
2654 __u16 handle, count;
2655
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002656 handle = __le16_to_cpu(info->handle);
2657 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658
2659 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002660 if (!conn)
2661 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002663 conn->sent -= count;
2664
2665 switch (conn->type) {
2666 case ACL_LINK:
2667 hdev->acl_cnt += count;
2668 if (hdev->acl_cnt > hdev->acl_pkts)
2669 hdev->acl_cnt = hdev->acl_pkts;
2670 break;
2671
2672 case LE_LINK:
2673 if (hdev->le_pkts) {
2674 hdev->le_cnt += count;
2675 if (hdev->le_cnt > hdev->le_pkts)
2676 hdev->le_cnt = hdev->le_pkts;
2677 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002678 hdev->acl_cnt += count;
2679 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 hdev->acl_cnt = hdev->acl_pkts;
2681 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002682 break;
2683
2684 case SCO_LINK:
2685 hdev->sco_cnt += count;
2686 if (hdev->sco_cnt > hdev->sco_pkts)
2687 hdev->sco_cnt = hdev->sco_pkts;
2688 break;
2689
2690 default:
2691 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2692 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 }
2694 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002695
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002696 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697}
2698
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002699static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
2700 __u16 handle)
2701{
2702 struct hci_chan *chan;
2703
2704 switch (hdev->dev_type) {
2705 case HCI_BREDR:
2706 return hci_conn_hash_lookup_handle(hdev, handle);
2707 case HCI_AMP:
2708 chan = hci_chan_lookup_handle(hdev, handle);
2709 if (chan)
2710 return chan->conn;
2711 break;
2712 default:
2713 BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
2714 break;
2715 }
2716
2717 return NULL;
2718}
2719
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002720static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002721{
2722 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2723 int i;
2724
2725 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2726 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2727 return;
2728 }
2729
2730 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
Gustavo Padovan807deac2012-05-17 00:36:24 -03002731 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002732 BT_DBG("%s bad parameters", hdev->name);
2733 return;
2734 }
2735
2736 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002737 ev->num_hndl);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002738
2739 for (i = 0; i < ev->num_hndl; i++) {
2740 struct hci_comp_blocks_info *info = &ev->handles[i];
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002741 struct hci_conn *conn = NULL;
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002742 __u16 handle, block_count;
2743
2744 handle = __le16_to_cpu(info->handle);
2745 block_count = __le16_to_cpu(info->blocks);
2746
Andrei Emeltchenko76ef7cf2012-10-10 17:38:29 +03002747 conn = __hci_conn_lookup_handle(hdev, handle);
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002748 if (!conn)
2749 continue;
2750
2751 conn->sent -= block_count;
2752
2753 switch (conn->type) {
2754 case ACL_LINK:
Andrei Emeltchenkobd1eb662012-10-10 17:38:30 +03002755 case AMP_LINK:
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002756 hdev->block_cnt += block_count;
2757 if (hdev->block_cnt > hdev->num_blocks)
2758 hdev->block_cnt = hdev->num_blocks;
2759 break;
2760
2761 default:
2762 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2763 break;
2764 }
2765 }
2766
2767 queue_work(hdev->workqueue, &hdev->tx_work);
2768}
2769
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002770static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002772 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002773 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002775 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776
2777 hci_dev_lock(hdev);
2778
Marcel Holtmann04837f62006-07-03 10:02:33 +02002779 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2780 if (conn) {
2781 conn->mode = ev->mode;
2782 conn->interval = __le16_to_cpu(ev->interval);
2783
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002784 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
2785 &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002786 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002787 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002788 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002789 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002790 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002791
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002792 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002793 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002794 }
2795
2796 hci_dev_unlock(hdev);
2797}
2798
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002799static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002801 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2802 struct hci_conn *conn;
2803
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002804 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002805
2806 hci_dev_lock(hdev);
2807
2808 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002809 if (!conn)
2810 goto unlock;
2811
2812 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002813 hci_conn_hold(conn);
2814 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2815 hci_conn_put(conn);
2816 }
2817
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002818 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002819 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002820 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002821 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002822 u8 secure;
2823
2824 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2825 secure = 1;
2826 else
2827 secure = 0;
2828
Johan Hedberg744cf192011-11-08 20:40:14 +02002829 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002830 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002831
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002832unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002833 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834}
2835
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002836static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002838 struct hci_ev_link_key_req *ev = (void *) skb->data;
2839 struct hci_cp_link_key_reply cp;
2840 struct hci_conn *conn;
2841 struct link_key *key;
2842
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002843 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002844
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002845 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002846 return;
2847
2848 hci_dev_lock(hdev);
2849
2850 key = hci_find_link_key(hdev, &ev->bdaddr);
2851 if (!key) {
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002852 BT_DBG("%s link key not found for %pMR", hdev->name,
2853 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002854 goto not_found;
2855 }
2856
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03002857 BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
2858 &ev->bdaddr);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002859
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002860 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002861 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002862 BT_DBG("%s ignoring debug key", hdev->name);
2863 goto not_found;
2864 }
2865
2866 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002867 if (conn) {
2868 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002869 conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002870 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2871 goto not_found;
2872 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002873
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002874 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03002875 conn->pending_sec_level == BT_SECURITY_HIGH) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002876 BT_DBG("%s ignoring key unauthenticated for high security",
2877 hdev->name);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002878 goto not_found;
2879 }
2880
2881 conn->key_type = key->type;
2882 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002883 }
2884
2885 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03002886 memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002887
2888 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2889
2890 hci_dev_unlock(hdev);
2891
2892 return;
2893
2894not_found:
2895 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2896 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897}
2898
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002899static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002901 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2902 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002903 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002904
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002905 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002906
2907 hci_dev_lock(hdev);
2908
2909 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2910 if (conn) {
2911 hci_conn_hold(conn);
2912 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002913 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002914
2915 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2916 conn->key_type = ev->key_type;
2917
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002918 hci_conn_put(conn);
2919 }
2920
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002921 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002922 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Gustavo Padovan807deac2012-05-17 00:36:24 -03002923 ev->key_type, pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002924
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002925 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926}
2927
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002928static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02002929{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002930 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002931 struct hci_conn *conn;
2932
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002933 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002934
2935 hci_dev_lock(hdev);
2936
2937 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 if (conn && !ev->status) {
2939 struct inquiry_entry *ie;
2940
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002941 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2942 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 ie->data.clock_offset = ev->clock_offset;
2944 ie->timestamp = jiffies;
2945 }
2946 }
2947
2948 hci_dev_unlock(hdev);
2949}
2950
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002951static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna8746412008-07-14 20:13:46 +02002952{
2953 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2954 struct hci_conn *conn;
2955
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03002956 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmanna8746412008-07-14 20:13:46 +02002957
2958 hci_dev_lock(hdev);
2959
2960 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2961 if (conn && !ev->status)
2962 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2963
2964 hci_dev_unlock(hdev);
2965}
2966
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002967static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002968{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002969 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002970 struct inquiry_entry *ie;
2971
2972 BT_DBG("%s", hdev->name);
2973
2974 hci_dev_lock(hdev);
2975
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002976 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2977 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002978 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2979 ie->timestamp = jiffies;
2980 }
2981
2982 hci_dev_unlock(hdev);
2983}
2984
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002985static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2986 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002987{
2988 struct inquiry_data data;
2989 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02002990 bool name_known, ssp;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002991
2992 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2993
2994 if (!num_rsp)
2995 return;
2996
Andre Guedes1519cc12012-03-21 00:03:38 -03002997 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
2998 return;
2999
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003000 hci_dev_lock(hdev);
3001
3002 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01003003 struct inquiry_info_with_rssi_and_pscan_mode *info;
3004 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003005
Johan Hedberge17acd42011-03-30 23:57:16 +03003006 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003007 bacpy(&data.bdaddr, &info->bdaddr);
3008 data.pscan_rep_mode = info->pscan_rep_mode;
3009 data.pscan_period_mode = info->pscan_period_mode;
3010 data.pscan_mode = info->pscan_mode;
3011 memcpy(data.dev_class, info->dev_class, 3);
3012 data.clock_offset = info->clock_offset;
3013 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003014 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003015
3016 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003017 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003018 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003019 info->dev_class, info->rssi,
3020 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003021 }
3022 } else {
3023 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3024
Johan Hedberge17acd42011-03-30 23:57:16 +03003025 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003026 bacpy(&data.bdaddr, &info->bdaddr);
3027 data.pscan_rep_mode = info->pscan_rep_mode;
3028 data.pscan_period_mode = info->pscan_period_mode;
3029 data.pscan_mode = 0x00;
3030 memcpy(data.dev_class, info->dev_class, 3);
3031 data.clock_offset = info->clock_offset;
3032 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003033 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02003034 name_known = hci_inquiry_cache_update(hdev, &data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003035 false, &ssp);
Johan Hedberg48264f02011-11-09 13:58:58 +02003036 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003037 info->dev_class, info->rssi,
3038 !name_known, ssp, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003039 }
3040 }
3041
3042 hci_dev_unlock(hdev);
3043}
3044
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003045static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3046 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003047{
Marcel Holtmann41a96212008-07-14 20:13:48 +02003048 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
3049 struct hci_conn *conn;
3050
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003051 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003052
Marcel Holtmann41a96212008-07-14 20:13:48 +02003053 hci_dev_lock(hdev);
3054
3055 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02003056 if (!conn)
3057 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003058
Johan Hedbergccd556f2010-11-10 17:11:51 +02003059 if (!ev->status && ev->page == 0x01) {
3060 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003061
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003062 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3063 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003064 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann769be972008-07-14 20:13:49 +02003065
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003066 if (ev->features[0] & LMP_HOST_SSP)
Johan Hedberg58a681e2012-01-16 06:47:28 +02003067 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003068 }
3069
Johan Hedbergccd556f2010-11-10 17:11:51 +02003070 if (conn->state != BT_CONFIG)
3071 goto unlock;
3072
Johan Hedberg671267b2012-05-12 16:11:50 -03003073 if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02003074 struct hci_cp_remote_name_req cp;
3075 memset(&cp, 0, sizeof(cp));
3076 bacpy(&cp.bdaddr, &conn->dst);
3077 cp.pscan_rep_mode = 0x02;
3078 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02003079 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3080 mgmt_device_connected(hdev, &conn->dst, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003081 conn->dst_type, 0, NULL, 0,
3082 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02003083
Johan Hedberg127178d2010-11-18 22:22:29 +02003084 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02003085 conn->state = BT_CONNECTED;
3086 hci_proto_connect_cfm(conn, ev->status);
3087 hci_conn_put(conn);
3088 }
3089
3090unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02003091 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003092}
3093
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003094static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3095 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003096{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003097 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3098 struct hci_conn *conn;
3099
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003100 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003101
3102 hci_dev_lock(hdev);
3103
3104 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02003105 if (!conn) {
3106 if (ev->link_type == ESCO_LINK)
3107 goto unlock;
3108
3109 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3110 if (!conn)
3111 goto unlock;
3112
3113 conn->type = SCO_LINK;
3114 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003115
Marcel Holtmann732547f2009-04-19 19:14:14 +02003116 switch (ev->status) {
3117 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003118 conn->handle = __le16_to_cpu(ev->handle);
3119 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003120
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07003121 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02003122 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02003123 break;
3124
Stephen Coe705e5712010-02-16 11:29:44 -05003125 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003126 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08003127 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02003128 case 0x1f: /* Unspecified error */
3129 if (conn->out && conn->attempt < 2) {
3130 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3131 (hdev->esco_type & EDR_ESCO_MASK);
3132 hci_setup_sync(conn, conn->link->handle);
3133 goto unlock;
3134 }
3135 /* fall through */
3136
3137 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003138 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02003139 break;
3140 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02003141
3142 hci_proto_connect_cfm(conn, ev->status);
3143 if (ev->status)
3144 hci_conn_del(conn);
3145
3146unlock:
3147 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003148}
3149
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003150static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003151{
3152 BT_DBG("%s", hdev->name);
3153}
3154
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003155static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04837f62006-07-03 10:02:33 +02003156{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003157 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02003158
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003159 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02003160}
3161
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003162static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3163 struct sk_buff *skb)
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003164{
3165 struct inquiry_data data;
3166 struct extended_inquiry_info *info = (void *) (skb->data + 1);
3167 int num_rsp = *((__u8 *) skb->data);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303168 size_t eir_len;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003169
3170 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3171
3172 if (!num_rsp)
3173 return;
3174
Andre Guedes1519cc12012-03-21 00:03:38 -03003175 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
3176 return;
3177
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003178 hci_dev_lock(hdev);
3179
Johan Hedberge17acd42011-03-30 23:57:16 +03003180 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003181 bool name_known, ssp;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003182
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003183 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01003184 data.pscan_rep_mode = info->pscan_rep_mode;
3185 data.pscan_period_mode = info->pscan_period_mode;
3186 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003187 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01003188 data.clock_offset = info->clock_offset;
3189 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02003190 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003191
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003192 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02003193 name_known = eir_has_data_type(info->data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003194 sizeof(info->data),
3195 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003196 else
3197 name_known = true;
3198
Johan Hedberg388fc8f2012-02-23 00:38:59 +02003199 name_known = hci_inquiry_cache_update(hdev, &data, name_known,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003200 &ssp);
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303201 eir_len = eir_get_length(info->data, sizeof(info->data));
Johan Hedberg48264f02011-11-09 13:58:58 +02003202 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003203 info->dev_class, info->rssi, !name_known,
Vishal Agarwal9d939d92012-04-26 19:19:56 +05303204 ssp, info->data, eir_len);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003205 }
3206
3207 hci_dev_unlock(hdev);
3208}
3209
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003210static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
3211 struct sk_buff *skb)
3212{
3213 struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
3214 struct hci_conn *conn;
3215
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003216 BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003217 __le16_to_cpu(ev->handle));
3218
3219 hci_dev_lock(hdev);
3220
3221 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3222 if (!conn)
3223 goto unlock;
3224
3225 if (!ev->status)
3226 conn->sec_level = conn->pending_sec_level;
3227
3228 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3229
3230 if (ev->status && conn->state == BT_CONNECTED) {
Andre Guedesbed71742013-01-30 11:50:56 -03003231 hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003232 hci_conn_put(conn);
3233 goto unlock;
3234 }
3235
3236 if (conn->state == BT_CONFIG) {
3237 if (!ev->status)
3238 conn->state = BT_CONNECTED;
3239
3240 hci_proto_connect_cfm(conn, ev->status);
3241 hci_conn_put(conn);
3242 } else {
3243 hci_auth_cfm(conn, ev->status);
3244
3245 hci_conn_hold(conn);
3246 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3247 hci_conn_put(conn);
3248 }
3249
3250unlock:
3251 hci_dev_unlock(hdev);
3252}
3253
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003254static u8 hci_get_auth_req(struct hci_conn *conn)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003255{
3256 /* If remote requests dedicated bonding follow that lead */
3257 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
3258 /* If both remote and local IO capabilities allow MITM
3259 * protection then require it, otherwise don't */
3260 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
3261 return 0x02;
3262 else
3263 return 0x03;
3264 }
3265
3266 /* If remote requests no-bonding follow that lead */
3267 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02003268 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003269
3270 return conn->auth_type;
3271}
3272
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003273static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003274{
3275 struct hci_ev_io_capa_request *ev = (void *) skb->data;
3276 struct hci_conn *conn;
3277
3278 BT_DBG("%s", hdev->name);
3279
3280 hci_dev_lock(hdev);
3281
3282 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003283 if (!conn)
3284 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003285
Johan Hedberg03b555e2011-01-04 15:40:05 +02003286 hci_conn_hold(conn);
3287
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003288 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003289 goto unlock;
3290
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003291 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Gustavo Padovan807deac2012-05-17 00:36:24 -03003292 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003293 struct hci_cp_io_capability_reply cp;
3294
3295 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303296 /* Change the IO capability from KeyboardDisplay
3297 * to DisplayYesNo as it is not supported by BT spec. */
3298 cp.capability = (conn->io_capability == 0x04) ?
3299 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003300 conn->auth_type = hci_get_auth_req(conn);
3301 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003302
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003303 if (hci_find_remote_oob_data(hdev, &conn->dst) &&
3304 (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
Szymon Jancce85ee12011-03-22 13:12:23 +01003305 cp.oob_data = 0x01;
3306 else
3307 cp.oob_data = 0x00;
3308
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003309 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003310 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003311 } else {
3312 struct hci_cp_io_capability_neg_reply cp;
3313
3314 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003315 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003316
3317 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003318 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003319 }
3320
3321unlock:
3322 hci_dev_unlock(hdev);
3323}
3324
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003325static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
Johan Hedberg03b555e2011-01-04 15:40:05 +02003326{
3327 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3328 struct hci_conn *conn;
3329
3330 BT_DBG("%s", hdev->name);
3331
3332 hci_dev_lock(hdev);
3333
3334 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3335 if (!conn)
3336 goto unlock;
3337
Johan Hedberg03b555e2011-01-04 15:40:05 +02003338 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003339 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003340 if (ev->oob_data)
3341 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003342
3343unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003344 hci_dev_unlock(hdev);
3345}
3346
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003347static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3348 struct sk_buff *skb)
Johan Hedberga5c29682011-02-19 12:05:57 -03003349{
3350 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003351 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003352 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003353
3354 BT_DBG("%s", hdev->name);
3355
3356 hci_dev_lock(hdev);
3357
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003358 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003359 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003360
Johan Hedberg7a828902011-04-28 11:28:53 -07003361 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3362 if (!conn)
3363 goto unlock;
3364
3365 loc_mitm = (conn->auth_type & 0x01);
3366 rem_mitm = (conn->remote_auth & 0x01);
3367
3368 /* If we require MITM but the remote device can't provide that
3369 * (it has NoInputNoOutput) then reject the confirmation
3370 * request. The only exception is when we're dedicated bonding
3371 * initiators (connect_cfm_cb set) since then we always have the MITM
3372 * bit set. */
3373 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3374 BT_DBG("Rejecting request: remote device can't provide MITM");
3375 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003376 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003377 goto unlock;
3378 }
3379
3380 /* If no side requires MITM protection; auto-accept */
3381 if ((!loc_mitm || conn->remote_cap == 0x03) &&
Gustavo Padovan807deac2012-05-17 00:36:24 -03003382 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003383
3384 /* If we're not the initiators request authorization to
3385 * proceed from user space (mgmt_user_confirm with
3386 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003387 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003388 BT_DBG("Confirming auto-accept as acceptor");
3389 confirm_hint = 1;
3390 goto confirm;
3391 }
3392
Johan Hedberg9f616562011-04-28 11:28:54 -07003393 BT_DBG("Auto-accept of user confirmation with %ums delay",
Gustavo Padovan807deac2012-05-17 00:36:24 -03003394 hdev->auto_accept_delay);
Johan Hedberg9f616562011-04-28 11:28:54 -07003395
3396 if (hdev->auto_accept_delay > 0) {
3397 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3398 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3399 goto unlock;
3400 }
3401
Johan Hedberg7a828902011-04-28 11:28:53 -07003402 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
Gustavo Padovan807deac2012-05-17 00:36:24 -03003403 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberg7a828902011-04-28 11:28:53 -07003404 goto unlock;
3405 }
3406
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003407confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003408 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003409 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003410
3411unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003412 hci_dev_unlock(hdev);
3413}
3414
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003415static void hci_user_passkey_request_evt(struct hci_dev *hdev,
3416 struct sk_buff *skb)
Brian Gix1143d452011-11-23 08:28:34 -08003417{
3418 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3419
3420 BT_DBG("%s", hdev->name);
3421
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003422 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003423 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003424}
3425
Johan Hedberg92a25252012-09-06 18:39:26 +03003426static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
3427 struct sk_buff *skb)
3428{
3429 struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
3430 struct hci_conn *conn;
3431
3432 BT_DBG("%s", hdev->name);
3433
3434 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3435 if (!conn)
3436 return;
3437
3438 conn->passkey_notify = __le32_to_cpu(ev->passkey);
3439 conn->passkey_entered = 0;
3440
3441 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3442 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3443 conn->dst_type, conn->passkey_notify,
3444 conn->passkey_entered);
3445}
3446
3447static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3448{
3449 struct hci_ev_keypress_notify *ev = (void *) skb->data;
3450 struct hci_conn *conn;
3451
3452 BT_DBG("%s", hdev->name);
3453
3454 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3455 if (!conn)
3456 return;
3457
3458 switch (ev->type) {
3459 case HCI_KEYPRESS_STARTED:
3460 conn->passkey_entered = 0;
3461 return;
3462
3463 case HCI_KEYPRESS_ENTERED:
3464 conn->passkey_entered++;
3465 break;
3466
3467 case HCI_KEYPRESS_ERASED:
3468 conn->passkey_entered--;
3469 break;
3470
3471 case HCI_KEYPRESS_CLEARED:
3472 conn->passkey_entered = 0;
3473 break;
3474
3475 case HCI_KEYPRESS_COMPLETED:
3476 return;
3477 }
3478
3479 if (test_bit(HCI_MGMT, &hdev->dev_flags))
3480 mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
3481 conn->dst_type, conn->passkey_notify,
3482 conn->passkey_entered);
3483}
3484
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003485static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3486 struct sk_buff *skb)
Marcel Holtmann04936842008-07-14 20:13:48 +02003487{
3488 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3489 struct hci_conn *conn;
3490
3491 BT_DBG("%s", hdev->name);
3492
3493 hci_dev_lock(hdev);
3494
3495 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003496 if (!conn)
3497 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003498
Johan Hedberg2a611692011-02-19 12:06:00 -03003499 /* To avoid duplicate auth_failed events to user space we check
3500 * the HCI_CONN_AUTH_PEND flag which will be set if we
3501 * initiated the authentication. A traditional auth_complete
3502 * event gets always produced as initiator and is also mapped to
3503 * the mgmt_auth_failed event */
Mikel Astizfa1bd912012-08-09 09:52:29 +02003504 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003505 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003506 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003507
3508 hci_conn_put(conn);
3509
3510unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003511 hci_dev_unlock(hdev);
3512}
3513
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003514static void hci_remote_host_features_evt(struct hci_dev *hdev,
3515 struct sk_buff *skb)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003516{
3517 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3518 struct inquiry_entry *ie;
3519
3520 BT_DBG("%s", hdev->name);
3521
3522 hci_dev_lock(hdev);
3523
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003524 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3525 if (ie)
Johan Hedberg02b7cc62012-02-28 02:28:43 +02003526 ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Marcel Holtmann41a96212008-07-14 20:13:48 +02003527
3528 hci_dev_unlock(hdev);
3529}
3530
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003531static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3532 struct sk_buff *skb)
Szymon Janc2763eda2011-03-22 13:12:22 +01003533{
3534 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3535 struct oob_data *data;
3536
3537 BT_DBG("%s", hdev->name);
3538
3539 hci_dev_lock(hdev);
3540
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003541 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003542 goto unlock;
3543
Szymon Janc2763eda2011-03-22 13:12:22 +01003544 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3545 if (data) {
3546 struct hci_cp_remote_oob_data_reply cp;
3547
3548 bacpy(&cp.bdaddr, &ev->bdaddr);
3549 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3550 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3551
3552 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003553 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003554 } else {
3555 struct hci_cp_remote_oob_data_neg_reply cp;
3556
3557 bacpy(&cp.bdaddr, &ev->bdaddr);
3558 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
Gustavo Padovan807deac2012-05-17 00:36:24 -03003559 &cp);
Szymon Janc2763eda2011-03-22 13:12:22 +01003560 }
3561
Szymon Jance1ba1f12011-04-06 13:01:59 +02003562unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003563 hci_dev_unlock(hdev);
3564}
3565
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003566static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3567 struct sk_buff *skb)
3568{
3569 struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3570 struct hci_conn *hcon, *bredr_hcon;
3571
3572 BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3573 ev->status);
3574
3575 hci_dev_lock(hdev);
3576
3577 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3578 if (!hcon) {
3579 hci_dev_unlock(hdev);
3580 return;
3581 }
3582
3583 if (ev->status) {
3584 hci_conn_del(hcon);
3585 hci_dev_unlock(hdev);
3586 return;
3587 }
3588
3589 bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3590
3591 hcon->state = BT_CONNECTED;
3592 bacpy(&hcon->dst, &bredr_hcon->dst);
3593
3594 hci_conn_hold(hcon);
3595 hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3596 hci_conn_put(hcon);
3597
3598 hci_conn_hold_device(hcon);
3599 hci_conn_add_sysfs(hcon);
3600
Andrei Emeltchenkocf70ff22012-10-31 15:46:36 +02003601 amp_physical_cfm(bredr_hcon, hcon);
3602
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003603 hci_dev_unlock(hdev);
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03003604}
3605
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03003606static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3607{
3608 struct hci_ev_logical_link_complete *ev = (void *) skb->data;
3609 struct hci_conn *hcon;
3610 struct hci_chan *hchan;
3611 struct amp_mgr *mgr;
3612
3613 BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
3614 hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
3615 ev->status);
3616
3617 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3618 if (!hcon)
3619 return;
3620
3621 /* Create AMP hchan */
3622 hchan = hci_chan_create(hcon);
3623 if (!hchan)
3624 return;
3625
3626 hchan->handle = le16_to_cpu(ev->handle);
3627
3628 BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
3629
3630 mgr = hcon->amp_mgr;
3631 if (mgr && mgr->bredr_chan) {
3632 struct l2cap_chan *bredr_chan = mgr->bredr_chan;
3633
3634 l2cap_chan_lock(bredr_chan);
3635
3636 bredr_chan->conn->mtu = hdev->block_mtu;
3637 l2cap_logical_cfm(bredr_chan, hchan, 0);
3638 hci_conn_hold(hcon);
3639
3640 l2cap_chan_unlock(bredr_chan);
3641 }
3642}
3643
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02003644static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3645 struct sk_buff *skb)
3646{
3647 struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3648 struct hci_chan *hchan;
3649
3650 BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3651 le16_to_cpu(ev->handle), ev->status);
3652
3653 if (ev->status)
3654 return;
3655
3656 hci_dev_lock(hdev);
3657
3658 hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3659 if (!hchan)
3660 goto unlock;
3661
3662 amp_destroy_logical_link(hchan, ev->reason);
3663
3664unlock:
3665 hci_dev_unlock(hdev);
3666}
3667
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02003668static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
3669 struct sk_buff *skb)
3670{
3671 struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
3672 struct hci_conn *hcon;
3673
3674 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3675
3676 if (ev->status)
3677 return;
3678
3679 hci_dev_lock(hdev);
3680
3681 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3682 if (hcon) {
3683 hcon->state = BT_CLOSED;
3684 hci_conn_del(hcon);
3685 }
3686
3687 hci_dev_unlock(hdev);
3688}
3689
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003690static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003691{
3692 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3693 struct hci_conn *conn;
3694
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003695 BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003696
3697 hci_dev_lock(hdev);
3698
Andre Guedesb47a09b2012-07-27 15:10:15 -03003699 conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
Ville Tervob62f3282011-02-10 22:38:50 -03003700 if (!conn) {
3701 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3702 if (!conn) {
3703 BT_ERR("No memory for new connection");
Andre Guedes230fd162012-07-27 15:10:10 -03003704 goto unlock;
Ville Tervob62f3282011-02-10 22:38:50 -03003705 }
Andre Guedes29b79882011-05-31 14:20:54 -03003706
3707 conn->dst_type = ev->bdaddr_type;
Andre Guedesb9b343d2012-07-27 15:10:11 -03003708
3709 if (ev->role == LE_CONN_ROLE_MASTER) {
3710 conn->out = true;
3711 conn->link_mode |= HCI_LM_MASTER;
3712 }
Ville Tervob62f3282011-02-10 22:38:50 -03003713 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003714
Andre Guedescd17dec2012-07-27 15:10:16 -03003715 if (ev->status) {
3716 mgmt_connect_failed(hdev, &conn->dst, conn->type,
3717 conn->dst_type, ev->status);
3718 hci_proto_connect_cfm(conn, ev->status);
3719 conn->state = BT_CLOSED;
3720 hci_conn_del(conn);
3721 goto unlock;
3722 }
3723
Johan Hedbergb644ba32012-01-17 21:48:47 +02003724 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3725 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003726 conn->dst_type, 0, NULL, 0, NULL);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003727
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003728 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003729 conn->handle = __le16_to_cpu(ev->handle);
3730 conn->state = BT_CONNECTED;
3731
3732 hci_conn_hold_device(conn);
3733 hci_conn_add_sysfs(conn);
3734
3735 hci_proto_connect_cfm(conn, ev->status);
3736
3737unlock:
3738 hci_dev_unlock(hdev);
3739}
3740
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003741static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
Andre Guedes9aa04c92011-05-26 16:23:51 -03003742{
Andre Guedese95beb42011-09-26 20:48:35 -03003743 u8 num_reports = skb->data[0];
3744 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003745 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003746
Andre Guedese95beb42011-09-26 20:48:35 -03003747 while (num_reports--) {
3748 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003749
Andre Guedes3c9e9192012-01-10 18:20:50 -03003750 rssi = ev->data[ev->length];
3751 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003752 NULL, rssi, 0, 1, ev->data, ev->length);
Andre Guedes3c9e9192012-01-10 18:20:50 -03003753
Andre Guedese95beb42011-09-26 20:48:35 -03003754 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003755 }
Andre Guedes9aa04c92011-05-26 16:23:51 -03003756}
3757
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003758static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003759{
3760 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3761 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003762 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003763 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003764 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003765
Andrei Emeltchenko9f1db002012-07-11 14:32:43 +03003766 BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003767
3768 hci_dev_lock(hdev);
3769
3770 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003771 if (conn == NULL)
3772 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003773
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003774 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3775 if (ltk == NULL)
3776 goto not_found;
3777
3778 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003779 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003780
3781 if (ltk->authenticated)
3782 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003783
3784 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3785
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003786 if (ltk->type & HCI_SMP_STK) {
3787 list_del(&ltk->list);
3788 kfree(ltk);
3789 }
3790
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003791 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003792
3793 return;
3794
3795not_found:
3796 neg.handle = ev->handle;
3797 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3798 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003799}
3800
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003801static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
Ville Tervofcd89c02011-02-10 22:38:47 -03003802{
3803 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3804
3805 skb_pull(skb, sizeof(*le_ev));
3806
3807 switch (le_ev->subevent) {
3808 case HCI_EV_LE_CONN_COMPLETE:
3809 hci_le_conn_complete_evt(hdev, skb);
3810 break;
3811
Andre Guedes9aa04c92011-05-26 16:23:51 -03003812 case HCI_EV_LE_ADVERTISING_REPORT:
3813 hci_le_adv_report_evt(hdev, skb);
3814 break;
3815
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003816 case HCI_EV_LE_LTK_REQ:
3817 hci_le_ltk_request_evt(hdev, skb);
3818 break;
3819
Ville Tervofcd89c02011-02-10 22:38:47 -03003820 default:
3821 break;
3822 }
3823}
3824
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03003825static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3826{
3827 struct hci_ev_channel_selected *ev = (void *) skb->data;
3828 struct hci_conn *hcon;
3829
3830 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3831
3832 skb_pull(skb, sizeof(*ev));
3833
3834 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3835 if (!hcon)
3836 return;
3837
3838 amp_read_loc_assoc_final_data(hdev, hcon);
3839}
3840
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3842{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003843 struct hci_event_hdr *hdr = (void *) skb->data;
3844 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
3846 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3847
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003848 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 case HCI_EV_INQUIRY_COMPLETE:
3850 hci_inquiry_complete_evt(hdev, skb);
3851 break;
3852
3853 case HCI_EV_INQUIRY_RESULT:
3854 hci_inquiry_result_evt(hdev, skb);
3855 break;
3856
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003857 case HCI_EV_CONN_COMPLETE:
3858 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003859 break;
3860
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 case HCI_EV_CONN_REQUEST:
3862 hci_conn_request_evt(hdev, skb);
3863 break;
3864
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 case HCI_EV_DISCONN_COMPLETE:
3866 hci_disconn_complete_evt(hdev, skb);
3867 break;
3868
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 case HCI_EV_AUTH_COMPLETE:
3870 hci_auth_complete_evt(hdev, skb);
3871 break;
3872
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003873 case HCI_EV_REMOTE_NAME:
3874 hci_remote_name_evt(hdev, skb);
3875 break;
3876
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 case HCI_EV_ENCRYPT_CHANGE:
3878 hci_encrypt_change_evt(hdev, skb);
3879 break;
3880
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003881 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3882 hci_change_link_key_complete_evt(hdev, skb);
3883 break;
3884
3885 case HCI_EV_REMOTE_FEATURES:
3886 hci_remote_features_evt(hdev, skb);
3887 break;
3888
3889 case HCI_EV_REMOTE_VERSION:
3890 hci_remote_version_evt(hdev, skb);
3891 break;
3892
3893 case HCI_EV_QOS_SETUP_COMPLETE:
3894 hci_qos_setup_complete_evt(hdev, skb);
3895 break;
3896
3897 case HCI_EV_CMD_COMPLETE:
3898 hci_cmd_complete_evt(hdev, skb);
3899 break;
3900
3901 case HCI_EV_CMD_STATUS:
3902 hci_cmd_status_evt(hdev, skb);
3903 break;
3904
3905 case HCI_EV_ROLE_CHANGE:
3906 hci_role_change_evt(hdev, skb);
3907 break;
3908
3909 case HCI_EV_NUM_COMP_PKTS:
3910 hci_num_comp_pkts_evt(hdev, skb);
3911 break;
3912
3913 case HCI_EV_MODE_CHANGE:
3914 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 break;
3916
3917 case HCI_EV_PIN_CODE_REQ:
3918 hci_pin_code_request_evt(hdev, skb);
3919 break;
3920
3921 case HCI_EV_LINK_KEY_REQ:
3922 hci_link_key_request_evt(hdev, skb);
3923 break;
3924
3925 case HCI_EV_LINK_KEY_NOTIFY:
3926 hci_link_key_notify_evt(hdev, skb);
3927 break;
3928
3929 case HCI_EV_CLOCK_OFFSET:
3930 hci_clock_offset_evt(hdev, skb);
3931 break;
3932
Marcel Holtmanna8746412008-07-14 20:13:46 +02003933 case HCI_EV_PKT_TYPE_CHANGE:
3934 hci_pkt_type_change_evt(hdev, skb);
3935 break;
3936
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003937 case HCI_EV_PSCAN_REP_MODE:
3938 hci_pscan_rep_mode_evt(hdev, skb);
3939 break;
3940
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003941 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3942 hci_inquiry_result_with_rssi_evt(hdev, skb);
3943 break;
3944
3945 case HCI_EV_REMOTE_EXT_FEATURES:
3946 hci_remote_ext_features_evt(hdev, skb);
3947 break;
3948
3949 case HCI_EV_SYNC_CONN_COMPLETE:
3950 hci_sync_conn_complete_evt(hdev, skb);
3951 break;
3952
3953 case HCI_EV_SYNC_CONN_CHANGED:
3954 hci_sync_conn_changed_evt(hdev, skb);
3955 break;
3956
Marcel Holtmann04837f62006-07-03 10:02:33 +02003957 case HCI_EV_SNIFF_SUBRATE:
3958 hci_sniff_subrate_evt(hdev, skb);
3959 break;
3960
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003961 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3962 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 break;
3964
Johan Hedberg1c2e0042012-06-08 23:31:13 +08003965 case HCI_EV_KEY_REFRESH_COMPLETE:
3966 hci_key_refresh_complete_evt(hdev, skb);
3967 break;
3968
Marcel Holtmann04936842008-07-14 20:13:48 +02003969 case HCI_EV_IO_CAPA_REQUEST:
3970 hci_io_capa_request_evt(hdev, skb);
3971 break;
3972
Johan Hedberg03b555e2011-01-04 15:40:05 +02003973 case HCI_EV_IO_CAPA_REPLY:
3974 hci_io_capa_reply_evt(hdev, skb);
3975 break;
3976
Johan Hedberga5c29682011-02-19 12:05:57 -03003977 case HCI_EV_USER_CONFIRM_REQUEST:
3978 hci_user_confirm_request_evt(hdev, skb);
3979 break;
3980
Brian Gix1143d452011-11-23 08:28:34 -08003981 case HCI_EV_USER_PASSKEY_REQUEST:
3982 hci_user_passkey_request_evt(hdev, skb);
3983 break;
3984
Johan Hedberg92a25252012-09-06 18:39:26 +03003985 case HCI_EV_USER_PASSKEY_NOTIFY:
3986 hci_user_passkey_notify_evt(hdev, skb);
3987 break;
3988
3989 case HCI_EV_KEYPRESS_NOTIFY:
3990 hci_keypress_notify_evt(hdev, skb);
3991 break;
3992
Marcel Holtmann04936842008-07-14 20:13:48 +02003993 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3994 hci_simple_pair_complete_evt(hdev, skb);
3995 break;
3996
Marcel Holtmann41a96212008-07-14 20:13:48 +02003997 case HCI_EV_REMOTE_HOST_FEATURES:
3998 hci_remote_host_features_evt(hdev, skb);
3999 break;
4000
Ville Tervofcd89c02011-02-10 22:38:47 -03004001 case HCI_EV_LE_META:
4002 hci_le_meta_evt(hdev, skb);
4003 break;
4004
Andrei Emeltchenko9495b2e2012-09-27 17:26:22 +03004005 case HCI_EV_CHANNEL_SELECTED:
4006 hci_chan_selected_evt(hdev, skb);
4007 break;
4008
Szymon Janc2763eda2011-03-22 13:12:22 +01004009 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
4010 hci_remote_oob_data_request_evt(hdev, skb);
4011 break;
4012
Andrei Emeltchenkod5e91192012-10-25 15:20:44 +03004013 case HCI_EV_PHY_LINK_COMPLETE:
4014 hci_phy_link_complete_evt(hdev, skb);
4015 break;
4016
Andrei Emeltchenko27695fb2012-10-25 15:20:45 +03004017 case HCI_EV_LOGICAL_LINK_COMPLETE:
4018 hci_loglink_complete_evt(hdev, skb);
4019 break;
4020
Andrei Emeltchenko606e2a12012-10-31 15:46:31 +02004021 case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4022 hci_disconn_loglink_complete_evt(hdev, skb);
4023 break;
4024
Andrei Emeltchenko9eef6b32012-10-31 15:46:32 +02004025 case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
4026 hci_disconn_phylink_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}