blob: 0def3e1fe5eff57efd2c77c7dcce78b8442e93bb [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>
38#include <linux/notifier.h>
39#include <net/sock.h>
40
41#include <asm/system.h>
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020042#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <asm/unaligned.h>
44
45#include <net/bluetooth/bluetooth.h>
46#include <net/bluetooth/hci_core.h>
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048/* Handle HCI Event packets */
49
Marcel Holtmanna9de9242007-10-20 13:33:56 +020050static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020052 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Marcel Holtmanna9de9242007-10-20 13:33:56 +020054 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Marcel Holtmanna9de9242007-10-20 13:33:56 +020056 if (status)
57 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Marcel Holtmanna9de9242007-10-20 13:33:56 +020059 clear_bit(HCI_INQUIRY, &hdev->flags);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010060
Johan Hedberg23bb5762010-12-21 23:01:27 +020061 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010062
Marcel Holtmanna9de9242007-10-20 13:33:56 +020063 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064}
65
Marcel Holtmanna9de9242007-10-20 13:33:56 +020066static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020068 __u8 status = *((__u8 *) skb->data);
69
70 BT_DBG("%s status 0x%x", hdev->name, status);
71
72 if (status)
73 return;
74
75 clear_bit(HCI_INQUIRY, &hdev->flags);
76
77 hci_conn_check_pending(hdev);
78}
79
80static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
81{
82 BT_DBG("%s", hdev->name);
83}
84
85static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
86{
87 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Marcel Holtmanna9de9242007-10-20 13:33:56 +020090 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Marcel Holtmanna9de9242007-10-20 13:33:56 +020092 if (rp->status)
93 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Marcel Holtmanna9de9242007-10-20 13:33:56 +020095 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Marcel Holtmanna9de9242007-10-20 13:33:56 +020097 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
98 if (conn) {
99 if (rp->role)
100 conn->link_mode &= ~HCI_LM_MASTER;
101 else
102 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200104
105 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106}
107
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200108static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
109{
110 struct hci_rp_read_link_policy *rp = (void *) skb->data;
111 struct hci_conn *conn;
112
113 BT_DBG("%s status 0x%x", hdev->name, rp->status);
114
115 if (rp->status)
116 return;
117
118 hci_dev_lock(hdev);
119
120 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
121 if (conn)
122 conn->link_policy = __le16_to_cpu(rp->policy);
123
124 hci_dev_unlock(hdev);
125}
126
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200127static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200129 struct hci_rp_write_link_policy *rp = (void *) skb->data;
130 struct hci_conn *conn;
131 void *sent;
132
133 BT_DBG("%s status 0x%x", hdev->name, rp->status);
134
135 if (rp->status)
136 return;
137
138 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
139 if (!sent)
140 return;
141
142 hci_dev_lock(hdev);
143
144 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200145 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700146 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200147
148 hci_dev_unlock(hdev);
149}
150
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200151static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
152{
153 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
154
155 BT_DBG("%s status 0x%x", hdev->name, rp->status);
156
157 if (rp->status)
158 return;
159
160 hdev->link_policy = __le16_to_cpu(rp->policy);
161}
162
163static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
164{
165 __u8 status = *((__u8 *) skb->data);
166 void *sent;
167
168 BT_DBG("%s status 0x%x", hdev->name, status);
169
170 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
171 if (!sent)
172 return;
173
174 if (!status)
175 hdev->link_policy = get_unaligned_le16(sent);
176
Johan Hedberg23bb5762010-12-21 23:01:27 +0200177 hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200178}
179
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200180static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
181{
182 __u8 status = *((__u8 *) skb->data);
183
184 BT_DBG("%s status 0x%x", hdev->name, status);
185
Johan Hedberg23bb5762010-12-21 23:01:27 +0200186 hci_req_complete(hdev, HCI_OP_RESET, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200187}
188
189static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
190{
191 __u8 status = *((__u8 *) skb->data);
192 void *sent;
193
194 BT_DBG("%s status 0x%x", hdev->name, status);
195
196 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
197 if (!sent)
198 return;
199
Johan Hedbergb312b1612011-03-16 14:29:37 +0200200 if (test_bit(HCI_MGMT, &hdev->flags))
201 mgmt_set_local_name_complete(hdev->id, sent, status);
202
203 if (status)
204 return;
205
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200206 memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200207}
208
209static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
210{
211 struct hci_rp_read_local_name *rp = (void *) skb->data;
212
213 BT_DBG("%s status 0x%x", hdev->name, rp->status);
214
215 if (rp->status)
216 return;
217
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200218 memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200219}
220
221static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
222{
223 __u8 status = *((__u8 *) skb->data);
224 void *sent;
225
226 BT_DBG("%s status 0x%x", hdev->name, status);
227
228 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
229 if (!sent)
230 return;
231
232 if (!status) {
233 __u8 param = *((__u8 *) sent);
234
235 if (param == AUTH_ENABLED)
236 set_bit(HCI_AUTH, &hdev->flags);
237 else
238 clear_bit(HCI_AUTH, &hdev->flags);
239 }
240
Johan Hedberg23bb5762010-12-21 23:01:27 +0200241 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200242}
243
244static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
245{
246 __u8 status = *((__u8 *) skb->data);
247 void *sent;
248
249 BT_DBG("%s status 0x%x", hdev->name, status);
250
251 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
252 if (!sent)
253 return;
254
255 if (!status) {
256 __u8 param = *((__u8 *) sent);
257
258 if (param)
259 set_bit(HCI_ENCRYPT, &hdev->flags);
260 else
261 clear_bit(HCI_ENCRYPT, &hdev->flags);
262 }
263
Johan Hedberg23bb5762010-12-21 23:01:27 +0200264 hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200265}
266
267static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
268{
269 __u8 status = *((__u8 *) skb->data);
270 void *sent;
271
272 BT_DBG("%s status 0x%x", hdev->name, status);
273
274 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
275 if (!sent)
276 return;
277
278 if (!status) {
279 __u8 param = *((__u8 *) sent);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200280 int old_pscan, old_iscan;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200281
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200282 old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
283 old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200284
Johan Hedberg73f22f62010-12-29 16:00:25 +0200285 if (param & SCAN_INQUIRY) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200286 set_bit(HCI_ISCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200287 if (!old_iscan)
288 mgmt_discoverable(hdev->id, 1);
289 } else if (old_iscan)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200290 mgmt_discoverable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200291
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200292 if (param & SCAN_PAGE) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200293 set_bit(HCI_PSCAN, &hdev->flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200294 if (!old_pscan)
295 mgmt_connectable(hdev->id, 1);
296 } else if (old_pscan)
297 mgmt_connectable(hdev->id, 0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200298 }
299
Johan Hedberg23bb5762010-12-21 23:01:27 +0200300 hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200301}
302
303static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
304{
305 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
306
307 BT_DBG("%s status 0x%x", hdev->name, rp->status);
308
309 if (rp->status)
310 return;
311
312 memcpy(hdev->dev_class, rp->dev_class, 3);
313
314 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
315 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
316}
317
318static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
319{
320 __u8 status = *((__u8 *) skb->data);
321 void *sent;
322
323 BT_DBG("%s status 0x%x", hdev->name, status);
324
Marcel Holtmannf383f272008-07-14 20:13:47 +0200325 if (status)
326 return;
327
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200328 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
329 if (!sent)
330 return;
331
Marcel Holtmannf383f272008-07-14 20:13:47 +0200332 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200333}
334
335static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
336{
337 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200339
340 BT_DBG("%s status 0x%x", hdev->name, rp->status);
341
342 if (rp->status)
343 return;
344
345 setting = __le16_to_cpu(rp->voice_setting);
346
Marcel Holtmannf383f272008-07-14 20:13:47 +0200347 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200348 return;
349
350 hdev->voice_setting = setting;
351
352 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
353
354 if (hdev->notify) {
355 tasklet_disable(&hdev->tx_task);
356 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
357 tasklet_enable(&hdev->tx_task);
358 }
359}
360
361static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
362{
363 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200364 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 void *sent;
366
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200367 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Marcel Holtmannf383f272008-07-14 20:13:47 +0200369 if (status)
370 return;
371
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200372 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
373 if (!sent)
374 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Marcel Holtmannf383f272008-07-14 20:13:47 +0200376 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Marcel Holtmannf383f272008-07-14 20:13:47 +0200378 if (hdev->voice_setting == setting)
379 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Marcel Holtmannf383f272008-07-14 20:13:47 +0200381 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
Marcel Holtmannf383f272008-07-14 20:13:47 +0200383 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
384
385 if (hdev->notify) {
386 tasklet_disable(&hdev->tx_task);
387 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
388 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 }
390}
391
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200392static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200394 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200396 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Johan Hedberg23bb5762010-12-21 23:01:27 +0200398 hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399}
400
Marcel Holtmann333140b2008-07-14 20:13:48 +0200401static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
402{
403 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
404
405 BT_DBG("%s status 0x%x", hdev->name, rp->status);
406
407 if (rp->status)
408 return;
409
410 hdev->ssp_mode = rp->mode;
411}
412
413static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
414{
415 __u8 status = *((__u8 *) skb->data);
416 void *sent;
417
418 BT_DBG("%s status 0x%x", hdev->name, status);
419
420 if (status)
421 return;
422
423 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
424 if (!sent)
425 return;
426
427 hdev->ssp_mode = *((__u8 *) sent);
428}
429
Johan Hedbergd5859e22011-01-25 01:19:58 +0200430static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
431{
432 if (hdev->features[6] & LMP_EXT_INQ)
433 return 2;
434
435 if (hdev->features[3] & LMP_RSSI_INQ)
436 return 1;
437
438 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
439 hdev->lmp_subver == 0x0757)
440 return 1;
441
442 if (hdev->manufacturer == 15) {
443 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
444 return 1;
445 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
446 return 1;
447 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
448 return 1;
449 }
450
451 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
452 hdev->lmp_subver == 0x1805)
453 return 1;
454
455 return 0;
456}
457
458static void hci_setup_inquiry_mode(struct hci_dev *hdev)
459{
460 u8 mode;
461
462 mode = hci_get_inquiry_mode(hdev);
463
464 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
465}
466
467static void hci_setup_event_mask(struct hci_dev *hdev)
468{
469 /* The second byte is 0xff instead of 0x9f (two reserved bits
470 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
471 * command otherwise */
472 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
473
474 /* Events for 1.2 and newer controllers */
475 if (hdev->lmp_ver > 1) {
476 events[4] |= 0x01; /* Flow Specification Complete */
477 events[4] |= 0x02; /* Inquiry Result with RSSI */
478 events[4] |= 0x04; /* Read Remote Extended Features Complete */
479 events[5] |= 0x08; /* Synchronous Connection Complete */
480 events[5] |= 0x10; /* Synchronous Connection Changed */
481 }
482
483 if (hdev->features[3] & LMP_RSSI_INQ)
484 events[4] |= 0x04; /* Inquiry Result with RSSI */
485
486 if (hdev->features[5] & LMP_SNIFF_SUBR)
487 events[5] |= 0x20; /* Sniff Subrating */
488
489 if (hdev->features[5] & LMP_PAUSE_ENC)
490 events[5] |= 0x80; /* Encryption Key Refresh Complete */
491
492 if (hdev->features[6] & LMP_EXT_INQ)
493 events[5] |= 0x40; /* Extended Inquiry Result */
494
495 if (hdev->features[6] & LMP_NO_FLUSH)
496 events[7] |= 0x01; /* Enhanced Flush Complete */
497
498 if (hdev->features[7] & LMP_LSTO)
499 events[6] |= 0x80; /* Link Supervision Timeout Changed */
500
501 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
502 events[6] |= 0x01; /* IO Capability Request */
503 events[6] |= 0x02; /* IO Capability Response */
504 events[6] |= 0x04; /* User Confirmation Request */
505 events[6] |= 0x08; /* User Passkey Request */
506 events[6] |= 0x10; /* Remote OOB Data Request */
507 events[6] |= 0x20; /* Simple Pairing Complete */
508 events[7] |= 0x04; /* User Passkey Notification */
509 events[7] |= 0x08; /* Keypress Notification */
510 events[7] |= 0x10; /* Remote Host Supported
511 * Features Notification */
512 }
513
514 if (hdev->features[4] & LMP_LE)
515 events[7] |= 0x20; /* LE Meta-Event */
516
517 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
518}
519
520static void hci_setup(struct hci_dev *hdev)
521{
522 hci_setup_event_mask(hdev);
523
524 if (hdev->lmp_ver > 1)
525 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
526
527 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
528 u8 mode = 0x01;
529 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
530 }
531
532 if (hdev->features[3] & LMP_RSSI_INQ)
533 hci_setup_inquiry_mode(hdev);
534
535 if (hdev->features[7] & LMP_INQ_TX_PWR)
536 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
537}
538
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200539static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
540{
541 struct hci_rp_read_local_version *rp = (void *) skb->data;
542
543 BT_DBG("%s status 0x%x", hdev->name, rp->status);
544
545 if (rp->status)
546 return;
547
548 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200549 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200550 hdev->lmp_ver = rp->lmp_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200551 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200552 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200553
554 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
555 hdev->manufacturer,
556 hdev->hci_ver, hdev->hci_rev);
Johan Hedbergd5859e22011-01-25 01:19:58 +0200557
558 if (test_bit(HCI_INIT, &hdev->flags))
559 hci_setup(hdev);
560}
561
562static void hci_setup_link_policy(struct hci_dev *hdev)
563{
564 u16 link_policy = 0;
565
566 if (hdev->features[0] & LMP_RSWITCH)
567 link_policy |= HCI_LP_RSWITCH;
568 if (hdev->features[0] & LMP_HOLD)
569 link_policy |= HCI_LP_HOLD;
570 if (hdev->features[0] & LMP_SNIFF)
571 link_policy |= HCI_LP_SNIFF;
572 if (hdev->features[1] & LMP_PARK)
573 link_policy |= HCI_LP_PARK;
574
575 link_policy = cpu_to_le16(link_policy);
576 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
577 sizeof(link_policy), &link_policy);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200578}
579
580static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
581{
582 struct hci_rp_read_local_commands *rp = (void *) skb->data;
583
584 BT_DBG("%s status 0x%x", hdev->name, rp->status);
585
586 if (rp->status)
Johan Hedbergd5859e22011-01-25 01:19:58 +0200587 goto done;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200588
589 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
Johan Hedbergd5859e22011-01-25 01:19:58 +0200590
591 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
592 hci_setup_link_policy(hdev);
593
594done:
595 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200596}
597
598static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
599{
600 struct hci_rp_read_local_features *rp = (void *) skb->data;
601
602 BT_DBG("%s status 0x%x", hdev->name, rp->status);
603
604 if (rp->status)
605 return;
606
607 memcpy(hdev->features, rp->features, 8);
608
609 /* Adjust default settings according to features
610 * supported by device. */
611
612 if (hdev->features[0] & LMP_3SLOT)
613 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
614
615 if (hdev->features[0] & LMP_5SLOT)
616 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
617
618 if (hdev->features[1] & LMP_HV2) {
619 hdev->pkt_type |= (HCI_HV2);
620 hdev->esco_type |= (ESCO_HV2);
621 }
622
623 if (hdev->features[1] & LMP_HV3) {
624 hdev->pkt_type |= (HCI_HV3);
625 hdev->esco_type |= (ESCO_HV3);
626 }
627
628 if (hdev->features[3] & LMP_ESCO)
629 hdev->esco_type |= (ESCO_EV3);
630
631 if (hdev->features[4] & LMP_EV4)
632 hdev->esco_type |= (ESCO_EV4);
633
634 if (hdev->features[4] & LMP_EV5)
635 hdev->esco_type |= (ESCO_EV5);
636
Marcel Holtmannefc76882009-02-06 09:13:37 +0100637 if (hdev->features[5] & LMP_EDR_ESCO_2M)
638 hdev->esco_type |= (ESCO_2EV3);
639
640 if (hdev->features[5] & LMP_EDR_ESCO_3M)
641 hdev->esco_type |= (ESCO_3EV3);
642
643 if (hdev->features[5] & LMP_EDR_3S_ESCO)
644 hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
645
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200646 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
647 hdev->features[0], hdev->features[1],
648 hdev->features[2], hdev->features[3],
649 hdev->features[4], hdev->features[5],
650 hdev->features[6], hdev->features[7]);
651}
652
653static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
654{
655 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
656
657 BT_DBG("%s status 0x%x", hdev->name, rp->status);
658
659 if (rp->status)
660 return;
661
662 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
663 hdev->sco_mtu = rp->sco_mtu;
664 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
665 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
666
667 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
668 hdev->sco_mtu = 64;
669 hdev->sco_pkts = 8;
670 }
671
672 hdev->acl_cnt = hdev->acl_pkts;
673 hdev->sco_cnt = hdev->sco_pkts;
674
675 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
676 hdev->acl_mtu, hdev->acl_pkts,
677 hdev->sco_mtu, hdev->sco_pkts);
678}
679
680static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
681{
682 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
683
684 BT_DBG("%s status 0x%x", hdev->name, rp->status);
685
686 if (!rp->status)
687 bacpy(&hdev->bdaddr, &rp->bdaddr);
688
Johan Hedberg23bb5762010-12-21 23:01:27 +0200689 hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
690}
691
692static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
693{
694 __u8 status = *((__u8 *) skb->data);
695
696 BT_DBG("%s status 0x%x", hdev->name, status);
697
698 hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200699}
700
Johan Hedbergb0916ea2011-01-10 13:44:55 +0200701static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
702 struct sk_buff *skb)
703{
704 __u8 status = *((__u8 *) skb->data);
705
706 BT_DBG("%s status 0x%x", hdev->name, status);
707
708 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
709}
710
Johan Hedbergd5859e22011-01-25 01:19:58 +0200711static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
712{
713 __u8 status = *((__u8 *) skb->data);
714
715 BT_DBG("%s status 0x%x", hdev->name, status);
716
717 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
718}
719
720static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
721 struct sk_buff *skb)
722{
723 __u8 status = *((__u8 *) skb->data);
724
725 BT_DBG("%s status 0x%x", hdev->name, status);
726
727 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
728}
729
730static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
731 struct sk_buff *skb)
732{
733 __u8 status = *((__u8 *) skb->data);
734
735 BT_DBG("%s status 0x%x", hdev->name, status);
736
737 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
738}
739
740static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
741{
742 __u8 status = *((__u8 *) skb->data);
743
744 BT_DBG("%s status 0x%x", hdev->name, status);
745
746 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
747}
748
Johan Hedberg980e1a52011-01-22 06:10:07 +0200749static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
750{
751 struct hci_rp_pin_code_reply *rp = (void *) skb->data;
752 struct hci_cp_pin_code_reply *cp;
753 struct hci_conn *conn;
754
755 BT_DBG("%s status 0x%x", hdev->name, rp->status);
756
757 if (test_bit(HCI_MGMT, &hdev->flags))
758 mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
759
760 if (rp->status != 0)
761 return;
762
763 cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
764 if (!cp)
765 return;
766
767 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
768 if (conn)
769 conn->pin_length = cp->pin_len;
770}
771
772static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
773{
774 struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
775
776 BT_DBG("%s status 0x%x", hdev->name, rp->status);
777
778 if (test_bit(HCI_MGMT, &hdev->flags))
779 mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
780 rp->status);
781}
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300782static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
783 struct sk_buff *skb)
784{
785 struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
786
787 BT_DBG("%s status 0x%x", hdev->name, rp->status);
788
789 if (rp->status)
790 return;
791
792 hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
793 hdev->le_pkts = rp->le_max_pkt;
794
795 hdev->le_cnt = hdev->le_pkts;
796
797 BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
798
799 hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
800}
Johan Hedberg980e1a52011-01-22 06:10:07 +0200801
Johan Hedberga5c29682011-02-19 12:05:57 -0300802static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
803{
804 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
805
806 BT_DBG("%s status 0x%x", hdev->name, rp->status);
807
808 if (test_bit(HCI_MGMT, &hdev->flags))
809 mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
810 rp->status);
811}
812
813static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
814 struct sk_buff *skb)
815{
816 struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
817
818 BT_DBG("%s status 0x%x", hdev->name, rp->status);
819
820 if (test_bit(HCI_MGMT, &hdev->flags))
821 mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
822 rp->status);
823}
824
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200825static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
826{
827 BT_DBG("%s status 0x%x", hdev->name, status);
828
829 if (status) {
Johan Hedberg23bb5762010-12-21 23:01:27 +0200830 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200831
832 hci_conn_check_pending(hdev);
833 } else
834 set_bit(HCI_INQUIRY, &hdev->flags);
835}
836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
838{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200839 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200842 BT_DBG("%s status 0x%x", hdev->name, status);
843
844 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 if (!cp)
846 return;
847
848 hci_dev_lock(hdev);
849
850 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
851
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200852 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
854 if (status) {
855 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200856 if (status != 0x0c || conn->attempt > 2) {
857 conn->state = BT_CLOSED;
858 hci_proto_connect_cfm(conn, status);
859 hci_conn_del(conn);
860 } else
861 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 }
863 } else {
864 if (!conn) {
865 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
866 if (conn) {
867 conn->out = 1;
868 conn->link_mode |= HCI_LM_MASTER;
869 } else
Gustavo F. Padovan893ef972010-07-18 15:13:37 -0300870 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 }
872 }
873
874 hci_dev_unlock(hdev);
875}
876
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200877static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200879 struct hci_cp_add_sco *cp;
880 struct hci_conn *acl, *sco;
881 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200883 BT_DBG("%s status 0x%x", hdev->name, status);
884
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200885 if (!status)
886 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200888 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
889 if (!cp)
890 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200892 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200894 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100895
896 hci_dev_lock(hdev);
897
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200898 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200899 if (acl) {
900 sco = acl->link;
901 if (sco) {
902 sco->state = BT_CLOSED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200903
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200904 hci_proto_connect_cfm(sco, status);
905 hci_conn_del(sco);
906 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200907 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100908
909 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910}
911
Marcel Holtmannf8558552008-07-14 20:13:49 +0200912static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
913{
914 struct hci_cp_auth_requested *cp;
915 struct hci_conn *conn;
916
917 BT_DBG("%s status 0x%x", hdev->name, status);
918
919 if (!status)
920 return;
921
922 cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
923 if (!cp)
924 return;
925
926 hci_dev_lock(hdev);
927
928 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
929 if (conn) {
930 if (conn->state == BT_CONFIG) {
931 hci_proto_connect_cfm(conn, status);
932 hci_conn_put(conn);
933 }
934 }
935
936 hci_dev_unlock(hdev);
937}
938
939static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
940{
941 struct hci_cp_set_conn_encrypt *cp;
942 struct hci_conn *conn;
943
944 BT_DBG("%s status 0x%x", hdev->name, status);
945
946 if (!status)
947 return;
948
949 cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
950 if (!cp)
951 return;
952
953 hci_dev_lock(hdev);
954
955 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
956 if (conn) {
957 if (conn->state == BT_CONFIG) {
958 hci_proto_connect_cfm(conn, status);
959 hci_conn_put(conn);
960 }
961 }
962
963 hci_dev_unlock(hdev);
964}
965
Johan Hedberg127178d2010-11-18 22:22:29 +0200966static int hci_outgoing_auth_needed(struct hci_dev *hdev,
Szymon Janc138d22e2011-02-17 16:44:23 +0100967 struct hci_conn *conn)
Johan Hedberg392599b2010-11-18 22:22:28 +0200968{
Johan Hedberg392599b2010-11-18 22:22:28 +0200969 if (conn->state != BT_CONFIG || !conn->out)
970 return 0;
971
Johan Hedberg765c2a92011-01-19 12:06:52 +0530972 if (conn->pending_sec_level == BT_SECURITY_SDP)
Johan Hedberg392599b2010-11-18 22:22:28 +0200973 return 0;
974
975 /* Only request authentication for SSP connections or non-SSP
976 * devices with sec_level HIGH */
977 if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
Johan Hedberg765c2a92011-01-19 12:06:52 +0530978 conn->pending_sec_level != BT_SECURITY_HIGH)
Johan Hedberg392599b2010-11-18 22:22:28 +0200979 return 0;
980
Johan Hedberg392599b2010-11-18 22:22:28 +0200981 return 1;
982}
983
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200984static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
985{
Johan Hedberg127178d2010-11-18 22:22:29 +0200986 struct hci_cp_remote_name_req *cp;
987 struct hci_conn *conn;
988
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200989 BT_DBG("%s status 0x%x", hdev->name, status);
Johan Hedberg127178d2010-11-18 22:22:29 +0200990
991 /* If successful wait for the name req complete event before
992 * checking for the need to do authentication */
993 if (!status)
994 return;
995
996 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
997 if (!cp)
998 return;
999
1000 hci_dev_lock(hdev);
1001
1002 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1003 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1004 struct hci_cp_auth_requested cp;
1005 cp.handle = __cpu_to_le16(conn->handle);
1006 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1007 }
1008
1009 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001010}
1011
Marcel Holtmann769be972008-07-14 20:13:49 +02001012static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1013{
1014 struct hci_cp_read_remote_features *cp;
1015 struct hci_conn *conn;
1016
1017 BT_DBG("%s status 0x%x", hdev->name, status);
1018
1019 if (!status)
1020 return;
1021
1022 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1023 if (!cp)
1024 return;
1025
1026 hci_dev_lock(hdev);
1027
1028 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1029 if (conn) {
1030 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001031 hci_proto_connect_cfm(conn, status);
1032 hci_conn_put(conn);
1033 }
1034 }
1035
1036 hci_dev_unlock(hdev);
1037}
1038
1039static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1040{
1041 struct hci_cp_read_remote_ext_features *cp;
1042 struct hci_conn *conn;
1043
1044 BT_DBG("%s status 0x%x", hdev->name, status);
1045
1046 if (!status)
1047 return;
1048
1049 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1050 if (!cp)
1051 return;
1052
1053 hci_dev_lock(hdev);
1054
1055 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1056 if (conn) {
1057 if (conn->state == BT_CONFIG) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001058 hci_proto_connect_cfm(conn, status);
1059 hci_conn_put(conn);
1060 }
1061 }
1062
1063 hci_dev_unlock(hdev);
1064}
1065
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001066static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1067{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001068 struct hci_cp_setup_sync_conn *cp;
1069 struct hci_conn *acl, *sco;
1070 __u16 handle;
1071
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001072 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001073
1074 if (!status)
1075 return;
1076
1077 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1078 if (!cp)
1079 return;
1080
1081 handle = __le16_to_cpu(cp->handle);
1082
1083 BT_DBG("%s handle %d", hdev->name, handle);
1084
1085 hci_dev_lock(hdev);
1086
1087 acl = hci_conn_hash_lookup_handle(hdev, handle);
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001088 if (acl) {
1089 sco = acl->link;
1090 if (sco) {
1091 sco->state = BT_CLOSED;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001092
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02001093 hci_proto_connect_cfm(sco, status);
1094 hci_conn_del(sco);
1095 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001096 }
1097
1098 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001099}
1100
1101static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1102{
1103 struct hci_cp_sniff_mode *cp;
1104 struct hci_conn *conn;
1105
1106 BT_DBG("%s status 0x%x", hdev->name, status);
1107
1108 if (!status)
1109 return;
1110
1111 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
1112 if (!cp)
1113 return;
1114
1115 hci_dev_lock(hdev);
1116
1117 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001118 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001119 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1120
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001121 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1122 hci_sco_setup(conn, status);
1123 }
1124
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001125 hci_dev_unlock(hdev);
1126}
1127
1128static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1129{
1130 struct hci_cp_exit_sniff_mode *cp;
1131 struct hci_conn *conn;
1132
1133 BT_DBG("%s status 0x%x", hdev->name, status);
1134
1135 if (!status)
1136 return;
1137
1138 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
1139 if (!cp)
1140 return;
1141
1142 hci_dev_lock(hdev);
1143
1144 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001145 if (conn) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001146 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
1147
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001148 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1149 hci_sco_setup(conn, status);
1150 }
1151
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001152 hci_dev_unlock(hdev);
1153}
1154
Ville Tervofcd89c02011-02-10 22:38:47 -03001155static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1156{
1157 struct hci_cp_le_create_conn *cp;
1158 struct hci_conn *conn;
1159
1160 BT_DBG("%s status 0x%x", hdev->name, status);
1161
1162 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1163 if (!cp)
1164 return;
1165
1166 hci_dev_lock(hdev);
1167
1168 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1169
1170 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1171 conn);
1172
1173 if (status) {
1174 if (conn && conn->state == BT_CONNECT) {
1175 conn->state = BT_CLOSED;
1176 hci_proto_connect_cfm(conn, status);
1177 hci_conn_del(conn);
1178 }
1179 } else {
1180 if (!conn) {
1181 conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
1182 if (conn)
1183 conn->out = 1;
1184 else
1185 BT_ERR("No memory for new connection");
1186 }
1187 }
1188
1189 hci_dev_unlock(hdev);
1190}
1191
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001192static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1193{
1194 __u8 status = *((__u8 *) skb->data);
1195
1196 BT_DBG("%s status %d", hdev->name, status);
1197
1198 clear_bit(HCI_INQUIRY, &hdev->flags);
1199
Johan Hedberg23bb5762010-12-21 23:01:27 +02001200 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001201
1202 hci_conn_check_pending(hdev);
1203}
1204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1206{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001207 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001208 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 int num_rsp = *((__u8 *) skb->data);
1210
1211 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1212
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001213 if (!num_rsp)
1214 return;
1215
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 for (; num_rsp; num_rsp--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 bacpy(&data.bdaddr, &info->bdaddr);
1220 data.pscan_rep_mode = info->pscan_rep_mode;
1221 data.pscan_period_mode = info->pscan_period_mode;
1222 data.pscan_mode = info->pscan_mode;
1223 memcpy(data.dev_class, info->dev_class, 3);
1224 data.clock_offset = info->clock_offset;
1225 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001226 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 info++;
1228 hci_inquiry_cache_update(hdev, &data);
1229 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001230
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 hci_dev_unlock(hdev);
1232}
1233
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001234static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001236 struct hci_ev_conn_complete *ev = (void *) skb->data;
1237 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001239 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001240
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001242
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001243 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann94992372009-04-19 19:30:03 +02001244 if (!conn) {
1245 if (ev->link_type != SCO_LINK)
1246 goto unlock;
1247
1248 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1249 if (!conn)
1250 goto unlock;
1251
1252 conn->type = SCO_LINK;
1253 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001254
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001255 if (!ev->status) {
1256 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +02001257
1258 if (conn->type == ACL_LINK) {
1259 conn->state = BT_CONFIG;
1260 hci_conn_hold(conn);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001261 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedbergf7520542011-01-20 12:34:39 +02001262 mgmt_connected(hdev->id, &ev->bdaddr);
Marcel Holtmann769be972008-07-14 20:13:49 +02001263 } else
1264 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001265
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001266 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001267 hci_conn_add_sysfs(conn);
1268
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001269 if (test_bit(HCI_AUTH, &hdev->flags))
1270 conn->link_mode |= HCI_LM_AUTH;
1271
1272 if (test_bit(HCI_ENCRYPT, &hdev->flags))
1273 conn->link_mode |= HCI_LM_ENCRYPT;
1274
1275 /* Get remote features */
1276 if (conn->type == ACL_LINK) {
1277 struct hci_cp_read_remote_features cp;
1278 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +02001279 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1280 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001281 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001282
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001283 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +02001284 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001285 struct hci_cp_change_conn_ptype cp;
1286 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +02001287 cp.pkt_type = cpu_to_le16(conn->pkt_type);
1288 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1289 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001290 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02001291 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001292 conn->state = BT_CLOSED;
Johan Hedberg17d5c042011-01-22 06:09:08 +02001293 if (conn->type == ACL_LINK)
1294 mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
1295 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001296
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001297 if (conn->type == ACL_LINK)
1298 hci_sco_setup(conn, ev->status);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -07001299
Marcel Holtmann769be972008-07-14 20:13:49 +02001300 if (ev->status) {
1301 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001302 hci_conn_del(conn);
Marcel Holtmannc89b6e62009-01-15 21:57:03 +01001303 } else if (ev->link_type != ACL_LINK)
1304 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001305
1306unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001308
1309 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310}
1311
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1313{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001314 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 int mask = hdev->link_mode;
1316
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001317 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
1318 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
1320 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
1321
Szymon Janc138d22e2011-02-17 16:44:23 +01001322 if ((mask & HCI_LM_ACCEPT) &&
1323 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001325 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
1328 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001329
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001330 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1331 if (ie)
Marcel Holtmannc7bdd502008-07-14 20:13:47 +02001332 memcpy(ie->data.dev_class, ev->dev_class, 3);
1333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
1335 if (!conn) {
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02001336 conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1337 if (!conn) {
Gustavo F. Padovan893ef972010-07-18 15:13:37 -03001338 BT_ERR("No memory for new connection");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 hci_dev_unlock(hdev);
1340 return;
1341 }
1342 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001343
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 memcpy(conn->dev_class, ev->dev_class, 3);
1345 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 hci_dev_unlock(hdev);
1348
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001349 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1350 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001352 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001354 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
1355 cp.role = 0x00; /* Become master */
1356 else
1357 cp.role = 0x01; /* Remain slave */
1358
1359 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1360 sizeof(cp), &cp);
1361 } else {
1362 struct hci_cp_accept_sync_conn_req cp;
1363
1364 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +02001365 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001366
1367 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
1368 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
1369 cp.max_latency = cpu_to_le16(0xffff);
1370 cp.content_format = cpu_to_le16(hdev->voice_setting);
1371 cp.retrans_effort = 0xff;
1372
1373 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1374 sizeof(cp), &cp);
1375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 } else {
1377 /* Connection rejected */
1378 struct hci_cp_reject_conn_req cp;
1379
1380 bacpy(&cp.bdaddr, &ev->bdaddr);
1381 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001382 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 }
1384}
1385
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1387{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001388 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001389 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
1391 BT_DBG("%s status %d", hdev->name, ev->status);
1392
Johan Hedberg8962ee72011-01-20 12:40:27 +02001393 if (ev->status) {
1394 mgmt_disconnect_failed(hdev->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001396 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
1398 hci_dev_lock(hdev);
1399
Marcel Holtmann04837f62006-07-03 10:02:33 +02001400 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergf7520542011-01-20 12:34:39 +02001401 if (!conn)
1402 goto unlock;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02001403
Johan Hedbergf7520542011-01-20 12:34:39 +02001404 conn->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Johan Hedbergf7520542011-01-20 12:34:39 +02001406 if (conn->type == ACL_LINK)
1407 mgmt_disconnected(hdev->id, &conn->dst);
1408
1409 hci_proto_disconn_cfm(conn, ev->reason);
1410 hci_conn_del(conn);
1411
1412unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 hci_dev_unlock(hdev);
1414}
1415
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001416static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1417{
1418 struct hci_ev_auth_complete *ev = (void *) skb->data;
1419 struct hci_conn *conn;
1420
1421 BT_DBG("%s status %d", hdev->name, ev->status);
1422
1423 hci_dev_lock(hdev);
1424
1425 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1426 if (conn) {
Johan Hedberg765c2a92011-01-19 12:06:52 +05301427 if (!ev->status) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001428 conn->link_mode |= HCI_LM_AUTH;
Johan Hedberg765c2a92011-01-19 12:06:52 +05301429 conn->sec_level = conn->pending_sec_level;
Johan Hedberg2a611692011-02-19 12:06:00 -03001430 } else {
1431 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
Johan Hedbergda213f42010-06-18 11:08:56 +03001432 conn->sec_level = BT_SECURITY_LOW;
Johan Hedberg2a611692011-02-19 12:06:00 -03001433 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001434
1435 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1436
Marcel Holtmannf8558552008-07-14 20:13:49 +02001437 if (conn->state == BT_CONFIG) {
1438 if (!ev->status && hdev->ssp_mode > 0 &&
1439 conn->ssp_mode > 0) {
1440 struct hci_cp_set_conn_encrypt cp;
1441 cp.handle = ev->handle;
1442 cp.encrypt = 0x01;
1443 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1444 sizeof(cp), &cp);
1445 } else {
1446 conn->state = BT_CONNECTED;
1447 hci_proto_connect_cfm(conn, ev->status);
1448 hci_conn_put(conn);
1449 }
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001450 } else {
Marcel Holtmannf8558552008-07-14 20:13:49 +02001451 hci_auth_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001452
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001453 hci_conn_hold(conn);
1454 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1455 hci_conn_put(conn);
1456 }
1457
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001458 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1459 if (!ev->status) {
1460 struct hci_cp_set_conn_encrypt cp;
Marcel Holtmannf8558552008-07-14 20:13:49 +02001461 cp.handle = ev->handle;
1462 cp.encrypt = 0x01;
1463 hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1464 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001465 } else {
1466 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1467 hci_encrypt_cfm(conn, ev->status, 0x00);
1468 }
1469 }
1470 }
1471
1472 hci_dev_unlock(hdev);
1473}
1474
1475static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1476{
Johan Hedberg127178d2010-11-18 22:22:29 +02001477 struct hci_ev_remote_name *ev = (void *) skb->data;
1478 struct hci_conn *conn;
1479
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001480 BT_DBG("%s", hdev->name);
1481
1482 hci_conn_check_pending(hdev);
Johan Hedberg127178d2010-11-18 22:22:29 +02001483
1484 hci_dev_lock(hdev);
1485
1486 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1487 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1488 struct hci_cp_auth_requested cp;
1489 cp.handle = __cpu_to_le16(conn->handle);
1490 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1491 }
1492
1493 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001494}
1495
1496static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1497{
1498 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1499 struct hci_conn *conn;
1500
1501 BT_DBG("%s status %d", hdev->name, ev->status);
1502
1503 hci_dev_lock(hdev);
1504
1505 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1506 if (conn) {
1507 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001508 if (ev->encrypt) {
1509 /* Encryption implies authentication */
1510 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001511 conn->link_mode |= HCI_LM_ENCRYPT;
Marcel Holtmannae293192008-07-14 20:13:45 +02001512 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001513 conn->link_mode &= ~HCI_LM_ENCRYPT;
1514 }
1515
1516 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1517
Marcel Holtmannf8558552008-07-14 20:13:49 +02001518 if (conn->state == BT_CONFIG) {
1519 if (!ev->status)
1520 conn->state = BT_CONNECTED;
1521
1522 hci_proto_connect_cfm(conn, ev->status);
1523 hci_conn_put(conn);
1524 } else
1525 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001526 }
1527
1528 hci_dev_unlock(hdev);
1529}
1530
1531static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1532{
1533 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1534 struct hci_conn *conn;
1535
1536 BT_DBG("%s status %d", hdev->name, ev->status);
1537
1538 hci_dev_lock(hdev);
1539
1540 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1541 if (conn) {
1542 if (!ev->status)
1543 conn->link_mode |= HCI_LM_SECURE;
1544
1545 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1546
1547 hci_key_change_cfm(conn, ev->status);
1548 }
1549
1550 hci_dev_unlock(hdev);
1551}
1552
1553static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1554{
1555 struct hci_ev_remote_features *ev = (void *) skb->data;
1556 struct hci_conn *conn;
1557
1558 BT_DBG("%s status %d", hdev->name, ev->status);
1559
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001560 hci_dev_lock(hdev);
1561
1562 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02001563 if (!conn)
1564 goto unlock;
Marcel Holtmann769be972008-07-14 20:13:49 +02001565
Johan Hedbergccd556f2010-11-10 17:11:51 +02001566 if (!ev->status)
1567 memcpy(conn->features, ev->features, 8);
1568
1569 if (conn->state != BT_CONFIG)
1570 goto unlock;
1571
1572 if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1573 struct hci_cp_read_remote_ext_features cp;
1574 cp.handle = ev->handle;
1575 cp.page = 0x01;
1576 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
Marcel Holtmann769be972008-07-14 20:13:49 +02001577 sizeof(cp), &cp);
Johan Hedberg392599b2010-11-18 22:22:28 +02001578 goto unlock;
1579 }
1580
Johan Hedberg127178d2010-11-18 22:22:29 +02001581 if (!ev->status) {
1582 struct hci_cp_remote_name_req cp;
1583 memset(&cp, 0, sizeof(cp));
1584 bacpy(&cp.bdaddr, &conn->dst);
1585 cp.pscan_rep_mode = 0x02;
1586 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1587 }
Johan Hedberg392599b2010-11-18 22:22:28 +02001588
Johan Hedberg127178d2010-11-18 22:22:29 +02001589 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02001590 conn->state = BT_CONNECTED;
1591 hci_proto_connect_cfm(conn, ev->status);
1592 hci_conn_put(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +02001593 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001594
Johan Hedbergccd556f2010-11-10 17:11:51 +02001595unlock:
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001596 hci_dev_unlock(hdev);
1597}
1598
1599static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1600{
1601 BT_DBG("%s", hdev->name);
1602}
1603
1604static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1605{
1606 BT_DBG("%s", hdev->name);
1607}
1608
1609static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1610{
1611 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1612 __u16 opcode;
1613
1614 skb_pull(skb, sizeof(*ev));
1615
1616 opcode = __le16_to_cpu(ev->opcode);
1617
1618 switch (opcode) {
1619 case HCI_OP_INQUIRY_CANCEL:
1620 hci_cc_inquiry_cancel(hdev, skb);
1621 break;
1622
1623 case HCI_OP_EXIT_PERIODIC_INQ:
1624 hci_cc_exit_periodic_inq(hdev, skb);
1625 break;
1626
1627 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1628 hci_cc_remote_name_req_cancel(hdev, skb);
1629 break;
1630
1631 case HCI_OP_ROLE_DISCOVERY:
1632 hci_cc_role_discovery(hdev, skb);
1633 break;
1634
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001635 case HCI_OP_READ_LINK_POLICY:
1636 hci_cc_read_link_policy(hdev, skb);
1637 break;
1638
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001639 case HCI_OP_WRITE_LINK_POLICY:
1640 hci_cc_write_link_policy(hdev, skb);
1641 break;
1642
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001643 case HCI_OP_READ_DEF_LINK_POLICY:
1644 hci_cc_read_def_link_policy(hdev, skb);
1645 break;
1646
1647 case HCI_OP_WRITE_DEF_LINK_POLICY:
1648 hci_cc_write_def_link_policy(hdev, skb);
1649 break;
1650
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001651 case HCI_OP_RESET:
1652 hci_cc_reset(hdev, skb);
1653 break;
1654
1655 case HCI_OP_WRITE_LOCAL_NAME:
1656 hci_cc_write_local_name(hdev, skb);
1657 break;
1658
1659 case HCI_OP_READ_LOCAL_NAME:
1660 hci_cc_read_local_name(hdev, skb);
1661 break;
1662
1663 case HCI_OP_WRITE_AUTH_ENABLE:
1664 hci_cc_write_auth_enable(hdev, skb);
1665 break;
1666
1667 case HCI_OP_WRITE_ENCRYPT_MODE:
1668 hci_cc_write_encrypt_mode(hdev, skb);
1669 break;
1670
1671 case HCI_OP_WRITE_SCAN_ENABLE:
1672 hci_cc_write_scan_enable(hdev, skb);
1673 break;
1674
1675 case HCI_OP_READ_CLASS_OF_DEV:
1676 hci_cc_read_class_of_dev(hdev, skb);
1677 break;
1678
1679 case HCI_OP_WRITE_CLASS_OF_DEV:
1680 hci_cc_write_class_of_dev(hdev, skb);
1681 break;
1682
1683 case HCI_OP_READ_VOICE_SETTING:
1684 hci_cc_read_voice_setting(hdev, skb);
1685 break;
1686
1687 case HCI_OP_WRITE_VOICE_SETTING:
1688 hci_cc_write_voice_setting(hdev, skb);
1689 break;
1690
1691 case HCI_OP_HOST_BUFFER_SIZE:
1692 hci_cc_host_buffer_size(hdev, skb);
1693 break;
1694
Marcel Holtmann333140b2008-07-14 20:13:48 +02001695 case HCI_OP_READ_SSP_MODE:
1696 hci_cc_read_ssp_mode(hdev, skb);
1697 break;
1698
1699 case HCI_OP_WRITE_SSP_MODE:
1700 hci_cc_write_ssp_mode(hdev, skb);
1701 break;
1702
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001703 case HCI_OP_READ_LOCAL_VERSION:
1704 hci_cc_read_local_version(hdev, skb);
1705 break;
1706
1707 case HCI_OP_READ_LOCAL_COMMANDS:
1708 hci_cc_read_local_commands(hdev, skb);
1709 break;
1710
1711 case HCI_OP_READ_LOCAL_FEATURES:
1712 hci_cc_read_local_features(hdev, skb);
1713 break;
1714
1715 case HCI_OP_READ_BUFFER_SIZE:
1716 hci_cc_read_buffer_size(hdev, skb);
1717 break;
1718
1719 case HCI_OP_READ_BD_ADDR:
1720 hci_cc_read_bd_addr(hdev, skb);
1721 break;
1722
Johan Hedberg23bb5762010-12-21 23:01:27 +02001723 case HCI_OP_WRITE_CA_TIMEOUT:
1724 hci_cc_write_ca_timeout(hdev, skb);
1725 break;
1726
Johan Hedbergb0916ea2011-01-10 13:44:55 +02001727 case HCI_OP_DELETE_STORED_LINK_KEY:
1728 hci_cc_delete_stored_link_key(hdev, skb);
1729 break;
1730
Johan Hedbergd5859e22011-01-25 01:19:58 +02001731 case HCI_OP_SET_EVENT_MASK:
1732 hci_cc_set_event_mask(hdev, skb);
1733 break;
1734
1735 case HCI_OP_WRITE_INQUIRY_MODE:
1736 hci_cc_write_inquiry_mode(hdev, skb);
1737 break;
1738
1739 case HCI_OP_READ_INQ_RSP_TX_POWER:
1740 hci_cc_read_inq_rsp_tx_power(hdev, skb);
1741 break;
1742
1743 case HCI_OP_SET_EVENT_FLT:
1744 hci_cc_set_event_flt(hdev, skb);
1745 break;
1746
Johan Hedberg980e1a52011-01-22 06:10:07 +02001747 case HCI_OP_PIN_CODE_REPLY:
1748 hci_cc_pin_code_reply(hdev, skb);
1749 break;
1750
1751 case HCI_OP_PIN_CODE_NEG_REPLY:
1752 hci_cc_pin_code_neg_reply(hdev, skb);
1753 break;
1754
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001755 case HCI_OP_LE_READ_BUFFER_SIZE:
1756 hci_cc_le_read_buffer_size(hdev, skb);
1757 break;
1758
Johan Hedberga5c29682011-02-19 12:05:57 -03001759 case HCI_OP_USER_CONFIRM_REPLY:
1760 hci_cc_user_confirm_reply(hdev, skb);
1761 break;
1762
1763 case HCI_OP_USER_CONFIRM_NEG_REPLY:
1764 hci_cc_user_confirm_neg_reply(hdev, skb);
1765 break;
1766
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001767 default:
1768 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1769 break;
1770 }
1771
Ville Tervo6bd32322011-02-16 16:32:41 +02001772 if (ev->opcode != HCI_OP_NOP)
1773 del_timer(&hdev->cmd_timer);
1774
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001775 if (ev->ncmd) {
1776 atomic_set(&hdev->cmd_cnt, 1);
1777 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001778 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001779 }
1780}
1781
1782static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1783{
1784 struct hci_ev_cmd_status *ev = (void *) skb->data;
1785 __u16 opcode;
1786
1787 skb_pull(skb, sizeof(*ev));
1788
1789 opcode = __le16_to_cpu(ev->opcode);
1790
1791 switch (opcode) {
1792 case HCI_OP_INQUIRY:
1793 hci_cs_inquiry(hdev, ev->status);
1794 break;
1795
1796 case HCI_OP_CREATE_CONN:
1797 hci_cs_create_conn(hdev, ev->status);
1798 break;
1799
1800 case HCI_OP_ADD_SCO:
1801 hci_cs_add_sco(hdev, ev->status);
1802 break;
1803
Marcel Holtmannf8558552008-07-14 20:13:49 +02001804 case HCI_OP_AUTH_REQUESTED:
1805 hci_cs_auth_requested(hdev, ev->status);
1806 break;
1807
1808 case HCI_OP_SET_CONN_ENCRYPT:
1809 hci_cs_set_conn_encrypt(hdev, ev->status);
1810 break;
1811
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001812 case HCI_OP_REMOTE_NAME_REQ:
1813 hci_cs_remote_name_req(hdev, ev->status);
1814 break;
1815
Marcel Holtmann769be972008-07-14 20:13:49 +02001816 case HCI_OP_READ_REMOTE_FEATURES:
1817 hci_cs_read_remote_features(hdev, ev->status);
1818 break;
1819
1820 case HCI_OP_READ_REMOTE_EXT_FEATURES:
1821 hci_cs_read_remote_ext_features(hdev, ev->status);
1822 break;
1823
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001824 case HCI_OP_SETUP_SYNC_CONN:
1825 hci_cs_setup_sync_conn(hdev, ev->status);
1826 break;
1827
1828 case HCI_OP_SNIFF_MODE:
1829 hci_cs_sniff_mode(hdev, ev->status);
1830 break;
1831
1832 case HCI_OP_EXIT_SNIFF_MODE:
1833 hci_cs_exit_sniff_mode(hdev, ev->status);
1834 break;
1835
Johan Hedberg8962ee72011-01-20 12:40:27 +02001836 case HCI_OP_DISCONNECT:
1837 if (ev->status != 0)
1838 mgmt_disconnect_failed(hdev->id);
1839 break;
1840
Ville Tervofcd89c02011-02-10 22:38:47 -03001841 case HCI_OP_LE_CREATE_CONN:
1842 hci_cs_le_create_conn(hdev, ev->status);
1843 break;
1844
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001845 default:
1846 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1847 break;
1848 }
1849
Ville Tervo6bd32322011-02-16 16:32:41 +02001850 if (ev->opcode != HCI_OP_NOP)
1851 del_timer(&hdev->cmd_timer);
1852
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001853 if (ev->ncmd) {
1854 atomic_set(&hdev->cmd_cnt, 1);
1855 if (!skb_queue_empty(&hdev->cmd_q))
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001856 tasklet_schedule(&hdev->cmd_task);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001857 }
1858}
1859
1860static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1861{
1862 struct hci_ev_role_change *ev = (void *) skb->data;
1863 struct hci_conn *conn;
1864
1865 BT_DBG("%s status %d", hdev->name, ev->status);
1866
1867 hci_dev_lock(hdev);
1868
1869 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1870 if (conn) {
1871 if (!ev->status) {
1872 if (ev->role)
1873 conn->link_mode &= ~HCI_LM_MASTER;
1874 else
1875 conn->link_mode |= HCI_LM_MASTER;
1876 }
1877
1878 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1879
1880 hci_role_switch_cfm(conn, ev->status, ev->role);
1881 }
1882
1883 hci_dev_unlock(hdev);
1884}
1885
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
1887{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001888 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001889 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 int i;
1891
1892 skb_pull(skb, sizeof(*ev));
1893
1894 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
1895
1896 if (skb->len < ev->num_hndl * 4) {
1897 BT_DBG("%s bad parameters", hdev->name);
1898 return;
1899 }
1900
1901 tasklet_disable(&hdev->tx_task);
1902
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001903 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 struct hci_conn *conn;
1905 __u16 handle, count;
1906
Harvey Harrison83985312008-05-02 16:25:46 -07001907 handle = get_unaligned_le16(ptr++);
1908 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
1910 conn = hci_conn_hash_lookup_handle(hdev, handle);
1911 if (conn) {
1912 conn->sent -= count;
1913
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001914 if (conn->type == ACL_LINK) {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001915 hdev->acl_cnt += count;
1916 if (hdev->acl_cnt > hdev->acl_pkts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 hdev->acl_cnt = hdev->acl_pkts;
Ville Tervo6ed58ec2011-02-10 22:38:48 -03001918 } else if (conn->type == LE_LINK) {
1919 if (hdev->le_pkts) {
1920 hdev->le_cnt += count;
1921 if (hdev->le_cnt > hdev->le_pkts)
1922 hdev->le_cnt = hdev->le_pkts;
1923 } else {
1924 hdev->acl_cnt += count;
1925 if (hdev->acl_cnt > hdev->acl_pkts)
1926 hdev->acl_cnt = hdev->acl_pkts;
1927 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001928 } else {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001929 hdev->sco_cnt += count;
1930 if (hdev->sco_cnt > hdev->sco_pkts)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001931 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 }
1933 }
1934 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001935
Marcel Holtmannc78ae282009-11-18 01:02:54 +01001936 tasklet_schedule(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937
1938 tasklet_enable(&hdev->tx_task);
1939}
1940
Marcel Holtmann04837f62006-07-03 10:02:33 +02001941static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001943 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001944 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945
1946 BT_DBG("%s status %d", hdev->name, ev->status);
1947
1948 hci_dev_lock(hdev);
1949
Marcel Holtmann04837f62006-07-03 10:02:33 +02001950 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1951 if (conn) {
1952 conn->mode = ev->mode;
1953 conn->interval = __le16_to_cpu(ev->interval);
1954
1955 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
1956 if (conn->mode == HCI_CM_ACTIVE)
1957 conn->power_save = 1;
1958 else
1959 conn->power_save = 0;
1960 }
Marcel Holtmanne73439d2010-07-26 10:06:00 -04001961
1962 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1963 hci_sco_setup(conn, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02001964 }
1965
1966 hci_dev_unlock(hdev);
1967}
1968
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1970{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001971 struct hci_ev_pin_code_req *ev = (void *) skb->data;
1972 struct hci_conn *conn;
1973
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001974 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001975
1976 hci_dev_lock(hdev);
1977
1978 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Marcel Holtmann3d7a9d12009-05-09 12:09:21 -07001979 if (conn && conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001980 hci_conn_hold(conn);
1981 conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1982 hci_conn_put(conn);
1983 }
1984
Johan Hedberg03b555e2011-01-04 15:40:05 +02001985 if (!test_bit(HCI_PAIRABLE, &hdev->flags))
1986 hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
1987 sizeof(ev->bdaddr), &ev->bdaddr);
1988
Johan Hedberg980e1a52011-01-22 06:10:07 +02001989 if (test_bit(HCI_MGMT, &hdev->flags))
1990 mgmt_pin_code_request(hdev->id, &ev->bdaddr);
1991
Marcel Holtmann052b30b2009-04-26 20:01:22 +02001992 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993}
1994
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1996{
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02001997 struct hci_ev_link_key_req *ev = (void *) skb->data;
1998 struct hci_cp_link_key_reply cp;
1999 struct hci_conn *conn;
2000 struct link_key *key;
2001
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002002 BT_DBG("%s", hdev->name);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002003
2004 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
2005 return;
2006
2007 hci_dev_lock(hdev);
2008
2009 key = hci_find_link_key(hdev, &ev->bdaddr);
2010 if (!key) {
2011 BT_DBG("%s link key not found for %s", hdev->name,
2012 batostr(&ev->bdaddr));
2013 goto not_found;
2014 }
2015
2016 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
2017 batostr(&ev->bdaddr));
2018
2019 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
2020 BT_DBG("%s ignoring debug key", hdev->name);
2021 goto not_found;
2022 }
2023
2024 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2025
2026 if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
2027 (conn->auth_type & 0x01)) {
2028 BT_DBG("%s ignoring unauthenticated key", hdev->name);
2029 goto not_found;
2030 }
2031
2032 bacpy(&cp.bdaddr, &ev->bdaddr);
2033 memcpy(cp.link_key, key->val, 16);
2034
2035 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
2036
2037 hci_dev_unlock(hdev);
2038
2039 return;
2040
2041not_found:
2042 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
2043 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044}
2045
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
2047{
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002048 struct hci_ev_link_key_notify *ev = (void *) skb->data;
2049 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002050 u8 pin_len = 0;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002051
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002052 BT_DBG("%s", hdev->name);
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002053
2054 hci_dev_lock(hdev);
2055
2056 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2057 if (conn) {
2058 hci_conn_hold(conn);
2059 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002060 pin_len = conn->pin_length;
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002061 hci_conn_put(conn);
2062 }
2063
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002064 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2065 hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
2066 ev->key_type, pin_len);
2067
Marcel Holtmann052b30b2009-04-26 20:01:22 +02002068 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069}
2070
Marcel Holtmann04837f62006-07-03 10:02:33 +02002071static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
2072{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002073 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002074 struct hci_conn *conn;
2075
2076 BT_DBG("%s status %d", hdev->name, ev->status);
2077
2078 hci_dev_lock(hdev);
2079
2080 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 if (conn && !ev->status) {
2082 struct inquiry_entry *ie;
2083
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002084 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2085 if (ie) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 ie->data.clock_offset = ev->clock_offset;
2087 ie->timestamp = jiffies;
2088 }
2089 }
2090
2091 hci_dev_unlock(hdev);
2092}
2093
Marcel Holtmanna8746412008-07-14 20:13:46 +02002094static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2095{
2096 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2097 struct hci_conn *conn;
2098
2099 BT_DBG("%s status %d", hdev->name, ev->status);
2100
2101 hci_dev_lock(hdev);
2102
2103 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2104 if (conn && !ev->status)
2105 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2106
2107 hci_dev_unlock(hdev);
2108}
2109
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002110static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
2111{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002112 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002113 struct inquiry_entry *ie;
2114
2115 BT_DBG("%s", hdev->name);
2116
2117 hci_dev_lock(hdev);
2118
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002119 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2120 if (ie) {
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002121 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
2122 ie->timestamp = jiffies;
2123 }
2124
2125 hci_dev_unlock(hdev);
2126}
2127
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002128static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2129{
2130 struct inquiry_data data;
2131 int num_rsp = *((__u8 *) skb->data);
2132
2133 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2134
2135 if (!num_rsp)
2136 return;
2137
2138 hci_dev_lock(hdev);
2139
2140 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
Szymon Janc138d22e2011-02-17 16:44:23 +01002141 struct inquiry_info_with_rssi_and_pscan_mode *info;
2142 info = (void *) (skb->data + 1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002143
2144 for (; num_rsp; num_rsp--) {
2145 bacpy(&data.bdaddr, &info->bdaddr);
2146 data.pscan_rep_mode = info->pscan_rep_mode;
2147 data.pscan_period_mode = info->pscan_period_mode;
2148 data.pscan_mode = info->pscan_mode;
2149 memcpy(data.dev_class, info->dev_class, 3);
2150 data.clock_offset = info->clock_offset;
2151 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002152 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002153 info++;
2154 hci_inquiry_cache_update(hdev, &data);
2155 }
2156 } else {
2157 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2158
2159 for (; num_rsp; num_rsp--) {
2160 bacpy(&data.bdaddr, &info->bdaddr);
2161 data.pscan_rep_mode = info->pscan_rep_mode;
2162 data.pscan_period_mode = info->pscan_period_mode;
2163 data.pscan_mode = 0x00;
2164 memcpy(data.dev_class, info->dev_class, 3);
2165 data.clock_offset = info->clock_offset;
2166 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002167 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002168 info++;
2169 hci_inquiry_cache_update(hdev, &data);
2170 }
2171 }
2172
2173 hci_dev_unlock(hdev);
2174}
2175
2176static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2177{
Marcel Holtmann41a96212008-07-14 20:13:48 +02002178 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
2179 struct hci_conn *conn;
2180
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002181 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002182
Marcel Holtmann41a96212008-07-14 20:13:48 +02002183 hci_dev_lock(hdev);
2184
2185 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Johan Hedbergccd556f2010-11-10 17:11:51 +02002186 if (!conn)
2187 goto unlock;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002188
Johan Hedbergccd556f2010-11-10 17:11:51 +02002189 if (!ev->status && ev->page == 0x01) {
2190 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002191
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002192 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2193 if (ie)
Johan Hedbergccd556f2010-11-10 17:11:51 +02002194 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann769be972008-07-14 20:13:49 +02002195
Johan Hedbergccd556f2010-11-10 17:11:51 +02002196 conn->ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02002197 }
2198
Johan Hedbergccd556f2010-11-10 17:11:51 +02002199 if (conn->state != BT_CONFIG)
2200 goto unlock;
2201
Johan Hedberg127178d2010-11-18 22:22:29 +02002202 if (!ev->status) {
2203 struct hci_cp_remote_name_req cp;
2204 memset(&cp, 0, sizeof(cp));
2205 bacpy(&cp.bdaddr, &conn->dst);
2206 cp.pscan_rep_mode = 0x02;
2207 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2208 }
Johan Hedberg392599b2010-11-18 22:22:28 +02002209
Johan Hedberg127178d2010-11-18 22:22:29 +02002210 if (!hci_outgoing_auth_needed(hdev, conn)) {
Johan Hedbergccd556f2010-11-10 17:11:51 +02002211 conn->state = BT_CONNECTED;
2212 hci_proto_connect_cfm(conn, ev->status);
2213 hci_conn_put(conn);
2214 }
2215
2216unlock:
Marcel Holtmann41a96212008-07-14 20:13:48 +02002217 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002218}
2219
2220static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2221{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002222 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2223 struct hci_conn *conn;
2224
2225 BT_DBG("%s status %d", hdev->name, ev->status);
2226
2227 hci_dev_lock(hdev);
2228
2229 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02002230 if (!conn) {
2231 if (ev->link_type == ESCO_LINK)
2232 goto unlock;
2233
2234 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2235 if (!conn)
2236 goto unlock;
2237
2238 conn->type = SCO_LINK;
2239 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002240
Marcel Holtmann732547f2009-04-19 19:14:14 +02002241 switch (ev->status) {
2242 case 0x00:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002243 conn->handle = __le16_to_cpu(ev->handle);
2244 conn->state = BT_CONNECTED;
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002245
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07002246 hci_conn_hold_device(conn);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +02002247 hci_conn_add_sysfs(conn);
Marcel Holtmann732547f2009-04-19 19:14:14 +02002248 break;
2249
Stephen Coe705e5712010-02-16 11:29:44 -05002250 case 0x11: /* Unsupported Feature or Parameter Value */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002251 case 0x1c: /* SCO interval rejected */
Nick Pelly1038a002010-02-03 11:42:26 -08002252 case 0x1a: /* Unsupported Remote Feature */
Marcel Holtmann732547f2009-04-19 19:14:14 +02002253 case 0x1f: /* Unspecified error */
2254 if (conn->out && conn->attempt < 2) {
2255 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2256 (hdev->esco_type & EDR_ESCO_MASK);
2257 hci_setup_sync(conn, conn->link->handle);
2258 goto unlock;
2259 }
2260 /* fall through */
2261
2262 default:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002263 conn->state = BT_CLOSED;
Marcel Holtmann732547f2009-04-19 19:14:14 +02002264 break;
2265 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02002266
2267 hci_proto_connect_cfm(conn, ev->status);
2268 if (ev->status)
2269 hci_conn_del(conn);
2270
2271unlock:
2272 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002273}
2274
2275static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2276{
2277 BT_DBG("%s", hdev->name);
2278}
2279
Marcel Holtmann04837f62006-07-03 10:02:33 +02002280static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
2281{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002282 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02002283
2284 BT_DBG("%s status %d", hdev->name, ev->status);
Marcel Holtmann04837f62006-07-03 10:02:33 +02002285}
2286
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002287static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2288{
2289 struct inquiry_data data;
2290 struct extended_inquiry_info *info = (void *) (skb->data + 1);
2291 int num_rsp = *((__u8 *) skb->data);
2292
2293 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2294
2295 if (!num_rsp)
2296 return;
2297
2298 hci_dev_lock(hdev);
2299
2300 for (; num_rsp; num_rsp--) {
2301 bacpy(&data.bdaddr, &info->bdaddr);
Szymon Janc138d22e2011-02-17 16:44:23 +01002302 data.pscan_rep_mode = info->pscan_rep_mode;
2303 data.pscan_period_mode = info->pscan_period_mode;
2304 data.pscan_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002305 memcpy(data.dev_class, info->dev_class, 3);
Szymon Janc138d22e2011-02-17 16:44:23 +01002306 data.clock_offset = info->clock_offset;
2307 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02002308 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002309 info++;
2310 hci_inquiry_cache_update(hdev, &data);
2311 }
2312
2313 hci_dev_unlock(hdev);
2314}
2315
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002316static inline u8 hci_get_auth_req(struct hci_conn *conn)
2317{
2318 /* If remote requests dedicated bonding follow that lead */
2319 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
2320 /* If both remote and local IO capabilities allow MITM
2321 * protection then require it, otherwise don't */
2322 if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
2323 return 0x02;
2324 else
2325 return 0x03;
2326 }
2327
2328 /* If remote requests no-bonding follow that lead */
2329 if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
2330 return 0x00;
2331
2332 return conn->auth_type;
2333}
2334
Marcel Holtmann04936842008-07-14 20:13:48 +02002335static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2336{
2337 struct hci_ev_io_capa_request *ev = (void *) skb->data;
2338 struct hci_conn *conn;
2339
2340 BT_DBG("%s", hdev->name);
2341
2342 hci_dev_lock(hdev);
2343
2344 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002345 if (!conn)
2346 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002347
Johan Hedberg03b555e2011-01-04 15:40:05 +02002348 hci_conn_hold(conn);
2349
2350 if (!test_bit(HCI_MGMT, &hdev->flags))
2351 goto unlock;
2352
2353 if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
2354 (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002355 struct hci_cp_io_capability_reply cp;
2356
2357 bacpy(&cp.bdaddr, &ev->bdaddr);
2358 cp.capability = conn->io_capability;
2359 cp.oob_data = 0;
2360 cp.authentication = hci_get_auth_req(conn);
2361
2362 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
2363 sizeof(cp), &cp);
Johan Hedberg03b555e2011-01-04 15:40:05 +02002364 } else {
2365 struct hci_cp_io_capability_neg_reply cp;
2366
2367 bacpy(&cp.bdaddr, &ev->bdaddr);
2368 cp.reason = 0x16; /* Pairing not allowed */
2369
2370 hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
2371 sizeof(cp), &cp);
2372 }
2373
2374unlock:
2375 hci_dev_unlock(hdev);
2376}
2377
2378static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
2379{
2380 struct hci_ev_io_capa_reply *ev = (void *) skb->data;
2381 struct hci_conn *conn;
2382
2383 BT_DBG("%s", hdev->name);
2384
2385 hci_dev_lock(hdev);
2386
2387 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2388 if (!conn)
2389 goto unlock;
2390
2391 hci_conn_hold(conn);
2392
2393 conn->remote_cap = ev->capability;
2394 conn->remote_oob = ev->oob_data;
2395 conn->remote_auth = ev->authentication;
2396
2397unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002398 hci_dev_unlock(hdev);
2399}
2400
Johan Hedberga5c29682011-02-19 12:05:57 -03002401static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2402 struct sk_buff *skb)
2403{
2404 struct hci_ev_user_confirm_req *ev = (void *) skb->data;
2405
2406 BT_DBG("%s", hdev->name);
2407
2408 hci_dev_lock(hdev);
2409
2410 if (test_bit(HCI_MGMT, &hdev->flags))
2411 mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
2412
2413 hci_dev_unlock(hdev);
2414}
2415
Marcel Holtmann04936842008-07-14 20:13:48 +02002416static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2417{
2418 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
2419 struct hci_conn *conn;
2420
2421 BT_DBG("%s", hdev->name);
2422
2423 hci_dev_lock(hdev);
2424
2425 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
Johan Hedberg2a611692011-02-19 12:06:00 -03002426 if (!conn)
2427 goto unlock;
Marcel Holtmann04936842008-07-14 20:13:48 +02002428
Johan Hedberg2a611692011-02-19 12:06:00 -03002429 /* To avoid duplicate auth_failed events to user space we check
2430 * the HCI_CONN_AUTH_PEND flag which will be set if we
2431 * initiated the authentication. A traditional auth_complete
2432 * event gets always produced as initiator and is also mapped to
2433 * the mgmt_auth_failed event */
2434 if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2435 mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
2436
2437 hci_conn_put(conn);
2438
2439unlock:
Marcel Holtmann04936842008-07-14 20:13:48 +02002440 hci_dev_unlock(hdev);
2441}
2442
Marcel Holtmann41a96212008-07-14 20:13:48 +02002443static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2444{
2445 struct hci_ev_remote_host_features *ev = (void *) skb->data;
2446 struct inquiry_entry *ie;
2447
2448 BT_DBG("%s", hdev->name);
2449
2450 hci_dev_lock(hdev);
2451
Andrei Emeltchenkocc11b9c2010-11-22 13:21:37 +02002452 ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2453 if (ie)
Marcel Holtmann41a96212008-07-14 20:13:48 +02002454 ie->data.ssp_mode = (ev->features[0] & 0x01);
2455
2456 hci_dev_unlock(hdev);
2457}
2458
Ville Tervofcd89c02011-02-10 22:38:47 -03002459static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2460{
2461 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2462 struct hci_conn *conn;
2463
2464 BT_DBG("%s status %d", hdev->name, ev->status);
2465
2466 hci_dev_lock(hdev);
2467
2468 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
Ville Tervob62f3282011-02-10 22:38:50 -03002469 if (!conn) {
2470 conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2471 if (!conn) {
2472 BT_ERR("No memory for new connection");
2473 hci_dev_unlock(hdev);
2474 return;
2475 }
2476 }
Ville Tervofcd89c02011-02-10 22:38:47 -03002477
2478 if (ev->status) {
2479 hci_proto_connect_cfm(conn, ev->status);
2480 conn->state = BT_CLOSED;
2481 hci_conn_del(conn);
2482 goto unlock;
2483 }
2484
2485 conn->handle = __le16_to_cpu(ev->handle);
2486 conn->state = BT_CONNECTED;
2487
2488 hci_conn_hold_device(conn);
2489 hci_conn_add_sysfs(conn);
2490
2491 hci_proto_connect_cfm(conn, ev->status);
2492
2493unlock:
2494 hci_dev_unlock(hdev);
2495}
2496
2497static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2498{
2499 struct hci_ev_le_meta *le_ev = (void *) skb->data;
2500
2501 skb_pull(skb, sizeof(*le_ev));
2502
2503 switch (le_ev->subevent) {
2504 case HCI_EV_LE_CONN_COMPLETE:
2505 hci_le_conn_complete_evt(hdev, skb);
2506 break;
2507
2508 default:
2509 break;
2510 }
2511}
2512
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
2514{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002515 struct hci_event_hdr *hdr = (void *) skb->data;
2516 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
2518 skb_pull(skb, HCI_EVENT_HDR_SIZE);
2519
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002520 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 case HCI_EV_INQUIRY_COMPLETE:
2522 hci_inquiry_complete_evt(hdev, skb);
2523 break;
2524
2525 case HCI_EV_INQUIRY_RESULT:
2526 hci_inquiry_result_evt(hdev, skb);
2527 break;
2528
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002529 case HCI_EV_CONN_COMPLETE:
2530 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02002531 break;
2532
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 case HCI_EV_CONN_REQUEST:
2534 hci_conn_request_evt(hdev, skb);
2535 break;
2536
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 case HCI_EV_DISCONN_COMPLETE:
2538 hci_disconn_complete_evt(hdev, skb);
2539 break;
2540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 case HCI_EV_AUTH_COMPLETE:
2542 hci_auth_complete_evt(hdev, skb);
2543 break;
2544
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002545 case HCI_EV_REMOTE_NAME:
2546 hci_remote_name_evt(hdev, skb);
2547 break;
2548
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 case HCI_EV_ENCRYPT_CHANGE:
2550 hci_encrypt_change_evt(hdev, skb);
2551 break;
2552
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002553 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2554 hci_change_link_key_complete_evt(hdev, skb);
2555 break;
2556
2557 case HCI_EV_REMOTE_FEATURES:
2558 hci_remote_features_evt(hdev, skb);
2559 break;
2560
2561 case HCI_EV_REMOTE_VERSION:
2562 hci_remote_version_evt(hdev, skb);
2563 break;
2564
2565 case HCI_EV_QOS_SETUP_COMPLETE:
2566 hci_qos_setup_complete_evt(hdev, skb);
2567 break;
2568
2569 case HCI_EV_CMD_COMPLETE:
2570 hci_cmd_complete_evt(hdev, skb);
2571 break;
2572
2573 case HCI_EV_CMD_STATUS:
2574 hci_cmd_status_evt(hdev, skb);
2575 break;
2576
2577 case HCI_EV_ROLE_CHANGE:
2578 hci_role_change_evt(hdev, skb);
2579 break;
2580
2581 case HCI_EV_NUM_COMP_PKTS:
2582 hci_num_comp_pkts_evt(hdev, skb);
2583 break;
2584
2585 case HCI_EV_MODE_CHANGE:
2586 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 break;
2588
2589 case HCI_EV_PIN_CODE_REQ:
2590 hci_pin_code_request_evt(hdev, skb);
2591 break;
2592
2593 case HCI_EV_LINK_KEY_REQ:
2594 hci_link_key_request_evt(hdev, skb);
2595 break;
2596
2597 case HCI_EV_LINK_KEY_NOTIFY:
2598 hci_link_key_notify_evt(hdev, skb);
2599 break;
2600
2601 case HCI_EV_CLOCK_OFFSET:
2602 hci_clock_offset_evt(hdev, skb);
2603 break;
2604
Marcel Holtmanna8746412008-07-14 20:13:46 +02002605 case HCI_EV_PKT_TYPE_CHANGE:
2606 hci_pkt_type_change_evt(hdev, skb);
2607 break;
2608
Marcel Holtmann85a1e932005-08-09 20:28:02 -07002609 case HCI_EV_PSCAN_REP_MODE:
2610 hci_pscan_rep_mode_evt(hdev, skb);
2611 break;
2612
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002613 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
2614 hci_inquiry_result_with_rssi_evt(hdev, skb);
2615 break;
2616
2617 case HCI_EV_REMOTE_EXT_FEATURES:
2618 hci_remote_ext_features_evt(hdev, skb);
2619 break;
2620
2621 case HCI_EV_SYNC_CONN_COMPLETE:
2622 hci_sync_conn_complete_evt(hdev, skb);
2623 break;
2624
2625 case HCI_EV_SYNC_CONN_CHANGED:
2626 hci_sync_conn_changed_evt(hdev, skb);
2627 break;
2628
Marcel Holtmann04837f62006-07-03 10:02:33 +02002629 case HCI_EV_SNIFF_SUBRATE:
2630 hci_sniff_subrate_evt(hdev, skb);
2631 break;
2632
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002633 case HCI_EV_EXTENDED_INQUIRY_RESULT:
2634 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 break;
2636
Marcel Holtmann04936842008-07-14 20:13:48 +02002637 case HCI_EV_IO_CAPA_REQUEST:
2638 hci_io_capa_request_evt(hdev, skb);
2639 break;
2640
Johan Hedberg03b555e2011-01-04 15:40:05 +02002641 case HCI_EV_IO_CAPA_REPLY:
2642 hci_io_capa_reply_evt(hdev, skb);
2643 break;
2644
Johan Hedberga5c29682011-02-19 12:05:57 -03002645 case HCI_EV_USER_CONFIRM_REQUEST:
2646 hci_user_confirm_request_evt(hdev, skb);
2647 break;
2648
Marcel Holtmann04936842008-07-14 20:13:48 +02002649 case HCI_EV_SIMPLE_PAIR_COMPLETE:
2650 hci_simple_pair_complete_evt(hdev, skb);
2651 break;
2652
Marcel Holtmann41a96212008-07-14 20:13:48 +02002653 case HCI_EV_REMOTE_HOST_FEATURES:
2654 hci_remote_host_features_evt(hdev, skb);
2655 break;
2656
Ville Tervofcd89c02011-02-10 22:38:47 -03002657 case HCI_EV_LE_META:
2658 hci_le_meta_evt(hdev, skb);
2659 break;
2660
Marcel Holtmanna9de9242007-10-20 13:33:56 +02002661 default:
2662 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 break;
2664 }
2665
2666 kfree_skb(skb);
2667 hdev->stat.evt_rx++;
2668}
2669
2670/* Generate internal stack event */
2671void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
2672{
2673 struct hci_event_hdr *hdr;
2674 struct hci_ev_stack_internal *ev;
2675 struct sk_buff *skb;
2676
2677 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
2678 if (!skb)
2679 return;
2680
2681 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
2682 hdr->evt = HCI_EV_STACK_INTERNAL;
2683 hdr->plen = sizeof(*ev) + dlen;
2684
2685 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
2686 ev->type = type;
2687 memcpy(ev->data, data, dlen);
2688
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002689 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07002690 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02002691
Marcel Holtmann0d48d932005-08-09 20:30:28 -07002692 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 skb->dev = (void *) hdev;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002694 hci_send_to_sock(hdev, skb, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 kfree_skb(skb);
2696}