blob: 3476d5c7b02d9035f9bddbc8a98c33047cf46419 [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 <linux/module.h>
28
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/slab.h>
33#include <linux/poll.h>
34#include <linux/fcntl.h>
35#include <linux/init.h>
36#include <linux/skbuff.h>
37#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <net/sock.h>
39
40#include <asm/system.h>
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020041#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <asm/unaligned.h>
43
44#include <net/bluetooth/bluetooth.h>
45#include <net/bluetooth/hci_core.h>
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047/* Handle HCI Event packets */
48
Marcel Holtmanna9de9242007-10-20 13:33:56 +020049static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020051 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Marcel Holtmanna9de9242007-10-20 13:33:56 +020053 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Andre Guedese6d465c2011-11-09 17:14:26 -030055 if (status) {
56 hci_dev_lock(hdev);
57 mgmt_stop_discovery_failed(hdev, status);
58 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +020059 return;
Andre Guedese6d465c2011-11-09 17:14:26 -030060 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Andre Guedes89352e72011-11-04 14:16:53 -030062 clear_bit(HCI_INQUIRY, &hdev->flags);
63
Johan Hedberg56e5cb82011-11-08 20:40:16 +020064 hci_dev_lock(hdev);
Johan Hedbergff9ef572012-01-04 14:23:45 +020065 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Johan Hedberg56e5cb82011-11-08 20:40:16 +020066 hci_dev_unlock(hdev);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010067
Johan Hedberg23bb5762010-12-21 23:01:27 +020068 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010069
Marcel Holtmanna9de9242007-10-20 13:33:56 +020070 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071}
72
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020075 __u8 status = *((__u8 *) skb->data);
76
77 BT_DBG("%s status 0x%x", hdev->name, status);
78
79 if (status)
80 return;
81
Marcel Holtmanna9de9242007-10-20 13:33:56 +020082 hci_conn_check_pending(hdev);
83}
84
85static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
86{
87 BT_DBG("%s", hdev->name);
88}
89
90static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
91{
92 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Marcel Holtmanna9de9242007-10-20 13:33:56 +020095 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Marcel Holtmanna9de9242007-10-20 13:33:56 +020097 if (rp->status)
98 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200102 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
103 if (conn) {
104 if (rp->role)
105 conn->link_mode &= ~HCI_LM_MASTER;
106 else
107 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200109
110 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}
112
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200113static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
114{
115 struct hci_rp_read_link_policy *rp = (void *) skb->data;
116 struct hci_conn *conn;
117
118 BT_DBG("%s status 0x%x", hdev->name, rp->status);
119
120 if (rp->status)
121 return;
122
123 hci_dev_lock(hdev);
124
125 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
126 if (conn)
127 conn->link_policy = __le16_to_cpu(rp->policy);
128
129 hci_dev_unlock(hdev);
130}
131
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200132static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200134 struct hci_rp_write_link_policy *rp = (void *) skb->data;
135 struct hci_conn *conn;
136 void *sent;
137
138 BT_DBG("%s status 0x%x", hdev->name, rp->status);
139
140 if (rp->status)
141 return;
142
143 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
144 if (!sent)
145 return;
146
147 hci_dev_lock(hdev);
148
149 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200150 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700151 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200152
153 hci_dev_unlock(hdev);
154}
155
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200156static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
157{
158 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
159
160 BT_DBG("%s status 0x%x", hdev->name, rp->status);
161
162 if (rp->status)
163 return;
164
165 hdev->link_policy = __le16_to_cpu(rp->policy);
166}
167
168static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
169{
170 __u8 status = *((__u8 *) skb->data);
171 void *sent;
172
173 BT_DBG("%s status 0x%x", hdev->name, status);
174
175 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
176 if (!sent)
177 return;
178
179 if (!status)
180 hdev->link_policy = get_unaligned_le16(sent);
181
Johan Hedberg23bb5762010-12-21 23:01:27 +0200182 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200183}
184
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200185static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
186{
187 __u8 status = *((__u8 *) skb->data);
188
189 BT_DBG("%s status 0x%x", hdev->name, status);
190
Gustavo F. Padovan10572132011-03-16 15:36:29 -0300191 clear_bit(HCI_RESET, &hdev->flags);
192
Johan Hedberg23bb5762010-12-21 23:01:27 +0200193 hci_req_complete(hdev, HCI_OP_RESET, status);
Andre Guedesd23264a2011-11-25 20:53:38 -0300194
Johan Hedberga297e972012-02-21 17:55:47 +0200195 /* Reset all non-persistent flags */
196 hdev->dev_flags &= ~(BIT(HCI_LE_SCAN));
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200197}
198
199static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
200{
201 __u8 status = *((__u8 *) skb->data);
202 void *sent;
203
204 BT_DBG("%s status 0x%x", hdev->name, status);
205
206 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
207 if (!sent)
208 return;
209
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200210 hci_dev_lock(hdev);
211
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200212 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200213 mgmt_set_local_name_complete(hdev, sent, status);
Johan Hedbergb312b1612011-03-16 14:29:37 +0200214
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200215 if (status == 0)
216 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +0200217
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200218 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200219}
220
221static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
222{
223 struct hci_rp_read_local_name *rp = (void *) skb->data;
224
225 BT_DBG("%s status 0x%x", hdev->name, rp->status);
226
227 if (rp->status)
228 return;
229
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200230 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200231}
232
233static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
234{
235 __u8 status = *((__u8 *) skb->data);
236 void *sent;
237
238 BT_DBG("%s status 0x%x", hdev->name, status);
239
240 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
241 if (!sent)
242 return;
243
244 if (!status) {
245 __u8 param = *((__u8 *) sent);
246
247 if (param == AUTH_ENABLED)
248 set_bit(HCI_AUTH, &hdev->flags);
249 else
250 clear_bit(HCI_AUTH, &hdev->flags);
251 }
252
Johan Hedberg33ef95e2012-02-16 23:56:27 +0200253 if (test_bit(HCI_MGMT, &hdev->dev_flags))
254 mgmt_auth_enable_complete(hdev, status);
255
Johan Hedberg23bb5762010-12-21 23:01:27 +0200256 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200257}
258
259static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
260{
261 __u8 status = *((__u8 *) skb->data);
262 void *sent;
263
264 BT_DBG("%s status 0x%x", hdev->name, status);
265
266 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
267 if (!sent)
268 return;
269
270 if (!status) {
271 __u8 param = *((__u8 *) sent);
272
273 if (param)
274 set_bit(HCI_ENCRYPT, &hdev->flags);
275 else
276 clear_bit(HCI_ENCRYPT, &hdev->flags);
277 }
278
Johan Hedberg23bb5762010-12-21 23:01:27 +0200279 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200280}
281
282static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
283{
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200284 __u8 param, status = *((__u8 *) skb->data);
285 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200286 void *sent;
287
288 BT_DBG("%s status 0x%x", hdev->name, status);
289
290 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
291 if (!sent)
292 return;
293
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200294 param = *((__u8 *) sent);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200295
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200296 hci_dev_lock(hdev);
297
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200298 if (status != 0) {
Johan Hedberg744cf192011-11-08 20:40:14 +0200299 mgmt_write_scan_failed(hdev, param, status);
Johan Hedberg2d7cee52011-11-07 22:16:03 +0200300 hdev->discov_timeout = 0;
301 goto done;
302 }
303
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200304 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
305 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200306
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200307 if (param & SCAN_INQUIRY) {
308 set_bit(HCI_ISCAN, &hdev->flags);
309 if (!old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200310 mgmt_discoverable(hdev, 1);
Johan Hedberg16ab91a2011-11-07 22:16:02 +0200311 if (hdev->discov_timeout > 0) {
312 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
313 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
314 to);
315 }
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200316 } else if (old_iscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200317 mgmt_discoverable(hdev, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200318
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200319 if (param & SCAN_PAGE) {
320 set_bit(HCI_PSCAN, &hdev->flags);
321 if (!old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200322 mgmt_connectable(hdev, 1);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200323 } else if (old_pscan)
Johan Hedberg744cf192011-11-08 20:40:14 +0200324 mgmt_connectable(hdev, 0);
Johan Hedberg36f7fc72011-11-04 00:17:45 +0200325
326done:
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200327 hci_dev_unlock(hdev);
Johan Hedberg23bb5762010-12-21 23:01:27 +0200328 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200329}
330
331static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
332{
333 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
334
335 BT_DBG("%s status 0x%x", hdev->name, rp->status);
336
337 if (rp->status)
338 return;
339
340 memcpy(hdev->dev_class, rp->dev_class, 3);
341
342 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
343 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
344}
345
346static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
347{
348 __u8 status = *((__u8 *) skb->data);
349 void *sent;
350
351 BT_DBG("%s status 0x%x", hdev->name, status);
352
Marcel Holtmannf383f272008-07-14 20:13:47 +0200353 if (status)
354 return;
355
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200356 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
357 if (!sent)
358 return;
359
Marcel Holtmannf383f272008-07-14 20:13:47 +0200360 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200361}
362
363static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
364{
365 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200367
368 BT_DBG("%s status 0x%x", hdev->name, rp->status);
369
370 if (rp->status)
371 return;
372
373 setting = __le16_to_cpu(rp->voice_setting);
374
Marcel Holtmannf383f272008-07-14 20:13:47 +0200375 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200376 return;
377
378 hdev->voice_setting = setting;
379
380 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
381
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200382 if (hdev->notify)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200383 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200384}
385
386static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387{
388 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200389 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 void *sent;
391
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Marcel Holtmannf383f272008-07-14 20:13:47 +0200394 if (status)
395 return;
396
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200397 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
398 if (!sent)
399 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Marcel Holtmannf383f272008-07-14 20:13:47 +0200401 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Marcel Holtmannf383f272008-07-14 20:13:47 +0200403 if (hdev->voice_setting == setting)
404 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
Marcel Holtmannf383f272008-07-14 20:13:47 +0200406 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Marcel Holtmannf383f272008-07-14 20:13:47 +0200408 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
409
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200410 if (hdev->notify)
Marcel Holtmannf383f272008-07-14 20:13:47 +0200411 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412}
413
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200414static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200416 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200418 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Johan Hedberg23bb5762010-12-21 23:01:27 +0200420 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421}
422
Marcel Holtmann333140b2008-07-14 20:13:48 +0200423static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
424{
425 __u8 status = *((__u8 *) skb->data);
426 void *sent;
427
428 BT_DBG("%s status 0x%x", hdev->name, status);
429
Marcel Holtmann333140b2008-07-14 20:13:48 +0200430 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
431 if (!sent)
432 return;
433
Johan Hedberged2c4ee2012-02-17 00:56:28 +0200434 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedbergc0ecddc2012-02-22 12:38:31 +0200435 mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
436 else if (!status) {
437 if (*((u8 *) sent))
438 set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
439 else
440 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
441 }
Marcel Holtmann333140b2008-07-14 20:13:48 +0200442}
443
Johan Hedbergd5859e22011-01-25 01:19:58 +0200444static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
445{
446 if (hdev->features[6] & LMP_EXT_INQ)
447 return 2;
448
449 if (hdev->features[3] & LMP_RSSI_INQ)
450 return 1;
451
452 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
453 hdev->lmp_subver == 0x0757)
454 return 1;
455
456 if (hdev->manufacturer == 15) {
457 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
458 return 1;
459 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
460 return 1;
461 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
462 return 1;
463 }
464
465 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
466 hdev->lmp_subver == 0x1805)
467 return 1;
468
469 return 0;
470}
471
472static void hci_setup_inquiry_mode(struct hci_dev *hdev)
473{
474 u8 mode;
475
476 mode = hci_get_inquiry_mode(hdev);
477
478 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
479}
480
481static void hci_setup_event_mask(struct hci_dev *hdev)
482{
483 /* The second byte is 0xff instead of 0x9f (two reserved bits
484 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
485 * command otherwise */
486 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
487
Ville Tervo6de6c182011-05-27 11:16:21 +0300488 /* CSR 1.1 dongles does not accept any bitfield so don't try to set
489 * any event mask for pre 1.2 devices */
Andrei Emeltchenko5a13b092011-12-01 14:33:28 +0200490 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
Ville Tervo6de6c182011-05-27 11:16:21 +0300491 return;
492
493 events[4] |= 0x01; /* Flow Specification Complete */
494 events[4] |= 0x02; /* Inquiry Result with RSSI */
495 events[4] |= 0x04; /* Read Remote Extended Features Complete */
496 events[5] |= 0x08; /* Synchronous Connection Complete */
497 events[5] |= 0x10; /* Synchronous Connection Changed */
Johan Hedbergd5859e22011-01-25 01:19:58 +0200498
499 if (hdev->features[3] & LMP_RSSI_INQ)
500 events[4] |= 0x04; /* Inquiry Result with RSSI */
501
502 if (hdev->features[5] & LMP_SNIFF_SUBR)
503 events[5] |= 0x20; /* Sniff Subrating */
504
505 if (hdev->features[5] & LMP_PAUSE_ENC)
506 events[5] |= 0x80; /* Encryption Key Refresh Complete */
507
508 if (hdev->features[6] & LMP_EXT_INQ)
509 events[5] |= 0x40; /* Extended Inquiry Result */
510
511 if (hdev->features[6] & LMP_NO_FLUSH)
512 events[7] |= 0x01; /* Enhanced Flush Complete */
513
514 if (hdev->features[7] & LMP_LSTO)
515 events[6] |= 0x80; /* Link Supervision Timeout Changed */
516
517 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
518 events[6] |= 0x01; /* IO Capability Request */
519 events[6] |= 0x02; /* IO Capability Response */
520 events[6] |= 0x04; /* User Confirmation Request */
521 events[6] |= 0x08; /* User Passkey Request */
522 events[6] |= 0x10; /* Remote OOB Data Request */
523 events[6] |= 0x20; /* Simple Pairing Complete */
524 events[7] |= 0x04; /* User Passkey Notification */
525 events[7] |= 0x08; /* Keypress Notification */
526 events[7] |= 0x10; /* Remote Host Supported
527 * Features Notification */
528 }
529
530 if (hdev->features[4] & LMP_LE)
531 events[7] |= 0x20; /* LE Meta-Event */
532
533 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
534}
535
Andre Guedese6100a22011-06-30 19:20:54 -0300536static void hci_set_le_support(struct hci_dev *hdev)
537{
538 struct hci_cp_write_le_host_supported cp;
539
540 memset(&cp, 0, sizeof(cp));
541
542 if (enable_le) {
543 cp.le = 1;
544 cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
545 }
546
547 hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
548}
549
Johan Hedbergd5859e22011-01-25 01:19:58 +0200550static void hci_setup(struct hci_dev *hdev)
551{
Andrei Emeltchenkoe61ef4992011-12-19 16:31:27 +0200552 if (hdev->dev_type != HCI_BREDR)
553 return;
554
Johan Hedbergd5859e22011-01-25 01:19:58 +0200555 hci_setup_event_mask(hdev);
556
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200557 if (hdev->hci_ver > BLUETOOTH_VER_1_1)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200558 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
559
Johan Hedberg54d04db2012-02-22 15:47:48 +0200560 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
561 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
562 u8 mode = 0x01;
563 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
564 sizeof(mode), &mode);
565 } else {
566 struct hci_cp_write_eir cp;
567
568 memset(hdev->eir, 0, sizeof(hdev->eir));
569 memset(&cp, 0, sizeof(cp));
570
571 hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
572 }
Johan Hedbergd5859e22011-01-25 01:19:58 +0200573 }
574
575 if (hdev->features[3] & LMP_RSSI_INQ)
576 hci_setup_inquiry_mode(hdev);
577
578 if (hdev->features[7] & LMP_INQ_TX_PWR)
579 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
Andre Guedes971e3a42011-06-30 19:20:52 -0300580
581 if (hdev->features[7] & LMP_EXTFEATURES) {
582 struct hci_cp_read_local_ext_features cp;
583
584 cp.page = 0x01;
585 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
586 sizeof(cp), &cp);
587 }
Andre Guedese6100a22011-06-30 19:20:54 -0300588
Johan Hedberg47990ea2012-02-22 11:58:37 +0200589 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
590 u8 enable = 1;
591 hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
592 sizeof(enable), &enable);
593 }
594
Andre Guedese6100a22011-06-30 19:20:54 -0300595 if (hdev->features[4] & LMP_LE)
596 hci_set_le_support(hdev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200597}
598
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200599static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
600{
601 struct hci_rp_read_local_version *rp = (void *) skb->data;
602
603 BT_DBG("%s status 0x%x", hdev->name, rp->status);
604
605 if (rp->status)
606 return;
607
608 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200609 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200610 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200611 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200612 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200613
614 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
615 hdev->manufacturer,
616 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200617
618 if (test_bit(HCI_INIT, &hdev->flags))
619 hci_setup(hdev);
620}
621
622static void hci_setup_link_policy(struct hci_dev *hdev)
623{
624 u16 link_policy = 0;
625
626 if (hdev->features[0] & LMP_RSWITCH)
627 link_policy |= HCI_LP_RSWITCH;
628 if (hdev->features[0] & LMP_HOLD)
629 link_policy |= HCI_LP_HOLD;
630 if (hdev->features[0] & LMP_SNIFF)
631 link_policy |= HCI_LP_SNIFF;
632 if (hdev->features[1] & LMP_PARK)
633 link_policy |= HCI_LP_PARK;
634
635 link_policy = cpu_to_le16(link_policy);
636 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
637 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200638}
639
640static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
641{
642 struct hci_rp_read_local_commands *rp = (void *) skb->data;
643
644 BT_DBG("%s status 0x%x", hdev->name, rp->status);
645
646 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200647 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200648
649 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200650
651 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
652 hci_setup_link_policy(hdev);
653
654done:
655 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200656}
657
658static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
659{
660 struct hci_rp_read_local_features *rp = (void *) skb->data;
661
662 BT_DBG("%s status 0x%x", hdev->name, rp->status);
663
664 if (rp->status)
665 return;
666
667 memcpy(hdev->features, rp->features, 8);
668
669 /* Adjust default settings according to features
670 * supported by device. */
671
672 if (hdev->features[0] & LMP_3SLOT)
673 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
674
675 if (hdev->features[0] & LMP_5SLOT)
676 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
677
678 if (hdev->features[1] & LMP_HV2) {
679 hdev->pkt_type |= (HCI_HV2);
680 hdev->esco_type |= (ESCO_HV2);
681 }
682
683 if (hdev->features[1] & LMP_HV3) {
684 hdev->pkt_type |= (HCI_HV3);
685 hdev->esco_type |= (ESCO_HV3);
686 }
687
688 if (hdev->features[3] & LMP_ESCO)
689 hdev->esco_type |= (ESCO_EV3);
690
691 if (hdev->features[4] & LMP_EV4)
692 hdev->esco_type |= (ESCO_EV4);
693
694 if (hdev->features[4] & LMP_EV5)
695 hdev->esco_type |= (ESCO_EV5);
696
Marcel Holtmannefc76882009-02-06 09:13:37 +0100697 if (hdev->features[5] & LMP_EDR_ESCO_2M)
698 hdev->esco_type |= (ESCO_2EV3);
699
700 if (hdev->features[5] & LMP_EDR_ESCO_3M)
701 hdev->esco_type |= (ESCO_3EV3);
702
703 if (hdev->features[5] & LMP_EDR_3S_ESCO)
704 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
705
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200706 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
707 hdev->features[0], hdev->features[1],
708 hdev->features[2], hdev->features[3],
709 hdev->features[4], hdev->features[5],
710 hdev->features[6], hdev->features[7]);
711}
712
Andre Guedes971e3a42011-06-30 19:20:52 -0300713static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
714 struct sk_buff *skb)
715{
716 struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
717
718 BT_DBG("%s status 0x%x", hdev->name, rp->status);
719
720 if (rp->status)
721 return;
722
Andre Guedesb5b32b62011-12-30 10:34:04 -0300723 switch (rp->page) {
724 case 0:
725 memcpy(hdev->features, rp->features, 8);
726 break;
727 case 1:
728 memcpy(hdev->host_features, rp->features, 8);
729 break;
730 }
Andre Guedes971e3a42011-06-30 19:20:52 -0300731
732 hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
733}
734
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +0200735static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
736 struct sk_buff *skb)
737{
738 struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
739
740 BT_DBG("%s status 0x%x", hdev->name, rp->status);
741
742 if (rp->status)
743 return;
744
745 hdev->flow_ctl_mode = rp->mode;
746
747 hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
748}
749
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200750static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
751{
752 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
753
754 BT_DBG("%s status 0x%x", hdev->name, rp->status);
755
756 if (rp->status)
757 return;
758
759 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
760 hdev->sco_mtu = rp->sco_mtu;
761 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
762 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
763
764 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
765 hdev->sco_mtu = 64;
766 hdev->sco_pkts = 8;
767 }
768
769 hdev->acl_cnt = hdev->acl_pkts;
770 hdev->sco_cnt = hdev->sco_pkts;
771
772 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
773 hdev->acl_mtu, hdev->acl_pkts,
774 hdev->sco_mtu, hdev->sco_pkts);
775}
776
777static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
778{
779 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
780
781 BT_DBG("%s status 0x%x", hdev->name, rp->status);
782
783 if (!rp->status)
784 bacpy(&hdev->bdaddr, &rp->bdaddr);
785
Johan Hedberg23bb5762010-12-21 23:01:27 +0200786 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
787}
788
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +0200789static void hci_cc_read_data_block_size(struct hci_dev *hdev,
790 struct sk_buff *skb)
791{
792 struct hci_rp_read_data_block_size *rp = (void *) skb->data;
793
794 BT_DBG("%s status 0x%x", hdev->name, rp->status);
795
796 if (rp->status)
797 return;
798
799 hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
800 hdev->block_len = __le16_to_cpu(rp->block_len);
801 hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
802
803 hdev->block_cnt = hdev->num_blocks;
804
805 BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
806 hdev->block_cnt, hdev->block_len);
807
808 hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
809}
810
Johan Hedberg23bb5762010-12-21 23:01:27 +0200811static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
812{
813 __u8 status = *((__u8 *) skb->data);
814
815 BT_DBG("%s status 0x%x", hdev->name, status);
816
817 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200818}
819
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +0300820static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
821 struct sk_buff *skb)
822{
823 struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
824
825 BT_DBG("%s status 0x%x", hdev->name, rp->status);
826
827 if (rp->status)
828 return;
829
830 hdev->amp_status = rp->amp_status;
831 hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
832 hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
833 hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
834 hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
835 hdev->amp_type = rp->amp_type;
836 hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
837 hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
838 hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
839 hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
840
841 hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
842}
843
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200844static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
845 struct sk_buff *skb)
846{
847 __u8 status = *((__u8 *) skb->data);
848
849 BT_DBG("%s status 0x%x", hdev->name, status);
850
851 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
852}
853
Johan Hedbergd5859e22011-01-25 01:19:58 +0200854static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
855{
856 __u8 status = *((__u8 *) skb->data);
857
858 BT_DBG("%s status 0x%x", hdev->name, status);
859
860 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
861}
862
863static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
864 struct sk_buff *skb)
865{
866 __u8 status = *((__u8 *) skb->data);
867
868 BT_DBG("%s status 0x%x", hdev->name, status);
869
870 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
871}
872
873static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
874 struct sk_buff *skb)
875{
876 __u8 status = *((__u8 *) skb->data);
877
878 BT_DBG("%s status 0x%x", hdev->name, status);
879
880 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
881}
882
883static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
884{
885 __u8 status = *((__u8 *) skb->data);
886
887 BT_DBG("%s status 0x%x", hdev->name, status);
888
889 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
890}
891
Johan Hedberg980e1a52011-01-22 06:10:07 +0200892static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
893{
894 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
895 struct hci_cp_pin_code_reply *cp;
896 struct hci_conn *conn;
897
898 BT_DBG("%s status 0x%x", hdev->name, rp->status);
899
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200900 hci_dev_lock(hdev);
901
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200902 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200903 mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200904
905 if (rp->status != 0)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200906 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200907
908 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
909 if (!cp)
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200910 goto unlock;
Johan Hedberg980e1a52011-01-22 06:10:07 +0200911
912 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
913 if (conn)
914 conn->pin_length = cp->pin_len;
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200915
916unlock:
917 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200918}
919
920static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
921{
922 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
923
924 BT_DBG("%s status 0x%x", hdev->name, rp->status);
925
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200926 hci_dev_lock(hdev);
927
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200928 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200929 mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg980e1a52011-01-22 06:10:07 +0200930 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200931
932 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200933}
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200934
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300935static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
936 struct sk_buff *skb)
937{
938 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
939
940 BT_DBG("%s status 0x%x", hdev->name, rp->status);
941
942 if (rp->status)
943 return;
944
945 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
946 hdev->le_pkts = rp->le_max_pkt;
947
948 hdev->le_cnt = hdev->le_pkts;
949
950 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
951
952 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
953}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200954
Johan Hedberga5c29682011-02-19 12:05:57 -0300955static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
956{
957 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
958
959 BT_DBG("%s status 0x%x", hdev->name, rp->status);
960
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200961 hci_dev_lock(hdev);
962
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200963 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200964 mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
965 0, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200966
967 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300968}
969
970static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
971 struct sk_buff *skb)
972{
973 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
974
975 BT_DBG("%s status 0x%x", hdev->name, rp->status);
976
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200977 hci_dev_lock(hdev);
978
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200979 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg744cf192011-11-08 20:40:14 +0200980 mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200981 ACL_LINK, 0,
Johan Hedberga5c29682011-02-19 12:05:57 -0300982 rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +0200983
984 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -0300985}
986
Brian Gix1143d452011-11-23 08:28:34 -0800987static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
988{
989 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
990
991 BT_DBG("%s status 0x%x", hdev->name, rp->status);
992
993 hci_dev_lock(hdev);
994
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200995 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +0200996 mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
997 0, rp->status);
Brian Gix1143d452011-11-23 08:28:34 -0800998
999 hci_dev_unlock(hdev);
1000}
1001
1002static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
1003 struct sk_buff *skb)
1004{
1005 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1006
1007 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1008
1009 hci_dev_lock(hdev);
1010
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001011 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Brian Gix1143d452011-11-23 08:28:34 -08001012 mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
Johan Hedberg272d90d2012-02-09 15:26:12 +02001013 ACL_LINK, 0,
Brian Gix1143d452011-11-23 08:28:34 -08001014 rp->status);
1015
1016 hci_dev_unlock(hdev);
1017}
1018
Szymon Jancc35938b2011-03-22 13:12:21 +01001019static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1020 struct sk_buff *skb)
1021{
1022 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1023
1024 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1025
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001026 hci_dev_lock(hdev);
Johan Hedberg744cf192011-11-08 20:40:14 +02001027 mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
Szymon Jancc35938b2011-03-22 13:12:21 +01001028 rp->randomizer, rp->status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001029 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01001030}
1031
Andre Guedes07f7fa52011-12-02 21:13:31 +09001032static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1033{
1034 __u8 status = *((__u8 *) skb->data);
1035
1036 BT_DBG("%s status 0x%x", hdev->name, status);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001037
1038 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
Andre Guedes3fd24152012-02-03 17:48:01 -03001039
1040 if (status) {
1041 hci_dev_lock(hdev);
1042 mgmt_start_discovery_failed(hdev, status);
1043 hci_dev_unlock(hdev);
1044 return;
1045 }
Andre Guedes07f7fa52011-12-02 21:13:31 +09001046}
1047
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001048static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1049 struct sk_buff *skb)
1050{
1051 struct hci_cp_le_set_scan_enable *cp;
1052 __u8 status = *((__u8 *) skb->data);
1053
1054 BT_DBG("%s status 0x%x", hdev->name, status);
1055
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001056 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1057 if (!cp)
1058 return;
1059
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001060 switch (cp->enable) {
1061 case LE_SCANNING_ENABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001062 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1063
Andre Guedes3fd24152012-02-03 17:48:01 -03001064 if (status) {
1065 hci_dev_lock(hdev);
1066 mgmt_start_discovery_failed(hdev, status);
1067 hci_dev_unlock(hdev);
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001068 return;
Andre Guedes3fd24152012-02-03 17:48:01 -03001069 }
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001070
Andre Guedesd23264a2011-11-25 20:53:38 -03001071 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1072
Gustavo F. Padovandb323f22011-06-20 16:39:29 -03001073 cancel_delayed_work_sync(&hdev->adv_work);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001074
1075 hci_dev_lock(hdev);
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001076 hci_adv_entries_clear(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001077 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedesa8f13c82011-09-09 18:56:24 -03001078 hci_dev_unlock(hdev);
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001079 break;
1080
1081 case LE_SCANNING_DISABLED:
Andre Guedes7ba8b4b2012-02-03 17:47:59 -03001082 if (status)
1083 return;
1084
Andre Guedesd23264a2011-11-25 20:53:38 -03001085 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1086
Andre Guedesd0843292012-01-02 19:18:11 -03001087 schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
Andre Guedes5e0452c2012-02-17 20:39:38 -03001088
1089 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
1090 mgmt_interleaved_discovery(hdev);
1091 } else {
1092 hci_dev_lock(hdev);
1093 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1094 hci_dev_unlock(hdev);
1095 }
1096
Andrei Emeltchenko68a8aea2011-12-19 16:14:18 +02001097 break;
1098
1099 default:
1100 BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
1101 break;
Andre Guedes35815082011-05-26 16:23:53 -03001102 }
Andre Guedeseb9d91f2011-05-26 16:23:52 -03001103}
1104
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001105static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1106{
1107 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1108
1109 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1110
1111 if (rp->status)
1112 return;
1113
1114 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1115}
1116
1117static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1118{
1119 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1120
1121 BT_DBG("%s status 0x%x", hdev->name, rp->status);
1122
1123 if (rp->status)
1124 return;
1125
1126 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1127}
1128
Andre Guedesf9b49302011-06-30 19:20:53 -03001129static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1130 struct sk_buff *skb)
1131{
1132 struct hci_cp_read_local_ext_features cp;
1133 __u8 status = *((__u8 *) skb->data);
1134
1135 BT_DBG("%s status 0x%x", hdev->name, status);
1136
1137 if (status)
1138 return;
1139
1140 cp.page = 0x01;
1141 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1142}
1143
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001144static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1145{
1146 BT_DBG("%s status 0x%x", hdev->name, status);
1147
1148 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +02001149 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001150 hci_conn_check_pending(hdev);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001151 hci_dev_lock(hdev);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001152 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Andre Guedes7a135102011-11-09 17:14:25 -03001153 mgmt_start_discovery_failed(hdev, status);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001154 hci_dev_unlock(hdev);
Johan Hedberg314b2382011-04-27 10:29:57 -04001155 return;
1156 }
1157
Andre Guedes89352e72011-11-04 14:16:53 -03001158 set_bit(HCI_INQUIRY, &hdev->flags);
1159
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001160 hci_dev_lock(hdev);
Andre Guedes343f9352012-02-17 20:39:37 -03001161 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001162 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001163}
1164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
1166{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001167 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001170 BT_DBG("%s status 0x%x", hdev->name, status);
1171
1172 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 if (!cp)
1174 return;
1175
1176 hci_dev_lock(hdev);
1177
1178 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1179
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001180 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182 if (status) {
1183 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +02001184 if (status != 0x0c || conn->attempt > 2) {
1185 conn->state = BT_CLOSED;
1186 hci_proto_connect_cfm(conn, status);
1187 hci_conn_del(conn);
1188 } else
1189 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 }
1191 } else {
1192 if (!conn) {
1193 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
1194 if (conn) {
Johan Hedberga0c808b2012-01-16 09:49:58 +02001195 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 conn->link_mode |= HCI_LM_MASTER;
1197 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001198 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 }
1200 }
1201
1202 hci_dev_unlock(hdev);
1203}
1204
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001205static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001207 struct hci_cp_add_sco *cp;
1208 struct hci_conn *acl, *sco;
1209 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001211 BT_DBG("%s status 0x%x", hdev->name, status);
1212
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001213 if (!status)
1214 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001216 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
1217 if (!cp)
1218 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001220 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001222 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001223
1224 hci_dev_lock(hdev);
1225
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001226 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001227 if (acl) {
1228 sco = acl->link;
1229 if (sco) {
1230 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001231
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001232 hci_proto_connect_cfm(sco, status);
1233 hci_conn_del(sco);
1234 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001235 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +01001236
1237 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238}
1239
Marcel Holtmannf8558552008-07-14 20:13:49 +02001240static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1241{
1242 struct hci_cp_auth_requested *cp;
1243 struct hci_conn *conn;
1244
1245 BT_DBG("%s status 0x%x", hdev->name, status);
1246
1247 if (!status)
1248 return;
1249
1250 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1251 if (!cp)
1252 return;
1253
1254 hci_dev_lock(hdev);
1255
1256 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1257 if (conn) {
1258 if (conn->state == BT_CONFIG) {
1259 hci_proto_connect_cfm(conn, status);
1260 hci_conn_put(conn);
1261 }
1262 }
1263
1264 hci_dev_unlock(hdev);
1265}
1266
1267static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1268{
1269 struct hci_cp_set_conn_encrypt *cp;
1270 struct hci_conn *conn;
1271
1272 BT_DBG("%s status 0x%x", hdev->name, status);
1273
1274 if (!status)
1275 return;
1276
1277 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1278 if (!cp)
1279 return;
1280
1281 hci_dev_lock(hdev);
1282
1283 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1284 if (conn) {
1285 if (conn->state == BT_CONFIG) {
1286 hci_proto_connect_cfm(conn, status);
1287 hci_conn_put(conn);
1288 }
1289 }
1290
1291 hci_dev_unlock(hdev);
1292}
1293
Johan Hedberg127178d2010-11-18 22:22:29 +02001294static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +01001295 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +02001296{
Johan Hedberg392599b2010-11-18 22:22:28 +02001297 if (conn->state != BT_CONFIG || !conn->out)
1298 return 0;
1299
Johan Hedberg765c2a92011-01-19 12:06:52 +05301300 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +02001301 return 0;
1302
1303 /* Only request authentication for SSP connections or non-SSP
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001304 * devices with sec_level HIGH or if MITM protection is requested */
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001305 if (!hci_conn_ssp_enabled(conn) &&
Vinicius Costa Gomese9bf2bf2011-09-02 14:51:20 -03001306 conn->pending_sec_level != BT_SECURITY_HIGH &&
1307 !(conn->auth_type & 0x01))
Johan Hedberg392599b2010-11-18 22:22:28 +02001308 return 0;
1309
Johan Hedberg392599b2010-11-18 22:22:28 +02001310 return 1;
1311}
1312
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001313static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
1314{
1315 struct hci_cp_remote_name_req cp;
1316
1317 memset(&cp, 0, sizeof(cp));
1318
1319 bacpy(&cp.bdaddr, &e->data.bdaddr);
1320 cp.pscan_rep_mode = e->data.pscan_rep_mode;
1321 cp.pscan_mode = e->data.pscan_mode;
1322 cp.clock_offset = e->data.clock_offset;
1323
1324 return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1325}
1326
Johan Hedbergb644ba32012-01-17 21:48:47 +02001327static bool hci_resolve_next_name(struct hci_dev *hdev)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001328{
1329 struct discovery_state *discov = &hdev->discovery;
1330 struct inquiry_entry *e;
1331
Johan Hedbergb644ba32012-01-17 21:48:47 +02001332 if (list_empty(&discov->resolve))
1333 return false;
1334
1335 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1336 if (hci_resolve_name(hdev, e) == 0) {
1337 e->name_state = NAME_PENDING;
1338 return true;
1339 }
1340
1341 return false;
1342}
1343
1344static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1345 bdaddr_t *bdaddr, u8 *name, u8 name_len)
1346{
1347 struct discovery_state *discov = &hdev->discovery;
1348 struct inquiry_entry *e;
1349
1350 if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1351 mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1352 name, name_len, conn->dev_class);
1353
1354 if (discov->state == DISCOVERY_STOPPED)
1355 return;
1356
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001357 if (discov->state == DISCOVERY_STOPPING)
1358 goto discov_complete;
1359
1360 if (discov->state != DISCOVERY_RESOLVING)
1361 return;
1362
1363 e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
1364 if (e) {
1365 e->name_state = NAME_KNOWN;
1366 list_del(&e->list);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001367 if (name)
1368 mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1369 e->data.rssi, name, name_len);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001370 }
1371
Johan Hedbergb644ba32012-01-17 21:48:47 +02001372 if (hci_resolve_next_name(hdev))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001373 return;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001374
1375discov_complete:
1376 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1377}
1378
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001379static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
1380{
Johan Hedberg127178d2010-11-18 22:22:29 +02001381 struct hci_cp_remote_name_req *cp;
1382 struct hci_conn *conn;
1383
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001384 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +02001385
1386 /* If successful wait for the name req complete event before
1387 * checking for the need to do authentication */
1388 if (!status)
1389 return;
1390
1391 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1392 if (!cp)
1393 return;
1394
1395 hci_dev_lock(hdev);
1396
1397 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001398
1399 if (test_bit(HCI_MGMT, &hdev->dev_flags))
1400 hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1401
Johan Hedberg79c6c702011-04-28 11:28:55 -07001402 if (!conn)
1403 goto unlock;
1404
1405 if (!hci_outgoing_auth_needed(hdev, conn))
1406 goto unlock;
1407
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001408 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001409 struct hci_cp_auth_requested cp;
1410 cp.handle = __cpu_to_le16(conn->handle);
1411 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1412 }
1413
Johan Hedberg79c6c702011-04-28 11:28:55 -07001414unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001415 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001416}
1417
Marcel Holtmann769be972008-07-14 20:13:49 +02001418static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1419{
1420 struct hci_cp_read_remote_features *cp;
1421 struct hci_conn *conn;
1422
1423 BT_DBG("%s status 0x%x", hdev->name, status);
1424
1425 if (!status)
1426 return;
1427
1428 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1429 if (!cp)
1430 return;
1431
1432 hci_dev_lock(hdev);
1433
1434 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1435 if (conn) {
1436 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001437 hci_proto_connect_cfm(conn, status);
1438 hci_conn_put(conn);
1439 }
1440 }
1441
1442 hci_dev_unlock(hdev);
1443}
1444
1445static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1446{
1447 struct hci_cp_read_remote_ext_features *cp;
1448 struct hci_conn *conn;
1449
1450 BT_DBG("%s status 0x%x", hdev->name, status);
1451
1452 if (!status)
1453 return;
1454
1455 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_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
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001472static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1473{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001474 struct hci_cp_setup_sync_conn *cp;
1475 struct hci_conn *acl, *sco;
1476 __u16 handle;
1477
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001478 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001479
1480 if (!status)
1481 return;
1482
1483 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1484 if (!cp)
1485 return;
1486
1487 handle = __le16_to_cpu(cp->handle);
1488
1489 BT_DBG("%s handle %d", hdev->name, handle);
1490
1491 hci_dev_lock(hdev);
1492
1493 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001494 if (acl) {
1495 sco = acl->link;
1496 if (sco) {
1497 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001498
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001499 hci_proto_connect_cfm(sco, status);
1500 hci_conn_del(sco);
1501 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001502 }
1503
1504 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001505}
1506
1507static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1508{
1509 struct hci_cp_sniff_mode *cp;
1510 struct hci_conn *conn;
1511
1512 BT_DBG("%s status 0x%x", hdev->name, status);
1513
1514 if (!status)
1515 return;
1516
1517 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1518 if (!cp)
1519 return;
1520
1521 hci_dev_lock(hdev);
1522
1523 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001524 if (conn) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001525 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001526
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001527 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001528 hci_sco_setup(conn, status);
1529 }
1530
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001531 hci_dev_unlock(hdev);
1532}
1533
1534static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1535{
1536 struct hci_cp_exit_sniff_mode *cp;
1537 struct hci_conn *conn;
1538
1539 BT_DBG("%s status 0x%x", hdev->name, status);
1540
1541 if (!status)
1542 return;
1543
1544 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_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
Johan Hedberg88c3df12012-02-09 14:27:38 +02001561static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1562{
1563 struct hci_cp_disconnect *cp;
1564 struct hci_conn *conn;
1565
1566 if (!status)
1567 return;
1568
1569 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1570 if (!cp)
1571 return;
1572
1573 hci_dev_lock(hdev);
1574
1575 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1576 if (conn)
1577 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1578 conn->dst_type, status);
1579
1580 hci_dev_unlock(hdev);
1581}
1582
Ville Tervofcd89c02011-02-10 22:38:47 -03001583static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1584{
1585 struct hci_cp_le_create_conn *cp;
1586 struct hci_conn *conn;
1587
1588 BT_DBG("%s status 0x%x", hdev->name, status);
1589
1590 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1591 if (!cp)
1592 return;
1593
1594 hci_dev_lock(hdev);
1595
1596 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1597
1598 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1599 conn);
1600
1601 if (status) {
1602 if (conn && conn->state == BT_CONNECT) {
1603 conn->state = BT_CLOSED;
1604 hci_proto_connect_cfm(conn, status);
1605 hci_conn_del(conn);
1606 }
1607 } else {
1608 if (!conn) {
1609 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
Andre Guedes29b79882011-05-31 14:20:54 -03001610 if (conn) {
1611 conn->dst_type = cp->peer_addr_type;
Johan Hedberga0c808b2012-01-16 09:49:58 +02001612 conn->out = true;
Andre Guedes29b79882011-05-31 14:20:54 -03001613 } else {
Ville Tervofcd89c02011-02-10 22:38:47 -03001614 BT_ERR("No memory for new connection");
Andre Guedes29b79882011-05-31 14:20:54 -03001615 }
Ville Tervofcd89c02011-02-10 22:38:47 -03001616 }
1617 }
1618
1619 hci_dev_unlock(hdev);
1620}
1621
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03001622static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1623{
1624 BT_DBG("%s status 0x%x", hdev->name, status);
1625}
1626
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001627static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1628{
1629 __u8 status = *((__u8 *) skb->data);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001630 struct discovery_state *discov = &hdev->discovery;
1631 struct inquiry_entry *e;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001632
1633 BT_DBG("%s status %d", hdev->name, status);
1634
Johan Hedberg23bb5762010-12-21 23:01:27 +02001635 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001636
1637 hci_conn_check_pending(hdev);
Andre Guedes89352e72011-11-04 14:16:53 -03001638
1639 if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1640 return;
1641
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001642 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001643 return;
1644
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001645 hci_dev_lock(hdev);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001646
Andre Guedes343f9352012-02-17 20:39:37 -03001647 if (discov->state != DISCOVERY_FINDING)
Johan Hedberg30dc78e2012-01-04 15:44:20 +02001648 goto unlock;
1649
1650 if (list_empty(&discov->resolve)) {
1651 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1652 goto unlock;
1653 }
1654
1655 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1656 if (e && hci_resolve_name(hdev, e) == 0) {
1657 e->name_state = NAME_PENDING;
1658 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
1659 } else {
1660 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1661 }
1662
1663unlock:
Johan Hedberg56e5cb82011-11-08 20:40:16 +02001664 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001665}
1666
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1668{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001669 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001670 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 int num_rsp = *((__u8 *) skb->data);
1672
1673 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1674
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001675 if (!num_rsp)
1676 return;
1677
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001679
Johan Hedberge17acd42011-03-30 23:57:16 +03001680 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg31754052012-01-04 13:39:52 +02001681 bool name_known;
1682
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 bacpy(&data.bdaddr, &info->bdaddr);
1684 data.pscan_rep_mode = info->pscan_rep_mode;
1685 data.pscan_period_mode = info->pscan_period_mode;
1686 data.pscan_mode = info->pscan_mode;
1687 memcpy(data.dev_class, info->dev_class, 3);
1688 data.clock_offset = info->clock_offset;
1689 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001690 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02001691
1692 name_known = hci_inquiry_cache_update(hdev, &data, false);
Johan Hedberg48264f02011-11-09 13:58:58 +02001693 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Andre Guedes7d262f82012-01-10 18:20:49 -03001694 info->dev_class, 0, !name_known,
1695 NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001697
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 hci_dev_unlock(hdev);
1699}
1700
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001701static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001703 struct hci_ev_conn_complete *ev = (void *) skb->data;
1704 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001706 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001709
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001710 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001711 if (!conn) {
1712 if (ev->link_type != SCO_LINK)
1713 goto unlock;
1714
1715 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1716 if (!conn)
1717 goto unlock;
1718
1719 conn->type = SCO_LINK;
1720 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001721
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001722 if (!ev->status) {
1723 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001724
1725 if (conn->type == ACL_LINK) {
1726 conn->state = BT_CONFIG;
1727 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001728 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann769be972008-07-14 20:13:49 +02001729 } else
1730 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001731
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001732 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001733 hci_conn_add_sysfs(conn);
1734
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001735 if (test_bit(HCI_AUTH, &hdev->flags))
1736 conn->link_mode |= HCI_LM_AUTH;
1737
1738 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1739 conn->link_mode |= HCI_LM_ENCRYPT;
1740
1741 /* Get remote features */
1742 if (conn->type == ACL_LINK) {
1743 struct hci_cp_read_remote_features cp;
1744 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001745 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1746 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001747 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001748
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001749 /* Set packet type for incoming connection */
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +02001750 if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001751 struct hci_cp_change_conn_ptype cp;
1752 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001753 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1754 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1755 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001756 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001757 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001758 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001759 if (conn->type == ACL_LINK)
Johan Hedberg744cf192011-11-08 20:40:14 +02001760 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001761 conn->dst_type, ev->status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001762 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001763
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001764 if (conn->type == ACL_LINK)
1765 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001766
Marcel Holtmann769be972008-07-14 20:13:49 +02001767 if (ev->status) {
1768 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001769 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001770 } else if (ev->link_type != ACL_LINK)
1771 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001772
1773unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001775
1776 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777}
1778
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1780{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001781 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 int mask = hdev->link_mode;
1783
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001784 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1785 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
1787 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1788
Szymon Janc138d22e2011-02-17 16:44:23 +01001789 if ((mask & HCI_LM_ACCEPT) &&
1790 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001792 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
1795 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001796
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001797 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1798 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001799 memcpy(ie->data.dev_class, ev->dev_class, 3);
1800
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1802 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001803 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1804 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001805 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 hci_dev_unlock(hdev);
1807 return;
1808 }
1809 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001810
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 memcpy(conn->dev_class, ev->dev_class, 3);
1812 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001813
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 hci_dev_unlock(hdev);
1815
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001816 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1817 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001819 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001821 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1822 cp.role = 0x00; /* Become master */
1823 else
1824 cp.role = 0x01; /* Remain slave */
1825
1826 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1827 sizeof(cp), &cp);
1828 } else {
1829 struct hci_cp_accept_sync_conn_req cp;
1830
1831 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001832 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001833
1834 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1835 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1836 cp.max_latency = cpu_to_le16(0xffff);
1837 cp.content_format = cpu_to_le16(hdev->voice_setting);
1838 cp.retrans_effort = 0xff;
1839
1840 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1841 sizeof(cp), &cp);
1842 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 } else {
1844 /* Connection rejected */
1845 struct hci_cp_reject_conn_req cp;
1846
1847 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001848 cp.reason = HCI_ERROR_REJ_BAD_ADDR;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001849 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 }
1851}
1852
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1854{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001855 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001856 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
1858 BT_DBG("%s status %d", hdev->name, ev->status);
1859
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 hci_dev_lock(hdev);
1861
Marcel Holtmann04837f62006-07-03 10:02:33 +02001862 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001863 if (!conn)
1864 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001865
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001866 if (ev->status == 0)
1867 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Johan Hedbergb644ba32012-01-17 21:48:47 +02001869 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1870 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001871 if (ev->status != 0)
Johan Hedberg88c3df12012-02-09 14:27:38 +02001872 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1873 conn->dst_type, ev->status);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001874 else
Johan Hedbergafc747a2012-01-15 18:11:07 +02001875 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
Johan Hedberg48264f02011-11-09 13:58:58 +02001876 conn->dst_type);
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001877 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001878
Johan Hedberg37d9ef72011-11-10 15:54:39 +02001879 if (ev->status == 0) {
1880 hci_proto_disconn_cfm(conn, ev->reason);
1881 hci_conn_del(conn);
1882 }
Johan Hedbergf7520542011-01-20 12:34:39 +02001883
1884unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 hci_dev_unlock(hdev);
1886}
1887
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001888static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1889{
1890 struct hci_ev_auth_complete *ev = (void *) skb->data;
1891 struct hci_conn *conn;
1892
1893 BT_DBG("%s status %d", hdev->name, ev->status);
1894
1895 hci_dev_lock(hdev);
1896
1897 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001898 if (!conn)
1899 goto unlock;
1900
1901 if (!ev->status) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001902 if (!hci_conn_ssp_enabled(conn) &&
1903 test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001904 BT_INFO("re-auth of legacy device is not possible.");
Johan Hedberg2a611692011-02-19 12:06:00 -03001905 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001906 conn->link_mode |= HCI_LM_AUTH;
1907 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001908 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001909 } else {
Johan Hedbergbab73cb2012-02-09 16:07:29 +02001910 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1911 ev->status);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001912 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001913
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001914 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1915 clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001916
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001917 if (conn->state == BT_CONFIG) {
Johan Hedbergaa64a8b2012-01-18 21:33:12 +02001918 if (!ev->status && hci_conn_ssp_enabled(conn)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001919 struct hci_cp_set_conn_encrypt cp;
1920 cp.handle = ev->handle;
1921 cp.encrypt = 0x01;
1922 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1923 &cp);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001924 } else {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001925 conn->state = BT_CONNECTED;
1926 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001927 hci_conn_put(conn);
1928 }
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001929 } else {
1930 hci_auth_cfm(conn, ev->status);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001931
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001932 hci_conn_hold(conn);
1933 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1934 hci_conn_put(conn);
1935 }
1936
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001937 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001938 if (!ev->status) {
1939 struct hci_cp_set_conn_encrypt cp;
1940 cp.handle = ev->handle;
1941 cp.encrypt = 0x01;
1942 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1943 &cp);
1944 } else {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001945 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001946 hci_encrypt_cfm(conn, ev->status, 0x00);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001947 }
1948 }
1949
Waldemar Rymarkiewiczd7556e22011-05-31 15:49:26 +02001950unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001951 hci_dev_unlock(hdev);
1952}
1953
1954static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1955{
Johan Hedberg127178d2010-11-18 22:22:29 +02001956 struct hci_ev_remote_name *ev = (void *) skb->data;
1957 struct hci_conn *conn;
1958
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001959 BT_DBG("%s", hdev->name);
1960
1961 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001962
1963 hci_dev_lock(hdev);
1964
1965 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedbergb644ba32012-01-17 21:48:47 +02001966
1967 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1968 goto check_auth;
1969
1970 if (ev->status == 0)
1971 hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1972 strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1973 else
1974 hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1975
1976check_auth:
Johan Hedberg79c6c702011-04-28 11:28:55 -07001977 if (!conn)
1978 goto unlock;
1979
1980 if (!hci_outgoing_auth_needed(hdev, conn))
1981 goto unlock;
1982
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001983 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg127178d2010-11-18 22:22:29 +02001984 struct hci_cp_auth_requested cp;
1985 cp.handle = __cpu_to_le16(conn->handle);
1986 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1987 }
1988
Johan Hedberg79c6c702011-04-28 11:28:55 -07001989unlock:
Johan Hedberg127178d2010-11-18 22:22:29 +02001990 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001991}
1992
1993static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1994{
1995 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1996 struct hci_conn *conn;
1997
1998 BT_DBG("%s status %d", hdev->name, ev->status);
1999
2000 hci_dev_lock(hdev);
2001
2002 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2003 if (conn) {
2004 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02002005 if (ev->encrypt) {
2006 /* Encryption implies authentication */
2007 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002008 conn->link_mode |= HCI_LM_ENCRYPT;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03002009 conn->sec_level = conn->pending_sec_level;
Marcel Holtmannae293192008-07-14 20:13:45 +02002010 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002011 conn->link_mode &= ~HCI_LM_ENCRYPT;
2012 }
2013
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002014 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002015
Marcel Holtmannf8558552008-07-14 20:13:49 +02002016 if (conn->state == BT_CONFIG) {
2017 if (!ev->status)
2018 conn->state = BT_CONNECTED;
2019
2020 hci_proto_connect_cfm(conn, ev->status);
2021 hci_conn_put(conn);
2022 } else
2023 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002024 }
2025
2026 hci_dev_unlock(hdev);
2027}
2028
2029static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2030{
2031 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2032 struct hci_conn *conn;
2033
2034 BT_DBG("%s status %d", hdev->name, ev->status);
2035
2036 hci_dev_lock(hdev);
2037
2038 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2039 if (conn) {
2040 if (!ev->status)
2041 conn->link_mode |= HCI_LM_SECURE;
2042
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002043 clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002044
2045 hci_key_change_cfm(conn, ev->status);
2046 }
2047
2048 hci_dev_unlock(hdev);
2049}
2050
2051static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2052{
2053 struct hci_ev_remote_features *ev = (void *) skb->data;
2054 struct hci_conn *conn;
2055
2056 BT_DBG("%s status %d", hdev->name, ev->status);
2057
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002058 hci_dev_lock(hdev);
2059
2060 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002061 if (!conn)
2062 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02002063
Johan Hedbergccd556f2010-11-10 17:11:51 +02002064 if (!ev->status)
2065 memcpy(conn->features, ev->features, 8);
2066
2067 if (conn->state != BT_CONFIG)
2068 goto unlock;
2069
2070 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2071 struct hci_cp_read_remote_ext_features cp;
2072 cp.handle = ev->handle;
2073 cp.page = 0x01;
2074 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02002075 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02002076 goto unlock;
2077 }
2078
Johan Hedberg127178d2010-11-18 22:22:29 +02002079 if (!ev->status) {
2080 struct hci_cp_remote_name_req cp;
2081 memset(&cp, 0, sizeof(cp));
2082 bacpy(&cp.bdaddr, &conn->dst);
2083 cp.pscan_rep_mode = 0x02;
2084 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002085 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2086 mgmt_device_connected(hdev, &conn->dst, conn->type,
2087 conn->dst_type, NULL, 0,
2088 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002089
Johan Hedberg127178d2010-11-18 22:22:29 +02002090 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002091 conn->state = BT_CONNECTED;
2092 hci_proto_connect_cfm(conn, ev->status);
2093 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02002094 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002095
Johan Hedbergccd556f2010-11-10 17:11:51 +02002096unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002097 hci_dev_unlock(hdev);
2098}
2099
2100static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2101{
2102 BT_DBG("%s", hdev->name);
2103}
2104
2105static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2106{
2107 BT_DBG("%s", hdev->name);
2108}
2109
2110static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2111{
2112 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2113 __u16 opcode;
2114
2115 skb_pull(skb, sizeof(*ev));
2116
2117 opcode = __le16_to_cpu(ev->opcode);
2118
2119 switch (opcode) {
2120 case HCI_OP_INQUIRY_CANCEL:
2121 hci_cc_inquiry_cancel(hdev, skb);
2122 break;
2123
2124 case HCI_OP_EXIT_PERIODIC_INQ:
2125 hci_cc_exit_periodic_inq(hdev, skb);
2126 break;
2127
2128 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2129 hci_cc_remote_name_req_cancel(hdev, skb);
2130 break;
2131
2132 case HCI_OP_ROLE_DISCOVERY:
2133 hci_cc_role_discovery(hdev, skb);
2134 break;
2135
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002136 case HCI_OP_READ_LINK_POLICY:
2137 hci_cc_read_link_policy(hdev, skb);
2138 break;
2139
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002140 case HCI_OP_WRITE_LINK_POLICY:
2141 hci_cc_write_link_policy(hdev, skb);
2142 break;
2143
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02002144 case HCI_OP_READ_DEF_LINK_POLICY:
2145 hci_cc_read_def_link_policy(hdev, skb);
2146 break;
2147
2148 case HCI_OP_WRITE_DEF_LINK_POLICY:
2149 hci_cc_write_def_link_policy(hdev, skb);
2150 break;
2151
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002152 case HCI_OP_RESET:
2153 hci_cc_reset(hdev, skb);
2154 break;
2155
2156 case HCI_OP_WRITE_LOCAL_NAME:
2157 hci_cc_write_local_name(hdev, skb);
2158 break;
2159
2160 case HCI_OP_READ_LOCAL_NAME:
2161 hci_cc_read_local_name(hdev, skb);
2162 break;
2163
2164 case HCI_OP_WRITE_AUTH_ENABLE:
2165 hci_cc_write_auth_enable(hdev, skb);
2166 break;
2167
2168 case HCI_OP_WRITE_ENCRYPT_MODE:
2169 hci_cc_write_encrypt_mode(hdev, skb);
2170 break;
2171
2172 case HCI_OP_WRITE_SCAN_ENABLE:
2173 hci_cc_write_scan_enable(hdev, skb);
2174 break;
2175
2176 case HCI_OP_READ_CLASS_OF_DEV:
2177 hci_cc_read_class_of_dev(hdev, skb);
2178 break;
2179
2180 case HCI_OP_WRITE_CLASS_OF_DEV:
2181 hci_cc_write_class_of_dev(hdev, skb);
2182 break;
2183
2184 case HCI_OP_READ_VOICE_SETTING:
2185 hci_cc_read_voice_setting(hdev, skb);
2186 break;
2187
2188 case HCI_OP_WRITE_VOICE_SETTING:
2189 hci_cc_write_voice_setting(hdev, skb);
2190 break;
2191
2192 case HCI_OP_HOST_BUFFER_SIZE:
2193 hci_cc_host_buffer_size(hdev, skb);
2194 break;
2195
Marcel Holtmann333140b2008-07-14 20:13:48 +02002196 case HCI_OP_WRITE_SSP_MODE:
2197 hci_cc_write_ssp_mode(hdev, skb);
2198 break;
2199
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002200 case HCI_OP_READ_LOCAL_VERSION:
2201 hci_cc_read_local_version(hdev, skb);
2202 break;
2203
2204 case HCI_OP_READ_LOCAL_COMMANDS:
2205 hci_cc_read_local_commands(hdev, skb);
2206 break;
2207
2208 case HCI_OP_READ_LOCAL_FEATURES:
2209 hci_cc_read_local_features(hdev, skb);
2210 break;
2211
Andre Guedes971e3a42011-06-30 19:20:52 -03002212 case HCI_OP_READ_LOCAL_EXT_FEATURES:
2213 hci_cc_read_local_ext_features(hdev, skb);
2214 break;
2215
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002216 case HCI_OP_READ_BUFFER_SIZE:
2217 hci_cc_read_buffer_size(hdev, skb);
2218 break;
2219
2220 case HCI_OP_READ_BD_ADDR:
2221 hci_cc_read_bd_addr(hdev, skb);
2222 break;
2223
Andrei Emeltchenko350ee4c2011-12-07 15:56:51 +02002224 case HCI_OP_READ_DATA_BLOCK_SIZE:
2225 hci_cc_read_data_block_size(hdev, skb);
2226 break;
2227
Johan Hedberg23bb5762010-12-21 23:01:27 +02002228 case HCI_OP_WRITE_CA_TIMEOUT:
2229 hci_cc_write_ca_timeout(hdev, skb);
2230 break;
2231
Andrei Emeltchenko1e89cff2011-11-24 14:52:02 +02002232 case HCI_OP_READ_FLOW_CONTROL_MODE:
2233 hci_cc_read_flow_control_mode(hdev, skb);
2234 break;
2235
Andrei Emeltchenko928abaa2011-10-12 10:53:57 +03002236 case HCI_OP_READ_LOCAL_AMP_INFO:
2237 hci_cc_read_local_amp_info(hdev, skb);
2238 break;
2239
Johan Hedbergb0916ea2011-01-10 13:44:55 +02002240 case HCI_OP_DELETE_STORED_LINK_KEY:
2241 hci_cc_delete_stored_link_key(hdev, skb);
2242 break;
2243
Johan Hedbergd5859e22011-01-25 01:19:58 +02002244 case HCI_OP_SET_EVENT_MASK:
2245 hci_cc_set_event_mask(hdev, skb);
2246 break;
2247
2248 case HCI_OP_WRITE_INQUIRY_MODE:
2249 hci_cc_write_inquiry_mode(hdev, skb);
2250 break;
2251
2252 case HCI_OP_READ_INQ_RSP_TX_POWER:
2253 hci_cc_read_inq_rsp_tx_power(hdev, skb);
2254 break;
2255
2256 case HCI_OP_SET_EVENT_FLT:
2257 hci_cc_set_event_flt(hdev, skb);
2258 break;
2259
Johan Hedberg980e1a52011-01-22 06:10:07 +02002260 case HCI_OP_PIN_CODE_REPLY:
2261 hci_cc_pin_code_reply(hdev, skb);
2262 break;
2263
2264 case HCI_OP_PIN_CODE_NEG_REPLY:
2265 hci_cc_pin_code_neg_reply(hdev, skb);
2266 break;
2267
Szymon Jancc35938b2011-03-22 13:12:21 +01002268 case HCI_OP_READ_LOCAL_OOB_DATA:
2269 hci_cc_read_local_oob_data_reply(hdev, skb);
2270 break;
2271
Ville Tervo6ed58ec2011-02-10 22:38:48 -03002272 case HCI_OP_LE_READ_BUFFER_SIZE:
2273 hci_cc_le_read_buffer_size(hdev, skb);
2274 break;
2275
Johan Hedberga5c29682011-02-19 12:05:57 -03002276 case HCI_OP_USER_CONFIRM_REPLY:
2277 hci_cc_user_confirm_reply(hdev, skb);
2278 break;
2279
2280 case HCI_OP_USER_CONFIRM_NEG_REPLY:
2281 hci_cc_user_confirm_neg_reply(hdev, skb);
2282 break;
2283
Brian Gix1143d452011-11-23 08:28:34 -08002284 case HCI_OP_USER_PASSKEY_REPLY:
2285 hci_cc_user_passkey_reply(hdev, skb);
2286 break;
2287
2288 case HCI_OP_USER_PASSKEY_NEG_REPLY:
2289 hci_cc_user_passkey_neg_reply(hdev, skb);
Andre Guedes07f7fa52011-12-02 21:13:31 +09002290
2291 case HCI_OP_LE_SET_SCAN_PARAM:
2292 hci_cc_le_set_scan_param(hdev, skb);
Brian Gix1143d452011-11-23 08:28:34 -08002293 break;
2294
Andre Guedeseb9d91f2011-05-26 16:23:52 -03002295 case HCI_OP_LE_SET_SCAN_ENABLE:
2296 hci_cc_le_set_scan_enable(hdev, skb);
2297 break;
2298
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002299 case HCI_OP_LE_LTK_REPLY:
2300 hci_cc_le_ltk_reply(hdev, skb);
2301 break;
2302
2303 case HCI_OP_LE_LTK_NEG_REPLY:
2304 hci_cc_le_ltk_neg_reply(hdev, skb);
2305 break;
2306
Andre Guedesf9b49302011-06-30 19:20:53 -03002307 case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2308 hci_cc_write_le_host_supported(hdev, skb);
2309 break;
2310
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002311 default:
2312 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2313 break;
2314 }
2315
Ville Tervo6bd32322011-02-16 16:32:41 +02002316 if (ev->opcode != HCI_OP_NOP)
2317 del_timer(&hdev->cmd_timer);
2318
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002319 if (ev->ncmd) {
2320 atomic_set(&hdev->cmd_cnt, 1);
2321 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002322 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002323 }
2324}
2325
2326static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2327{
2328 struct hci_ev_cmd_status *ev = (void *) skb->data;
2329 __u16 opcode;
2330
2331 skb_pull(skb, sizeof(*ev));
2332
2333 opcode = __le16_to_cpu(ev->opcode);
2334
2335 switch (opcode) {
2336 case HCI_OP_INQUIRY:
2337 hci_cs_inquiry(hdev, ev->status);
2338 break;
2339
2340 case HCI_OP_CREATE_CONN:
2341 hci_cs_create_conn(hdev, ev->status);
2342 break;
2343
2344 case HCI_OP_ADD_SCO:
2345 hci_cs_add_sco(hdev, ev->status);
2346 break;
2347
Marcel Holtmannf8558552008-07-14 20:13:49 +02002348 case HCI_OP_AUTH_REQUESTED:
2349 hci_cs_auth_requested(hdev, ev->status);
2350 break;
2351
2352 case HCI_OP_SET_CONN_ENCRYPT:
2353 hci_cs_set_conn_encrypt(hdev, ev->status);
2354 break;
2355
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002356 case HCI_OP_REMOTE_NAME_REQ:
2357 hci_cs_remote_name_req(hdev, ev->status);
2358 break;
2359
Marcel Holtmann769be972008-07-14 20:13:49 +02002360 case HCI_OP_READ_REMOTE_FEATURES:
2361 hci_cs_read_remote_features(hdev, ev->status);
2362 break;
2363
2364 case HCI_OP_READ_REMOTE_EXT_FEATURES:
2365 hci_cs_read_remote_ext_features(hdev, ev->status);
2366 break;
2367
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002368 case HCI_OP_SETUP_SYNC_CONN:
2369 hci_cs_setup_sync_conn(hdev, ev->status);
2370 break;
2371
2372 case HCI_OP_SNIFF_MODE:
2373 hci_cs_sniff_mode(hdev, ev->status);
2374 break;
2375
2376 case HCI_OP_EXIT_SNIFF_MODE:
2377 hci_cs_exit_sniff_mode(hdev, ev->status);
2378 break;
2379
Johan Hedberg8962ee72011-01-20 12:40:27 +02002380 case HCI_OP_DISCONNECT:
Johan Hedberg88c3df12012-02-09 14:27:38 +02002381 hci_cs_disconnect(hdev, ev->status);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002382 break;
2383
Ville Tervofcd89c02011-02-10 22:38:47 -03002384 case HCI_OP_LE_CREATE_CONN:
2385 hci_cs_le_create_conn(hdev, ev->status);
2386 break;
2387
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03002388 case HCI_OP_LE_START_ENC:
2389 hci_cs_le_start_enc(hdev, ev->status);
2390 break;
2391
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002392 default:
2393 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2394 break;
2395 }
2396
Ville Tervo6bd32322011-02-16 16:32:41 +02002397 if (ev->opcode != HCI_OP_NOP)
2398 del_timer(&hdev->cmd_timer);
2399
Gustavo F. Padovan10572132011-03-16 15:36:29 -03002400 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002401 atomic_set(&hdev->cmd_cnt, 1);
2402 if (!skb_queue_empty(&hdev->cmd_q))
Gustavo F. Padovanc347b762011-12-14 23:53:47 -02002403 queue_work(hdev->workqueue, &hdev->cmd_work);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002404 }
2405}
2406
2407static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2408{
2409 struct hci_ev_role_change *ev = (void *) skb->data;
2410 struct hci_conn *conn;
2411
2412 BT_DBG("%s status %d", hdev->name, ev->status);
2413
2414 hci_dev_lock(hdev);
2415
2416 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2417 if (conn) {
2418 if (!ev->status) {
2419 if (ev->role)
2420 conn->link_mode &= ~HCI_LM_MASTER;
2421 else
2422 conn->link_mode |= HCI_LM_MASTER;
2423 }
2424
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002425 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002426
2427 hci_role_switch_cfm(conn, ev->status, ev->role);
2428 }
2429
2430 hci_dev_unlock(hdev);
2431}
2432
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
2434{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002435 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 int i;
2437
Andrei Emeltchenko32ac5b92011-12-19 16:31:29 +02002438 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
2439 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2440 return;
2441 }
2442
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002443 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2444 ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 BT_DBG("%s bad parameters", hdev->name);
2446 return;
2447 }
2448
Andrei Emeltchenkoc5993de2011-12-30 12:07:47 +02002449 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2450
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002451 for (i = 0; i < ev->num_hndl; i++) {
2452 struct hci_comp_pkts_info *info = &ev->handles[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 struct hci_conn *conn;
2454 __u16 handle, count;
2455
Andrei Emeltchenko613a1c02011-12-19 16:31:30 +02002456 handle = __le16_to_cpu(info->handle);
2457 count = __le16_to_cpu(info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458
2459 conn = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002460 if (!conn)
2461 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002463 conn->sent -= count;
2464
2465 switch (conn->type) {
2466 case ACL_LINK:
2467 hdev->acl_cnt += count;
2468 if (hdev->acl_cnt > hdev->acl_pkts)
2469 hdev->acl_cnt = hdev->acl_pkts;
2470 break;
2471
2472 case LE_LINK:
2473 if (hdev->le_pkts) {
2474 hdev->le_cnt += count;
2475 if (hdev->le_cnt > hdev->le_pkts)
2476 hdev->le_cnt = hdev->le_pkts;
2477 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02002478 hdev->acl_cnt += count;
2479 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 hdev->acl_cnt = hdev->acl_pkts;
2481 }
Andrei Emeltchenkof4280912011-12-07 15:56:52 +02002482 break;
2483
2484 case SCO_LINK:
2485 hdev->sco_cnt += count;
2486 if (hdev->sco_cnt > hdev->sco_pkts)
2487 hdev->sco_cnt = hdev->sco_pkts;
2488 break;
2489
2490 default:
2491 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2492 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 }
2494 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002495
Gustavo F. Padovan3eff45e2011-12-15 00:50:02 -02002496 queue_work(hdev->workqueue, &hdev->tx_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497}
2498
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02002499static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
2500 struct sk_buff *skb)
2501{
2502 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2503 int i;
2504
2505 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2506 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2507 return;
2508 }
2509
2510 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2511 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
2512 BT_DBG("%s bad parameters", hdev->name);
2513 return;
2514 }
2515
2516 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
2517 ev->num_hndl);
2518
2519 for (i = 0; i < ev->num_hndl; i++) {
2520 struct hci_comp_blocks_info *info = &ev->handles[i];
2521 struct hci_conn *conn;
2522 __u16 handle, block_count;
2523
2524 handle = __le16_to_cpu(info->handle);
2525 block_count = __le16_to_cpu(info->blocks);
2526
2527 conn = hci_conn_hash_lookup_handle(hdev, handle);
2528 if (!conn)
2529 continue;
2530
2531 conn->sent -= block_count;
2532
2533 switch (conn->type) {
2534 case ACL_LINK:
2535 hdev->block_cnt += block_count;
2536 if (hdev->block_cnt > hdev->num_blocks)
2537 hdev->block_cnt = hdev->num_blocks;
2538 break;
2539
2540 default:
2541 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2542 break;
2543 }
2544 }
2545
2546 queue_work(hdev->workqueue, &hdev->tx_work);
2547}
2548
Marcel Holtmann04837f62006-07-03 10:02:33 +02002549static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002551 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002552 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
2554 BT_DBG("%s status %d", hdev->name, ev->status);
2555
2556 hci_dev_lock(hdev);
2557
Marcel Holtmann04837f62006-07-03 10:02:33 +02002558 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2559 if (conn) {
2560 conn->mode = ev->mode;
2561 conn->interval = __le16_to_cpu(ev->interval);
2562
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002563 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +02002564 if (conn->mode == HCI_CM_ACTIVE)
Johan Hedberg58a681e2012-01-16 06:47:28 +02002565 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002566 else
Johan Hedberg58a681e2012-01-16 06:47:28 +02002567 clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002568 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002569
Johan Hedberg51a8efd2012-01-16 06:10:31 +02002570 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
Marcel Holtmanne73439d2010-07-26 10:06:00 -04002571 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002572 }
2573
2574 hci_dev_unlock(hdev);
2575}
2576
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2578{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002579 struct hci_ev_pin_code_req *ev = (void *) skb->data;
2580 struct hci_conn *conn;
2581
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002582 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002583
2584 hci_dev_lock(hdev);
2585
2586 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002587 if (!conn)
2588 goto unlock;
2589
2590 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002591 hci_conn_hold(conn);
2592 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2593 hci_conn_put(conn);
2594 }
2595
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002596 if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02002597 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
2598 sizeof(ev->bdaddr), &ev->bdaddr);
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002599 else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002600 u8 secure;
2601
2602 if (conn->pending_sec_level == BT_SECURITY_HIGH)
2603 secure = 1;
2604 else
2605 secure = 0;
2606
Johan Hedberg744cf192011-11-08 20:40:14 +02002607 mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02002608 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002609
Waldemar Rymarkiewiczb6f98042011-09-23 10:01:30 +02002610unlock:
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002611 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612}
2613
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2615{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002616 struct hci_ev_link_key_req *ev = (void *) skb->data;
2617 struct hci_cp_link_key_reply cp;
2618 struct hci_conn *conn;
2619 struct link_key *key;
2620
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002621 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002622
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002623 if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002624 return;
2625
2626 hci_dev_lock(hdev);
2627
2628 key = hci_find_link_key(hdev, &ev->bdaddr);
2629 if (!key) {
2630 BT_DBG("%s link key not found for %s", hdev->name,
2631 batostr(&ev->bdaddr));
2632 goto not_found;
2633 }
2634
2635 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2636 batostr(&ev->bdaddr));
2637
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002638 if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
Waldemar Rymarkiewiczb6020ba2011-04-28 12:07:53 +02002639 key->type == HCI_LK_DEBUG_COMBINATION) {
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002640 BT_DBG("%s ignoring debug key", hdev->name);
2641 goto not_found;
2642 }
2643
2644 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002645 if (conn) {
2646 if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2647 conn->auth_type != 0xff &&
2648 (conn->auth_type & 0x01)) {
2649 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2650 goto not_found;
2651 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002652
Waldemar Rymarkiewicz60b83f52011-04-28 12:07:56 +02002653 if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
2654 conn->pending_sec_level == BT_SECURITY_HIGH) {
2655 BT_DBG("%s ignoring key unauthenticated for high \
2656 security", hdev->name);
2657 goto not_found;
2658 }
2659
2660 conn->key_type = key->type;
2661 conn->pin_length = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002662 }
2663
2664 bacpy(&cp.bdaddr, &ev->bdaddr);
2665 memcpy(cp.link_key, key->val, 16);
2666
2667 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2668
2669 hci_dev_unlock(hdev);
2670
2671 return;
2672
2673not_found:
2674 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2675 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676}
2677
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2679{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002680 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2681 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002683
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002684 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002685
2686 hci_dev_lock(hdev);
2687
2688 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2689 if (conn) {
2690 hci_conn_hold(conn);
2691 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002692 pin_len = conn->pin_length;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +02002693
2694 if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
2695 conn->key_type = ev->key_type;
2696
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002697 hci_conn_put(conn);
2698 }
2699
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002700 if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
Johan Hedbergd25e28a2011-04-28 11:28:59 -07002701 hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702 ev->key_type, pin_len);
2703
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002704 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705}
2706
Marcel Holtmann04837f62006-07-03 10:02:33 +02002707static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2708{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002709 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002710 struct hci_conn *conn;
2711
2712 BT_DBG("%s status %d", hdev->name, ev->status);
2713
2714 hci_dev_lock(hdev);
2715
2716 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 if (conn && !ev->status) {
2718 struct inquiry_entry *ie;
2719
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002720 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2721 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 ie->data.clock_offset = ev->clock_offset;
2723 ie->timestamp = jiffies;
2724 }
2725 }
2726
2727 hci_dev_unlock(hdev);
2728}
2729
Marcel Holtmanna8746412008-07-14 20:13:46 +02002730static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2731{
2732 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2733 struct hci_conn *conn;
2734
2735 BT_DBG("%s status %d", hdev->name, ev->status);
2736
2737 hci_dev_lock(hdev);
2738
2739 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2740 if (conn && !ev->status)
2741 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2742
2743 hci_dev_unlock(hdev);
2744}
2745
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002746static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2747{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002748 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002749 struct inquiry_entry *ie;
2750
2751 BT_DBG("%s", hdev->name);
2752
2753 hci_dev_lock(hdev);
2754
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002755 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2756 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002757 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2758 ie->timestamp = jiffies;
2759 }
2760
2761 hci_dev_unlock(hdev);
2762}
2763
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002764static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2765{
2766 struct inquiry_data data;
2767 int num_rsp = *((__u8 *) skb->data);
Johan Hedberg31754052012-01-04 13:39:52 +02002768 bool name_known;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002769
2770 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2771
2772 if (!num_rsp)
2773 return;
2774
2775 hci_dev_lock(hdev);
2776
2777 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002778 struct inquiry_info_with_rssi_and_pscan_mode *info;
2779 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002780
Johan Hedberge17acd42011-03-30 23:57:16 +03002781 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002782 bacpy(&data.bdaddr, &info->bdaddr);
2783 data.pscan_rep_mode = info->pscan_rep_mode;
2784 data.pscan_period_mode = info->pscan_period_mode;
2785 data.pscan_mode = info->pscan_mode;
2786 memcpy(data.dev_class, info->dev_class, 3);
2787 data.clock_offset = info->clock_offset;
2788 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002789 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002790
2791 name_known = hci_inquiry_cache_update(hdev, &data,
2792 false);
Johan Hedberg48264f02011-11-09 13:58:58 +02002793 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002794 info->dev_class, info->rssi,
Andre Guedes7d262f82012-01-10 18:20:49 -03002795 !name_known, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002796 }
2797 } else {
2798 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2799
Johan Hedberge17acd42011-03-30 23:57:16 +03002800 for (; num_rsp; num_rsp--, info++) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002801 bacpy(&data.bdaddr, &info->bdaddr);
2802 data.pscan_rep_mode = info->pscan_rep_mode;
2803 data.pscan_period_mode = info->pscan_period_mode;
2804 data.pscan_mode = 0x00;
2805 memcpy(data.dev_class, info->dev_class, 3);
2806 data.clock_offset = info->clock_offset;
2807 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002808 data.ssp_mode = 0x00;
Johan Hedberg31754052012-01-04 13:39:52 +02002809 name_known = hci_inquiry_cache_update(hdev, &data,
2810 false);
Johan Hedberg48264f02011-11-09 13:58:58 +02002811 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberge17acd42011-03-30 23:57:16 +03002812 info->dev_class, info->rssi,
Andre Guedes7d262f82012-01-10 18:20:49 -03002813 !name_known, NULL, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002814 }
2815 }
2816
2817 hci_dev_unlock(hdev);
2818}
2819
2820static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2821{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002822 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2823 struct hci_conn *conn;
2824
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002825 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002826
Marcel Holtmann41a96212008-07-14 20:13:48 +02002827 hci_dev_lock(hdev);
2828
2829 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002830 if (!conn)
2831 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002832
Johan Hedbergccd556f2010-11-10 17:11:51 +02002833 if (!ev->status && ev->page == 0x01) {
2834 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002835
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002836 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2837 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002838 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002839
Johan Hedberg58a681e2012-01-16 06:47:28 +02002840 if (ev->features[0] & 0x01)
2841 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002842 }
2843
Johan Hedbergccd556f2010-11-10 17:11:51 +02002844 if (conn->state != BT_CONFIG)
2845 goto unlock;
2846
Johan Hedberg127178d2010-11-18 22:22:29 +02002847 if (!ev->status) {
2848 struct hci_cp_remote_name_req cp;
2849 memset(&cp, 0, sizeof(cp));
2850 bacpy(&cp.bdaddr, &conn->dst);
2851 cp.pscan_rep_mode = 0x02;
2852 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
Johan Hedbergb644ba32012-01-17 21:48:47 +02002853 } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2854 mgmt_device_connected(hdev, &conn->dst, conn->type,
2855 conn->dst_type, NULL, 0,
2856 conn->dev_class);
Johan Hedberg392599b2010-11-18 22:22:28 +02002857
Johan Hedberg127178d2010-11-18 22:22:29 +02002858 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002859 conn->state = BT_CONNECTED;
2860 hci_proto_connect_cfm(conn, ev->status);
2861 hci_conn_put(conn);
2862 }
2863
2864unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002865 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002866}
2867
2868static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2869{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002870 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2871 struct hci_conn *conn;
2872
2873 BT_DBG("%s status %d", hdev->name, ev->status);
2874
2875 hci_dev_lock(hdev);
2876
2877 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002878 if (!conn) {
2879 if (ev->link_type == ESCO_LINK)
2880 goto unlock;
2881
2882 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2883 if (!conn)
2884 goto unlock;
2885
2886 conn->type = SCO_LINK;
2887 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002888
Marcel Holtmann732547f2009-04-19 19:14:14 +02002889 switch (ev->status) {
2890 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002891 conn->handle = __le16_to_cpu(ev->handle);
2892 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002893
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002894 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002895 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002896 break;
2897
Stephen Coe705e5712010-02-16 11:29:44 -05002898 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002899 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002900 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002901 case 0x1f: /* Unspecified error */
2902 if (conn->out && conn->attempt < 2) {
2903 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2904 (hdev->esco_type & EDR_ESCO_MASK);
2905 hci_setup_sync(conn, conn->link->handle);
2906 goto unlock;
2907 }
2908 /* fall through */
2909
2910 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002911 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002912 break;
2913 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002914
2915 hci_proto_connect_cfm(conn, ev->status);
2916 if (ev->status)
2917 hci_conn_del(conn);
2918
2919unlock:
2920 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002921}
2922
2923static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2924{
2925 BT_DBG("%s", hdev->name);
2926}
2927
Marcel Holtmann04837f62006-07-03 10:02:33 +02002928static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2929{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002930 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002931
2932 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002933}
2934
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002935static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2936{
2937 struct inquiry_data data;
2938 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2939 int num_rsp = *((__u8 *) skb->data);
2940
2941 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2942
2943 if (!num_rsp)
2944 return;
2945
2946 hci_dev_lock(hdev);
2947
Johan Hedberge17acd42011-03-30 23:57:16 +03002948 for (; num_rsp; num_rsp--, info++) {
Johan Hedberg561aafb2012-01-04 13:31:59 +02002949 bool name_known;
2950
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002951 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002952 data.pscan_rep_mode = info->pscan_rep_mode;
2953 data.pscan_period_mode = info->pscan_period_mode;
2954 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002955 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002956 data.clock_offset = info->clock_offset;
2957 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002958 data.ssp_mode = 0x01;
Johan Hedberg561aafb2012-01-04 13:31:59 +02002959
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002960 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg4ddb1932012-01-15 20:04:43 +02002961 name_known = eir_has_data_type(info->data,
2962 sizeof(info->data),
2963 EIR_NAME_COMPLETE);
Johan Hedberg561aafb2012-01-04 13:31:59 +02002964 else
2965 name_known = true;
2966
Johan Hedberg31754052012-01-04 13:39:52 +02002967 name_known = hci_inquiry_cache_update(hdev, &data, name_known);
Johan Hedberg48264f02011-11-09 13:58:58 +02002968 mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
Johan Hedberg561aafb2012-01-04 13:31:59 +02002969 info->dev_class, info->rssi,
Andre Guedes7d262f82012-01-10 18:20:49 -03002970 !name_known, info->data,
2971 sizeof(info->data));
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002972 }
2973
2974 hci_dev_unlock(hdev);
2975}
2976
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002977static inline u8 hci_get_auth_req(struct hci_conn *conn)
2978{
2979 /* If remote requests dedicated bonding follow that lead */
2980 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2981 /* If both remote and local IO capabilities allow MITM
2982 * protection then require it, otherwise don't */
2983 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2984 return 0x02;
2985 else
2986 return 0x03;
2987 }
2988
2989 /* If remote requests no-bonding follow that lead */
2990 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
Waldemar Rymarkiewicz58797bf2011-04-28 12:07:58 +02002991 return conn->remote_auth | (conn->auth_type & 0x01);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002992
2993 return conn->auth_type;
2994}
2995
Marcel Holtmann04936842008-07-14 20:13:48 +02002996static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2997{
2998 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2999 struct hci_conn *conn;
3000
3001 BT_DBG("%s", hdev->name);
3002
3003 hci_dev_lock(hdev);
3004
3005 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003006 if (!conn)
3007 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003008
Johan Hedberg03b555e2011-01-04 15:40:05 +02003009 hci_conn_hold(conn);
3010
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003011 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg03b555e2011-01-04 15:40:05 +02003012 goto unlock;
3013
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003014 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
Johan Hedberg03b555e2011-01-04 15:40:05 +02003015 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003016 struct hci_cp_io_capability_reply cp;
3017
3018 bacpy(&cp.bdaddr, &ev->bdaddr);
Hemant Gupta7a7f1e72012-01-16 13:34:29 +05303019 /* Change the IO capability from KeyboardDisplay
3020 * to DisplayYesNo as it is not supported by BT spec. */
3021 cp.capability = (conn->io_capability == 0x04) ?
3022 0x01 : conn->io_capability;
Johan Hedberg7cbc9bd2011-04-28 11:29:04 -07003023 conn->auth_type = hci_get_auth_req(conn);
3024 cp.authentication = conn->auth_type;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003025
Johan Hedberg58a681e2012-01-16 06:47:28 +02003026 if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
Szymon Jancce85ee12011-03-22 13:12:23 +01003027 hci_find_remote_oob_data(hdev, &conn->dst))
3028 cp.oob_data = 0x01;
3029 else
3030 cp.oob_data = 0x00;
3031
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003032 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
3033 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003034 } else {
3035 struct hci_cp_io_capability_neg_reply cp;
3036
3037 bacpy(&cp.bdaddr, &ev->bdaddr);
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003038 cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003039
3040 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
3041 sizeof(cp), &cp);
3042 }
3043
3044unlock:
3045 hci_dev_unlock(hdev);
3046}
3047
3048static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
3049{
3050 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
3051 struct hci_conn *conn;
3052
3053 BT_DBG("%s", hdev->name);
3054
3055 hci_dev_lock(hdev);
3056
3057 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3058 if (!conn)
3059 goto unlock;
3060
Johan Hedberg03b555e2011-01-04 15:40:05 +02003061 conn->remote_cap = ev->capability;
Johan Hedberg03b555e2011-01-04 15:40:05 +02003062 conn->remote_auth = ev->authentication;
Johan Hedberg58a681e2012-01-16 06:47:28 +02003063 if (ev->oob_data)
3064 set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
Johan Hedberg03b555e2011-01-04 15:40:05 +02003065
3066unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003067 hci_dev_unlock(hdev);
3068}
3069
Johan Hedberga5c29682011-02-19 12:05:57 -03003070static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3071 struct sk_buff *skb)
3072{
3073 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003074 int loc_mitm, rem_mitm, confirm_hint = 0;
Johan Hedberg7a828902011-04-28 11:28:53 -07003075 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003076
3077 BT_DBG("%s", hdev->name);
3078
3079 hci_dev_lock(hdev);
3080
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003081 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg7a828902011-04-28 11:28:53 -07003082 goto unlock;
Johan Hedberga5c29682011-02-19 12:05:57 -03003083
Johan Hedberg7a828902011-04-28 11:28:53 -07003084 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3085 if (!conn)
3086 goto unlock;
3087
3088 loc_mitm = (conn->auth_type & 0x01);
3089 rem_mitm = (conn->remote_auth & 0x01);
3090
3091 /* If we require MITM but the remote device can't provide that
3092 * (it has NoInputNoOutput) then reject the confirmation
3093 * request. The only exception is when we're dedicated bonding
3094 * initiators (connect_cfm_cb set) since then we always have the MITM
3095 * bit set. */
3096 if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
3097 BT_DBG("Rejecting request: remote device can't provide MITM");
3098 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
3099 sizeof(ev->bdaddr), &ev->bdaddr);
3100 goto unlock;
3101 }
3102
3103 /* If no side requires MITM protection; auto-accept */
3104 if ((!loc_mitm || conn->remote_cap == 0x03) &&
3105 (!rem_mitm || conn->io_capability == 0x03)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003106
3107 /* If we're not the initiators request authorization to
3108 * proceed from user space (mgmt_user_confirm with
3109 * confirm_hint set to 1). */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003110 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003111 BT_DBG("Confirming auto-accept as acceptor");
3112 confirm_hint = 1;
3113 goto confirm;
3114 }
3115
Johan Hedberg9f616562011-04-28 11:28:54 -07003116 BT_DBG("Auto-accept of user confirmation with %ums delay",
3117 hdev->auto_accept_delay);
3118
3119 if (hdev->auto_accept_delay > 0) {
3120 int delay = msecs_to_jiffies(hdev->auto_accept_delay);
3121 mod_timer(&conn->auto_accept_timer, jiffies + delay);
3122 goto unlock;
3123 }
3124
Johan Hedberg7a828902011-04-28 11:28:53 -07003125 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
3126 sizeof(ev->bdaddr), &ev->bdaddr);
3127 goto unlock;
3128 }
3129
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003130confirm:
Johan Hedberg272d90d2012-02-09 15:26:12 +02003131 mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
Johan Hedberg55bc1a32011-04-28 11:28:56 -07003132 confirm_hint);
Johan Hedberg7a828902011-04-28 11:28:53 -07003133
3134unlock:
Johan Hedberga5c29682011-02-19 12:05:57 -03003135 hci_dev_unlock(hdev);
3136}
3137
Brian Gix1143d452011-11-23 08:28:34 -08003138static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
3139 struct sk_buff *skb)
3140{
3141 struct hci_ev_user_passkey_req *ev = (void *) skb->data;
3142
3143 BT_DBG("%s", hdev->name);
3144
3145 hci_dev_lock(hdev);
3146
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003147 if (test_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg272d90d2012-02-09 15:26:12 +02003148 mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
Brian Gix1143d452011-11-23 08:28:34 -08003149
3150 hci_dev_unlock(hdev);
3151}
3152
Marcel Holtmann04936842008-07-14 20:13:48 +02003153static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3154{
3155 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
3156 struct hci_conn *conn;
3157
3158 BT_DBG("%s", hdev->name);
3159
3160 hci_dev_lock(hdev);
3161
3162 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03003163 if (!conn)
3164 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02003165
Johan Hedberg2a611692011-02-19 12:06:00 -03003166 /* To avoid duplicate auth_failed events to user space we check
3167 * the HCI_CONN_AUTH_PEND flag which will be set if we
3168 * initiated the authentication. A traditional auth_complete
3169 * event gets always produced as initiator and is also mapped to
3170 * the mgmt_auth_failed event */
Johan Hedberg51a8efd2012-01-16 06:10:31 +02003171 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
Johan Hedbergbab73cb2012-02-09 16:07:29 +02003172 mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3173 ev->status);
Johan Hedberg2a611692011-02-19 12:06:00 -03003174
3175 hci_conn_put(conn);
3176
3177unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02003178 hci_dev_unlock(hdev);
3179}
3180
Marcel Holtmann41a96212008-07-14 20:13:48 +02003181static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
3182{
3183 struct hci_ev_remote_host_features *ev = (void *) skb->data;
3184 struct inquiry_entry *ie;
3185
3186 BT_DBG("%s", hdev->name);
3187
3188 hci_dev_lock(hdev);
3189
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02003190 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3191 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02003192 ie->data.ssp_mode = (ev->features[0] & 0x01);
3193
3194 hci_dev_unlock(hdev);
3195}
3196
Szymon Janc2763eda2011-03-22 13:12:22 +01003197static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
3198 struct sk_buff *skb)
3199{
3200 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
3201 struct oob_data *data;
3202
3203 BT_DBG("%s", hdev->name);
3204
3205 hci_dev_lock(hdev);
3206
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02003207 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
Szymon Jance1ba1f12011-04-06 13:01:59 +02003208 goto unlock;
3209
Szymon Janc2763eda2011-03-22 13:12:22 +01003210 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
3211 if (data) {
3212 struct hci_cp_remote_oob_data_reply cp;
3213
3214 bacpy(&cp.bdaddr, &ev->bdaddr);
3215 memcpy(cp.hash, data->hash, sizeof(cp.hash));
3216 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
3217
3218 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
3219 &cp);
3220 } else {
3221 struct hci_cp_remote_oob_data_neg_reply cp;
3222
3223 bacpy(&cp.bdaddr, &ev->bdaddr);
3224 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
3225 &cp);
3226 }
3227
Szymon Jance1ba1f12011-04-06 13:01:59 +02003228unlock:
Szymon Janc2763eda2011-03-22 13:12:22 +01003229 hci_dev_unlock(hdev);
3230}
3231
Ville Tervofcd89c02011-02-10 22:38:47 -03003232static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3233{
3234 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3235 struct hci_conn *conn;
3236
3237 BT_DBG("%s status %d", hdev->name, ev->status);
3238
3239 hci_dev_lock(hdev);
3240
3241 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03003242 if (!conn) {
3243 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3244 if (!conn) {
3245 BT_ERR("No memory for new connection");
3246 hci_dev_unlock(hdev);
3247 return;
3248 }
Andre Guedes29b79882011-05-31 14:20:54 -03003249
3250 conn->dst_type = ev->bdaddr_type;
Ville Tervob62f3282011-02-10 22:38:50 -03003251 }
Ville Tervofcd89c02011-02-10 22:38:47 -03003252
3253 if (ev->status) {
Johan Hedberg48264f02011-11-09 13:58:58 +02003254 mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
3255 conn->dst_type, ev->status);
Ville Tervofcd89c02011-02-10 22:38:47 -03003256 hci_proto_connect_cfm(conn, ev->status);
3257 conn->state = BT_CLOSED;
3258 hci_conn_del(conn);
3259 goto unlock;
3260 }
3261
Johan Hedbergb644ba32012-01-17 21:48:47 +02003262 if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3263 mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3264 conn->dst_type, NULL, 0, 0);
Vinicius Costa Gomes83bc71b2011-05-06 18:41:43 -03003265
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -03003266 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -03003267 conn->handle = __le16_to_cpu(ev->handle);
3268 conn->state = BT_CONNECTED;
3269
3270 hci_conn_hold_device(conn);
3271 hci_conn_add_sysfs(conn);
3272
3273 hci_proto_connect_cfm(conn, ev->status);
3274
3275unlock:
3276 hci_dev_unlock(hdev);
3277}
3278
Andre Guedes9aa04c92011-05-26 16:23:51 -03003279static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
3280 struct sk_buff *skb)
3281{
Andre Guedese95beb42011-09-26 20:48:35 -03003282 u8 num_reports = skb->data[0];
3283 void *ptr = &skb->data[1];
Andre Guedes3c9e9192012-01-10 18:20:50 -03003284 s8 rssi;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003285
3286 hci_dev_lock(hdev);
3287
Andre Guedese95beb42011-09-26 20:48:35 -03003288 while (num_reports--) {
3289 struct hci_ev_le_advertising_info *ev = ptr;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003290
Andre Guedes9aa04c92011-05-26 16:23:51 -03003291 hci_add_adv_entry(hdev, ev);
Andre Guedese95beb42011-09-26 20:48:35 -03003292
Andre Guedes3c9e9192012-01-10 18:20:50 -03003293 rssi = ev->data[ev->length];
3294 mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
3295 NULL, rssi, 0, ev->data, ev->length);
3296
Andre Guedese95beb42011-09-26 20:48:35 -03003297 ptr += sizeof(*ev) + ev->length + 1;
Andre Guedes9aa04c92011-05-26 16:23:51 -03003298 }
3299
3300 hci_dev_unlock(hdev);
3301}
3302
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003303static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3304 struct sk_buff *skb)
3305{
3306 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3307 struct hci_cp_le_ltk_reply cp;
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003308 struct hci_cp_le_ltk_neg_reply neg;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003309 struct hci_conn *conn;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003310 struct smp_ltk *ltk;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003311
3312 BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3313
3314 hci_dev_lock(hdev);
3315
3316 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003317 if (conn == NULL)
3318 goto not_found;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003319
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003320 ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3321 if (ltk == NULL)
3322 goto not_found;
3323
3324 memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003325 cp.handle = cpu_to_le16(conn->handle);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003326
3327 if (ltk->authenticated)
3328 conn->sec_level = BT_SECURITY_HIGH;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003329
3330 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3331
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03003332 if (ltk->type & HCI_SMP_STK) {
3333 list_del(&ltk->list);
3334 kfree(ltk);
3335 }
3336
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003337 hci_dev_unlock(hdev);
Vinicius Costa Gomesbea710f2011-07-07 18:59:37 -03003338
3339 return;
3340
3341not_found:
3342 neg.handle = ev->handle;
3343 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3344 hci_dev_unlock(hdev);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003345}
3346
Ville Tervofcd89c02011-02-10 22:38:47 -03003347static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3348{
3349 struct hci_ev_le_meta *le_ev = (void *) skb->data;
3350
3351 skb_pull(skb, sizeof(*le_ev));
3352
3353 switch (le_ev->subevent) {
3354 case HCI_EV_LE_CONN_COMPLETE:
3355 hci_le_conn_complete_evt(hdev, skb);
3356 break;
3357
Andre Guedes9aa04c92011-05-26 16:23:51 -03003358 case HCI_EV_LE_ADVERTISING_REPORT:
3359 hci_le_adv_report_evt(hdev, skb);
3360 break;
3361
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -03003362 case HCI_EV_LE_LTK_REQ:
3363 hci_le_ltk_request_evt(hdev, skb);
3364 break;
3365
Ville Tervofcd89c02011-02-10 22:38:47 -03003366 default:
3367 break;
3368 }
3369}
3370
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3372{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003373 struct hci_event_hdr *hdr = (void *) skb->data;
3374 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
3376 skb_pull(skb, HCI_EVENT_HDR_SIZE);
3377
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003378 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 case HCI_EV_INQUIRY_COMPLETE:
3380 hci_inquiry_complete_evt(hdev, skb);
3381 break;
3382
3383 case HCI_EV_INQUIRY_RESULT:
3384 hci_inquiry_result_evt(hdev, skb);
3385 break;
3386
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003387 case HCI_EV_CONN_COMPLETE:
3388 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02003389 break;
3390
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 case HCI_EV_CONN_REQUEST:
3392 hci_conn_request_evt(hdev, skb);
3393 break;
3394
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395 case HCI_EV_DISCONN_COMPLETE:
3396 hci_disconn_complete_evt(hdev, skb);
3397 break;
3398
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 case HCI_EV_AUTH_COMPLETE:
3400 hci_auth_complete_evt(hdev, skb);
3401 break;
3402
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003403 case HCI_EV_REMOTE_NAME:
3404 hci_remote_name_evt(hdev, skb);
3405 break;
3406
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 case HCI_EV_ENCRYPT_CHANGE:
3408 hci_encrypt_change_evt(hdev, skb);
3409 break;
3410
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003411 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3412 hci_change_link_key_complete_evt(hdev, skb);
3413 break;
3414
3415 case HCI_EV_REMOTE_FEATURES:
3416 hci_remote_features_evt(hdev, skb);
3417 break;
3418
3419 case HCI_EV_REMOTE_VERSION:
3420 hci_remote_version_evt(hdev, skb);
3421 break;
3422
3423 case HCI_EV_QOS_SETUP_COMPLETE:
3424 hci_qos_setup_complete_evt(hdev, skb);
3425 break;
3426
3427 case HCI_EV_CMD_COMPLETE:
3428 hci_cmd_complete_evt(hdev, skb);
3429 break;
3430
3431 case HCI_EV_CMD_STATUS:
3432 hci_cmd_status_evt(hdev, skb);
3433 break;
3434
3435 case HCI_EV_ROLE_CHANGE:
3436 hci_role_change_evt(hdev, skb);
3437 break;
3438
3439 case HCI_EV_NUM_COMP_PKTS:
3440 hci_num_comp_pkts_evt(hdev, skb);
3441 break;
3442
3443 case HCI_EV_MODE_CHANGE:
3444 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 break;
3446
3447 case HCI_EV_PIN_CODE_REQ:
3448 hci_pin_code_request_evt(hdev, skb);
3449 break;
3450
3451 case HCI_EV_LINK_KEY_REQ:
3452 hci_link_key_request_evt(hdev, skb);
3453 break;
3454
3455 case HCI_EV_LINK_KEY_NOTIFY:
3456 hci_link_key_notify_evt(hdev, skb);
3457 break;
3458
3459 case HCI_EV_CLOCK_OFFSET:
3460 hci_clock_offset_evt(hdev, skb);
3461 break;
3462
Marcel Holtmanna8746412008-07-14 20:13:46 +02003463 case HCI_EV_PKT_TYPE_CHANGE:
3464 hci_pkt_type_change_evt(hdev, skb);
3465 break;
3466
Marcel Holtmann85a1e932005-08-09 20:28:02 -07003467 case HCI_EV_PSCAN_REP_MODE:
3468 hci_pscan_rep_mode_evt(hdev, skb);
3469 break;
3470
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003471 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3472 hci_inquiry_result_with_rssi_evt(hdev, skb);
3473 break;
3474
3475 case HCI_EV_REMOTE_EXT_FEATURES:
3476 hci_remote_ext_features_evt(hdev, skb);
3477 break;
3478
3479 case HCI_EV_SYNC_CONN_COMPLETE:
3480 hci_sync_conn_complete_evt(hdev, skb);
3481 break;
3482
3483 case HCI_EV_SYNC_CONN_CHANGED:
3484 hci_sync_conn_changed_evt(hdev, skb);
3485 break;
3486
Marcel Holtmann04837f62006-07-03 10:02:33 +02003487 case HCI_EV_SNIFF_SUBRATE:
3488 hci_sniff_subrate_evt(hdev, skb);
3489 break;
3490
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003491 case HCI_EV_EXTENDED_INQUIRY_RESULT:
3492 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493 break;
3494
Marcel Holtmann04936842008-07-14 20:13:48 +02003495 case HCI_EV_IO_CAPA_REQUEST:
3496 hci_io_capa_request_evt(hdev, skb);
3497 break;
3498
Johan Hedberg03b555e2011-01-04 15:40:05 +02003499 case HCI_EV_IO_CAPA_REPLY:
3500 hci_io_capa_reply_evt(hdev, skb);
3501 break;
3502
Johan Hedberga5c29682011-02-19 12:05:57 -03003503 case HCI_EV_USER_CONFIRM_REQUEST:
3504 hci_user_confirm_request_evt(hdev, skb);
3505 break;
3506
Brian Gix1143d452011-11-23 08:28:34 -08003507 case HCI_EV_USER_PASSKEY_REQUEST:
3508 hci_user_passkey_request_evt(hdev, skb);
3509 break;
3510
Marcel Holtmann04936842008-07-14 20:13:48 +02003511 case HCI_EV_SIMPLE_PAIR_COMPLETE:
3512 hci_simple_pair_complete_evt(hdev, skb);
3513 break;
3514
Marcel Holtmann41a96212008-07-14 20:13:48 +02003515 case HCI_EV_REMOTE_HOST_FEATURES:
3516 hci_remote_host_features_evt(hdev, skb);
3517 break;
3518
Ville Tervofcd89c02011-02-10 22:38:47 -03003519 case HCI_EV_LE_META:
3520 hci_le_meta_evt(hdev, skb);
3521 break;
3522
Szymon Janc2763eda2011-03-22 13:12:22 +01003523 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3524 hci_remote_oob_data_request_evt(hdev, skb);
3525 break;
3526
Andrei Emeltchenko25e89e92012-01-04 12:41:58 +02003527 case HCI_EV_NUM_COMP_BLOCKS:
3528 hci_num_comp_blocks_evt(hdev, skb);
3529 break;
3530
Marcel Holtmanna9de9242007-10-20 13:33:56 +02003531 default:
3532 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 break;
3534 }
3535
3536 kfree_skb(skb);
3537 hdev->stat.evt_rx++;
3538}