blob: e3e360c3c536e8d4a55521ea31ce54bcf1934726 [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
3 Copyright (C) 2000-2001 Qualcomm Incorporated
4
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>
42#include <asm/uaccess.h>
43#include <asm/unaligned.h>
44
45#include <net/bluetooth/bluetooth.h>
46#include <net/bluetooth/hci_core.h>
47
48#ifndef CONFIG_BT_HCI_CORE_DEBUG
49#undef BT_DBG
50#define BT_DBG(D...)
51#endif
52
53/* Handle HCI Event packets */
54
Marcel Holtmanna9de9242007-10-20 13:33:56 +020055static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020057 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Marcel Holtmanna9de9242007-10-20 13:33:56 +020059 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Marcel Holtmanna9de9242007-10-20 13:33:56 +020061 if (status)
62 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Marcel Holtmanna9de9242007-10-20 13:33:56 +020064 clear_bit(HCI_INQUIRY, &hdev->flags);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010065
Marcel Holtmanna9de9242007-10-20 13:33:56 +020066 hci_req_complete(hdev, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +010067
Marcel Holtmanna9de9242007-10-20 13:33:56 +020068 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069}
70
Marcel Holtmanna9de9242007-10-20 13:33:56 +020071static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
Marcel Holtmanna9de9242007-10-20 13:33:56 +020073 __u8 status = *((__u8 *) skb->data);
74
75 BT_DBG("%s status 0x%x", hdev->name, status);
76
77 if (status)
78 return;
79
80 clear_bit(HCI_INQUIRY, &hdev->flags);
81
82 hci_conn_check_pending(hdev);
83}
84
85static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
86{
87 BT_DBG("%s", hdev->name);
88}
89
90static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
91{
92 struct hci_rp_role_discovery *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Marcel Holtmanna9de9242007-10-20 13:33:56 +020095 BT_DBG("%s status 0x%x", hdev->name, rp->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Marcel Holtmanna9de9242007-10-20 13:33:56 +020097 if (rp->status)
98 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200100 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200102 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
103 if (conn) {
104 if (rp->role)
105 conn->link_mode &= ~HCI_LM_MASTER;
106 else
107 conn->link_mode |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200109
110 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}
112
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200113static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
114{
115 struct hci_rp_read_link_policy *rp = (void *) skb->data;
116 struct hci_conn *conn;
117
118 BT_DBG("%s status 0x%x", hdev->name, rp->status);
119
120 if (rp->status)
121 return;
122
123 hci_dev_lock(hdev);
124
125 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
126 if (conn)
127 conn->link_policy = __le16_to_cpu(rp->policy);
128
129 hci_dev_unlock(hdev);
130}
131
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200132static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200134 struct hci_rp_write_link_policy *rp = (void *) skb->data;
135 struct hci_conn *conn;
136 void *sent;
137
138 BT_DBG("%s status 0x%x", hdev->name, rp->status);
139
140 if (rp->status)
141 return;
142
143 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
144 if (!sent)
145 return;
146
147 hci_dev_lock(hdev);
148
149 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200150 if (conn)
Harvey Harrison83985312008-05-02 16:25:46 -0700151 conn->link_policy = get_unaligned_le16(sent + 2);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200152
153 hci_dev_unlock(hdev);
154}
155
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200156static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
157{
158 struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
159
160 BT_DBG("%s status 0x%x", hdev->name, rp->status);
161
162 if (rp->status)
163 return;
164
165 hdev->link_policy = __le16_to_cpu(rp->policy);
166}
167
168static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
169{
170 __u8 status = *((__u8 *) skb->data);
171 void *sent;
172
173 BT_DBG("%s status 0x%x", hdev->name, status);
174
175 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
176 if (!sent)
177 return;
178
179 if (!status)
180 hdev->link_policy = get_unaligned_le16(sent);
181
182 hci_req_complete(hdev, status);
183}
184
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200185static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
186{
187 __u8 status = *((__u8 *) skb->data);
188
189 BT_DBG("%s status 0x%x", hdev->name, status);
190
191 hci_req_complete(hdev, status);
192}
193
194static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
195{
196 __u8 status = *((__u8 *) skb->data);
197 void *sent;
198
199 BT_DBG("%s status 0x%x", hdev->name, status);
200
Marcel Holtmannf383f272008-07-14 20:13:47 +0200201 if (status)
202 return;
203
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200204 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
205 if (!sent)
206 return;
207
Marcel Holtmannf383f272008-07-14 20:13:47 +0200208 memcpy(hdev->dev_name, sent, 248);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200209}
210
211static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
212{
213 struct hci_rp_read_local_name *rp = (void *) skb->data;
214
215 BT_DBG("%s status 0x%x", hdev->name, rp->status);
216
217 if (rp->status)
218 return;
219
220 memcpy(hdev->dev_name, rp->name, 248);
221}
222
223static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
224{
225 __u8 status = *((__u8 *) skb->data);
226 void *sent;
227
228 BT_DBG("%s status 0x%x", hdev->name, status);
229
230 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
231 if (!sent)
232 return;
233
234 if (!status) {
235 __u8 param = *((__u8 *) sent);
236
237 if (param == AUTH_ENABLED)
238 set_bit(HCI_AUTH, &hdev->flags);
239 else
240 clear_bit(HCI_AUTH, &hdev->flags);
241 }
242
243 hci_req_complete(hdev, status);
244}
245
246static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
247{
248 __u8 status = *((__u8 *) skb->data);
249 void *sent;
250
251 BT_DBG("%s status 0x%x", hdev->name, status);
252
253 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
254 if (!sent)
255 return;
256
257 if (!status) {
258 __u8 param = *((__u8 *) sent);
259
260 if (param)
261 set_bit(HCI_ENCRYPT, &hdev->flags);
262 else
263 clear_bit(HCI_ENCRYPT, &hdev->flags);
264 }
265
266 hci_req_complete(hdev, status);
267}
268
269static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
270{
271 __u8 status = *((__u8 *) skb->data);
272 void *sent;
273
274 BT_DBG("%s status 0x%x", hdev->name, status);
275
276 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
277 if (!sent)
278 return;
279
280 if (!status) {
281 __u8 param = *((__u8 *) sent);
282
283 clear_bit(HCI_PSCAN, &hdev->flags);
284 clear_bit(HCI_ISCAN, &hdev->flags);
285
286 if (param & SCAN_INQUIRY)
287 set_bit(HCI_ISCAN, &hdev->flags);
288
289 if (param & SCAN_PAGE)
290 set_bit(HCI_PSCAN, &hdev->flags);
291 }
292
293 hci_req_complete(hdev, status);
294}
295
296static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
297{
298 struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
299
300 BT_DBG("%s status 0x%x", hdev->name, rp->status);
301
302 if (rp->status)
303 return;
304
305 memcpy(hdev->dev_class, rp->dev_class, 3);
306
307 BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
308 hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
309}
310
311static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
312{
313 __u8 status = *((__u8 *) skb->data);
314 void *sent;
315
316 BT_DBG("%s status 0x%x", hdev->name, status);
317
Marcel Holtmannf383f272008-07-14 20:13:47 +0200318 if (status)
319 return;
320
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200321 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
322 if (!sent)
323 return;
324
Marcel Holtmannf383f272008-07-14 20:13:47 +0200325 memcpy(hdev->dev_class, sent, 3);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200326}
327
328static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
329{
330 struct hci_rp_read_voice_setting *rp = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 __u16 setting;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200332
333 BT_DBG("%s status 0x%x", hdev->name, rp->status);
334
335 if (rp->status)
336 return;
337
338 setting = __le16_to_cpu(rp->voice_setting);
339
Marcel Holtmannf383f272008-07-14 20:13:47 +0200340 if (hdev->voice_setting == setting)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200341 return;
342
343 hdev->voice_setting = setting;
344
345 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
346
347 if (hdev->notify) {
348 tasklet_disable(&hdev->tx_task);
349 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
350 tasklet_enable(&hdev->tx_task);
351 }
352}
353
354static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
355{
356 __u8 status = *((__u8 *) skb->data);
Marcel Holtmannf383f272008-07-14 20:13:47 +0200357 __u16 setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 void *sent;
359
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200360 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Marcel Holtmannf383f272008-07-14 20:13:47 +0200362 if (status)
363 return;
364
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200365 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
366 if (!sent)
367 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Marcel Holtmannf383f272008-07-14 20:13:47 +0200369 setting = get_unaligned_le16(sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Marcel Holtmannf383f272008-07-14 20:13:47 +0200371 if (hdev->voice_setting == setting)
372 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Marcel Holtmannf383f272008-07-14 20:13:47 +0200374 hdev->voice_setting = setting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Marcel Holtmannf383f272008-07-14 20:13:47 +0200376 BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
377
378 if (hdev->notify) {
379 tasklet_disable(&hdev->tx_task);
380 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
381 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 }
383}
384
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200385static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200387 __u8 status = *((__u8 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200389 BT_DBG("%s status 0x%x", hdev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200391 hci_req_complete(hdev, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392}
393
Marcel Holtmann333140b2008-07-14 20:13:48 +0200394static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
395{
396 struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
397
398 BT_DBG("%s status 0x%x", hdev->name, rp->status);
399
400 if (rp->status)
401 return;
402
403 hdev->ssp_mode = rp->mode;
404}
405
406static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
407{
408 __u8 status = *((__u8 *) skb->data);
409 void *sent;
410
411 BT_DBG("%s status 0x%x", hdev->name, status);
412
413 if (status)
414 return;
415
416 sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
417 if (!sent)
418 return;
419
420 hdev->ssp_mode = *((__u8 *) sent);
421}
422
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200423static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
424{
425 struct hci_rp_read_local_version *rp = (void *) skb->data;
426
427 BT_DBG("%s status 0x%x", hdev->name, rp->status);
428
429 if (rp->status)
430 return;
431
432 hdev->hci_ver = rp->hci_ver;
Marcel Holtmanne4e8e372008-07-14 20:13:47 +0200433 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
434 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200435
436 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
437 hdev->manufacturer,
438 hdev->hci_ver, hdev->hci_rev);
439}
440
441static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
442{
443 struct hci_rp_read_local_commands *rp = (void *) skb->data;
444
445 BT_DBG("%s status 0x%x", hdev->name, rp->status);
446
447 if (rp->status)
448 return;
449
450 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
451}
452
453static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
454{
455 struct hci_rp_read_local_features *rp = (void *) skb->data;
456
457 BT_DBG("%s status 0x%x", hdev->name, rp->status);
458
459 if (rp->status)
460 return;
461
462 memcpy(hdev->features, rp->features, 8);
463
464 /* Adjust default settings according to features
465 * supported by device. */
466
467 if (hdev->features[0] & LMP_3SLOT)
468 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
469
470 if (hdev->features[0] & LMP_5SLOT)
471 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
472
473 if (hdev->features[1] & LMP_HV2) {
474 hdev->pkt_type |= (HCI_HV2);
475 hdev->esco_type |= (ESCO_HV2);
476 }
477
478 if (hdev->features[1] & LMP_HV3) {
479 hdev->pkt_type |= (HCI_HV3);
480 hdev->esco_type |= (ESCO_HV3);
481 }
482
483 if (hdev->features[3] & LMP_ESCO)
484 hdev->esco_type |= (ESCO_EV3);
485
486 if (hdev->features[4] & LMP_EV4)
487 hdev->esco_type |= (ESCO_EV4);
488
489 if (hdev->features[4] & LMP_EV5)
490 hdev->esco_type |= (ESCO_EV5);
491
492 BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
493 hdev->features[0], hdev->features[1],
494 hdev->features[2], hdev->features[3],
495 hdev->features[4], hdev->features[5],
496 hdev->features[6], hdev->features[7]);
497}
498
499static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
500{
501 struct hci_rp_read_buffer_size *rp = (void *) skb->data;
502
503 BT_DBG("%s status 0x%x", hdev->name, rp->status);
504
505 if (rp->status)
506 return;
507
508 hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
509 hdev->sco_mtu = rp->sco_mtu;
510 hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
511 hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
512
513 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
514 hdev->sco_mtu = 64;
515 hdev->sco_pkts = 8;
516 }
517
518 hdev->acl_cnt = hdev->acl_pkts;
519 hdev->sco_cnt = hdev->sco_pkts;
520
521 BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
522 hdev->acl_mtu, hdev->acl_pkts,
523 hdev->sco_mtu, hdev->sco_pkts);
524}
525
526static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
527{
528 struct hci_rp_read_bd_addr *rp = (void *) skb->data;
529
530 BT_DBG("%s status 0x%x", hdev->name, rp->status);
531
532 if (!rp->status)
533 bacpy(&hdev->bdaddr, &rp->bdaddr);
534
535 hci_req_complete(hdev, rp->status);
536}
537
538static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
539{
540 BT_DBG("%s status 0x%x", hdev->name, status);
541
542 if (status) {
543 hci_req_complete(hdev, status);
544
545 hci_conn_check_pending(hdev);
546 } else
547 set_bit(HCI_INQUIRY, &hdev->flags);
548}
549
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
551{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200552 struct hci_cp_create_conn *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200555 BT_DBG("%s status 0x%x", hdev->name, status);
556
557 cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 if (!cp)
559 return;
560
561 hci_dev_lock(hdev);
562
563 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
564
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200565 BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
567 if (status) {
568 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200569 if (status != 0x0c || conn->attempt > 2) {
570 conn->state = BT_CLOSED;
571 hci_proto_connect_cfm(conn, status);
572 hci_conn_del(conn);
573 } else
574 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 }
576 } else {
577 if (!conn) {
578 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
579 if (conn) {
580 conn->out = 1;
581 conn->link_mode |= HCI_LM_MASTER;
582 } else
583 BT_ERR("No memmory for new connection");
584 }
585 }
586
587 hci_dev_unlock(hdev);
588}
589
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200590static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200592 struct hci_cp_add_sco *cp;
593 struct hci_conn *acl, *sco;
594 __u16 handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200596 BT_DBG("%s status 0x%x", hdev->name, status);
597
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200598 if (!status)
599 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200601 cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
602 if (!cp)
603 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200605 handle = __le16_to_cpu(cp->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200607 BT_DBG("%s handle %d", hdev->name, handle);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100608
609 hci_dev_lock(hdev);
610
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200611 acl = hci_conn_hash_lookup_handle(hdev, handle);
612 if (acl && (sco = acl->link)) {
613 sco->state = BT_CLOSED;
614
615 hci_proto_connect_cfm(sco, status);
616 hci_conn_del(sco);
617 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100618
619 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620}
621
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200622static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
623{
624 BT_DBG("%s status 0x%x", hdev->name, status);
625}
626
Marcel Holtmann769be972008-07-14 20:13:49 +0200627static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
628{
629 struct hci_cp_read_remote_features *cp;
630 struct hci_conn *conn;
631
632 BT_DBG("%s status 0x%x", hdev->name, status);
633
634 if (!status)
635 return;
636
637 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
638 if (!cp)
639 return;
640
641 hci_dev_lock(hdev);
642
643 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
644 if (conn) {
645 if (conn->state == BT_CONFIG) {
646 conn->state = BT_CONNECTED;
647 hci_proto_connect_cfm(conn, status);
648 hci_conn_put(conn);
649 }
650 }
651
652 hci_dev_unlock(hdev);
653}
654
655static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
656{
657 struct hci_cp_read_remote_ext_features *cp;
658 struct hci_conn *conn;
659
660 BT_DBG("%s status 0x%x", hdev->name, status);
661
662 if (!status)
663 return;
664
665 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
666 if (!cp)
667 return;
668
669 hci_dev_lock(hdev);
670
671 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
672 if (conn) {
673 if (conn->state == BT_CONFIG) {
674 conn->state = BT_CONNECTED;
675 hci_proto_connect_cfm(conn, status);
676 hci_conn_put(conn);
677 }
678 }
679
680 hci_dev_unlock(hdev);
681}
682
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200683static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
684{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200685 struct hci_cp_setup_sync_conn *cp;
686 struct hci_conn *acl, *sco;
687 __u16 handle;
688
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200689 BT_DBG("%s status 0x%x", hdev->name, status);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200690
691 if (!status)
692 return;
693
694 cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
695 if (!cp)
696 return;
697
698 handle = __le16_to_cpu(cp->handle);
699
700 BT_DBG("%s handle %d", hdev->name, handle);
701
702 hci_dev_lock(hdev);
703
704 acl = hci_conn_hash_lookup_handle(hdev, handle);
705 if (acl && (sco = acl->link)) {
706 sco->state = BT_CLOSED;
707
708 hci_proto_connect_cfm(sco, status);
709 hci_conn_del(sco);
710 }
711
712 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200713}
714
715static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
716{
717 struct hci_cp_sniff_mode *cp;
718 struct hci_conn *conn;
719
720 BT_DBG("%s status 0x%x", hdev->name, status);
721
722 if (!status)
723 return;
724
725 cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
726 if (!cp)
727 return;
728
729 hci_dev_lock(hdev);
730
731 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
732 if (conn)
733 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
734
735 hci_dev_unlock(hdev);
736}
737
738static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
739{
740 struct hci_cp_exit_sniff_mode *cp;
741 struct hci_conn *conn;
742
743 BT_DBG("%s status 0x%x", hdev->name, status);
744
745 if (!status)
746 return;
747
748 cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
749 if (!cp)
750 return;
751
752 hci_dev_lock(hdev);
753
754 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
755 if (conn)
756 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
757
758 hci_dev_unlock(hdev);
759}
760
761static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
762{
763 __u8 status = *((__u8 *) skb->data);
764
765 BT_DBG("%s status %d", hdev->name, status);
766
767 clear_bit(HCI_INQUIRY, &hdev->flags);
768
769 hci_req_complete(hdev, status);
770
771 hci_conn_check_pending(hdev);
772}
773
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
775{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700776 struct inquiry_data data;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200777 struct inquiry_info *info = (void *) (skb->data + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 int num_rsp = *((__u8 *) skb->data);
779
780 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
781
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700782 if (!num_rsp)
783 return;
784
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 for (; num_rsp; num_rsp--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 bacpy(&data.bdaddr, &info->bdaddr);
789 data.pscan_rep_mode = info->pscan_rep_mode;
790 data.pscan_period_mode = info->pscan_period_mode;
791 data.pscan_mode = info->pscan_mode;
792 memcpy(data.dev_class, info->dev_class, 3);
793 data.clock_offset = info->clock_offset;
794 data.rssi = 0x00;
Marcel Holtmann41a96212008-07-14 20:13:48 +0200795 data.ssp_mode = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 info++;
797 hci_inquiry_cache_update(hdev, &data);
798 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 hci_dev_unlock(hdev);
801}
802
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200803static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200805 struct hci_ev_conn_complete *ev = (void *) skb->data;
806 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200808 BT_DBG("%s", hdev->name);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700811
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200812 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
813 if (!conn)
814 goto unlock;
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700815
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200816 if (!ev->status) {
817 conn->handle = __le16_to_cpu(ev->handle);
Marcel Holtmann769be972008-07-14 20:13:49 +0200818
819 if (conn->type == ACL_LINK) {
820 conn->state = BT_CONFIG;
821 hci_conn_hold(conn);
822 } else
823 conn->state = BT_CONNECTED;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200824
825 if (test_bit(HCI_AUTH, &hdev->flags))
826 conn->link_mode |= HCI_LM_AUTH;
827
828 if (test_bit(HCI_ENCRYPT, &hdev->flags))
829 conn->link_mode |= HCI_LM_ENCRYPT;
830
831 /* Get remote features */
832 if (conn->type == ACL_LINK) {
833 struct hci_cp_read_remote_features cp;
834 cp.handle = ev->handle;
Marcel Holtmann769be972008-07-14 20:13:49 +0200835 hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
836 sizeof(cp), &cp);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700837 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700838
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200839 /* Set packet type for incoming connection */
Marcel Holtmanna8746412008-07-14 20:13:46 +0200840 if (!conn->out && hdev->hci_ver < 3) {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200841 struct hci_cp_change_conn_ptype cp;
842 cp.handle = ev->handle;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200843 cp.pkt_type = cpu_to_le16(conn->pkt_type);
844 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
845 sizeof(cp), &cp);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200846 }
847 } else
848 conn->state = BT_CLOSED;
849
850 if (conn->type == ACL_LINK) {
851 struct hci_conn *sco = conn->link;
852 if (sco) {
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200853 if (!ev->status) {
854 if (lmp_esco_capable(hdev))
855 hci_setup_sync(sco, conn->handle);
856 else
857 hci_add_sco(sco, conn->handle);
858 } else {
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200859 hci_proto_connect_cfm(sco, ev->status);
860 hci_conn_del(sco);
861 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700864
Marcel Holtmann769be972008-07-14 20:13:49 +0200865 if (ev->status) {
866 hci_proto_connect_cfm(conn, ev->status);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200867 hci_conn_del(conn);
Marcel Holtmann769be972008-07-14 20:13:49 +0200868 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200869
870unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200872
873 hci_conn_check_pending(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
877{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200878 struct hci_ev_conn_request *ev = (void *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 int mask = hdev->link_mode;
880
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200881 BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
882 batostr(&ev->bdaddr), ev->link_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
885
886 if (mask & HCI_LM_ACCEPT) {
887 /* Connection accepted */
Marcel Holtmannc7bdd502008-07-14 20:13:47 +0200888 struct inquiry_entry *ie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890
891 hci_dev_lock(hdev);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200892
Marcel Holtmannc7bdd502008-07-14 20:13:47 +0200893 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
894 memcpy(ie->data.dev_class, ev->dev_class, 3);
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
897 if (!conn) {
898 if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
899 BT_ERR("No memmory for new connection");
900 hci_dev_unlock(hdev);
901 return;
902 }
903 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 memcpy(conn->dev_class, ev->dev_class, 3);
906 conn->state = BT_CONNECT;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 hci_dev_unlock(hdev);
909
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200910 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
911 struct hci_cp_accept_conn_req cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200913 bacpy(&cp.bdaddr, &ev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200915 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
916 cp.role = 0x00; /* Become master */
917 else
918 cp.role = 0x01; /* Remain slave */
919
920 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
921 sizeof(cp), &cp);
922 } else {
923 struct hci_cp_accept_sync_conn_req cp;
924
925 bacpy(&cp.bdaddr, &ev->bdaddr);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200926 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200927
928 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
929 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
930 cp.max_latency = cpu_to_le16(0xffff);
931 cp.content_format = cpu_to_le16(hdev->voice_setting);
932 cp.retrans_effort = 0xff;
933
934 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
935 sizeof(cp), &cp);
936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 } else {
938 /* Connection rejected */
939 struct hci_cp_reject_conn_req cp;
940
941 bacpy(&cp.bdaddr, &ev->bdaddr);
942 cp.reason = 0x0f;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200943 hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 }
945}
946
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
948{
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200949 struct hci_ev_disconn_complete *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200950 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
952 BT_DBG("%s status %d", hdev->name, ev->status);
953
954 if (ev->status)
955 return;
956
957 hci_dev_lock(hdev);
958
Marcel Holtmann04837f62006-07-03 10:02:33 +0200959 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 if (conn) {
961 conn->state = BT_CLOSED;
962 hci_proto_disconn_ind(conn, ev->reason);
963 hci_conn_del(conn);
964 }
965
966 hci_dev_unlock(hdev);
967}
968
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200969static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
970{
971 struct hci_ev_auth_complete *ev = (void *) skb->data;
972 struct hci_conn *conn;
973
974 BT_DBG("%s status %d", hdev->name, ev->status);
975
976 hci_dev_lock(hdev);
977
978 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
979 if (conn) {
980 if (!ev->status)
981 conn->link_mode |= HCI_LM_AUTH;
982
983 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
984
985 hci_auth_cfm(conn, ev->status);
986
987 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
988 if (!ev->status) {
989 struct hci_cp_set_conn_encrypt cp;
990 cp.handle = cpu_to_le16(conn->handle);
991 cp.encrypt = 1;
992 hci_send_cmd(conn->hdev,
993 HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp);
994 } else {
995 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
996 hci_encrypt_cfm(conn, ev->status, 0x00);
997 }
998 }
999 }
1000
1001 hci_dev_unlock(hdev);
1002}
1003
1004static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1005{
1006 BT_DBG("%s", hdev->name);
1007
1008 hci_conn_check_pending(hdev);
1009}
1010
1011static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1012{
1013 struct hci_ev_encrypt_change *ev = (void *) skb->data;
1014 struct hci_conn *conn;
1015
1016 BT_DBG("%s status %d", hdev->name, ev->status);
1017
1018 hci_dev_lock(hdev);
1019
1020 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1021 if (conn) {
1022 if (!ev->status) {
Marcel Holtmannae293192008-07-14 20:13:45 +02001023 if (ev->encrypt) {
1024 /* Encryption implies authentication */
1025 conn->link_mode |= HCI_LM_AUTH;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001026 conn->link_mode |= HCI_LM_ENCRYPT;
Marcel Holtmannae293192008-07-14 20:13:45 +02001027 } else
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001028 conn->link_mode &= ~HCI_LM_ENCRYPT;
1029 }
1030
1031 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1032
1033 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1034 }
1035
1036 hci_dev_unlock(hdev);
1037}
1038
1039static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1040{
1041 struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1042 struct hci_conn *conn;
1043
1044 BT_DBG("%s status %d", hdev->name, ev->status);
1045
1046 hci_dev_lock(hdev);
1047
1048 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1049 if (conn) {
1050 if (!ev->status)
1051 conn->link_mode |= HCI_LM_SECURE;
1052
1053 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1054
1055 hci_key_change_cfm(conn, ev->status);
1056 }
1057
1058 hci_dev_unlock(hdev);
1059}
1060
1061static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1062{
1063 struct hci_ev_remote_features *ev = (void *) skb->data;
1064 struct hci_conn *conn;
1065
1066 BT_DBG("%s status %d", hdev->name, ev->status);
1067
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001068 hci_dev_lock(hdev);
1069
1070 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Marcel Holtmann769be972008-07-14 20:13:49 +02001071 if (conn) {
1072 if (!ev->status)
1073 memcpy(conn->features, ev->features, 8);
1074
1075 if (conn->state == BT_CONFIG) {
1076 if (!ev->status && lmp_ssp_capable(hdev) &&
1077 lmp_ssp_capable(conn)) {
1078 struct hci_cp_read_remote_ext_features cp;
1079 cp.handle = ev->handle;
1080 cp.page = 0x01;
1081 hci_send_cmd(hdev,
1082 HCI_OP_READ_REMOTE_EXT_FEATURES,
1083 sizeof(cp), &cp);
1084 } else {
1085 conn->state = BT_CONNECTED;
1086 hci_proto_connect_cfm(conn, ev->status);
1087 hci_conn_put(conn);
1088 }
1089 }
1090 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001091
1092 hci_dev_unlock(hdev);
1093}
1094
1095static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1096{
1097 BT_DBG("%s", hdev->name);
1098}
1099
1100static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1101{
1102 BT_DBG("%s", hdev->name);
1103}
1104
1105static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1106{
1107 struct hci_ev_cmd_complete *ev = (void *) skb->data;
1108 __u16 opcode;
1109
1110 skb_pull(skb, sizeof(*ev));
1111
1112 opcode = __le16_to_cpu(ev->opcode);
1113
1114 switch (opcode) {
1115 case HCI_OP_INQUIRY_CANCEL:
1116 hci_cc_inquiry_cancel(hdev, skb);
1117 break;
1118
1119 case HCI_OP_EXIT_PERIODIC_INQ:
1120 hci_cc_exit_periodic_inq(hdev, skb);
1121 break;
1122
1123 case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1124 hci_cc_remote_name_req_cancel(hdev, skb);
1125 break;
1126
1127 case HCI_OP_ROLE_DISCOVERY:
1128 hci_cc_role_discovery(hdev, skb);
1129 break;
1130
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001131 case HCI_OP_READ_LINK_POLICY:
1132 hci_cc_read_link_policy(hdev, skb);
1133 break;
1134
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001135 case HCI_OP_WRITE_LINK_POLICY:
1136 hci_cc_write_link_policy(hdev, skb);
1137 break;
1138
Marcel Holtmanne4e8e372008-07-14 20:13:47 +02001139 case HCI_OP_READ_DEF_LINK_POLICY:
1140 hci_cc_read_def_link_policy(hdev, skb);
1141 break;
1142
1143 case HCI_OP_WRITE_DEF_LINK_POLICY:
1144 hci_cc_write_def_link_policy(hdev, skb);
1145 break;
1146
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001147 case HCI_OP_RESET:
1148 hci_cc_reset(hdev, skb);
1149 break;
1150
1151 case HCI_OP_WRITE_LOCAL_NAME:
1152 hci_cc_write_local_name(hdev, skb);
1153 break;
1154
1155 case HCI_OP_READ_LOCAL_NAME:
1156 hci_cc_read_local_name(hdev, skb);
1157 break;
1158
1159 case HCI_OP_WRITE_AUTH_ENABLE:
1160 hci_cc_write_auth_enable(hdev, skb);
1161 break;
1162
1163 case HCI_OP_WRITE_ENCRYPT_MODE:
1164 hci_cc_write_encrypt_mode(hdev, skb);
1165 break;
1166
1167 case HCI_OP_WRITE_SCAN_ENABLE:
1168 hci_cc_write_scan_enable(hdev, skb);
1169 break;
1170
1171 case HCI_OP_READ_CLASS_OF_DEV:
1172 hci_cc_read_class_of_dev(hdev, skb);
1173 break;
1174
1175 case HCI_OP_WRITE_CLASS_OF_DEV:
1176 hci_cc_write_class_of_dev(hdev, skb);
1177 break;
1178
1179 case HCI_OP_READ_VOICE_SETTING:
1180 hci_cc_read_voice_setting(hdev, skb);
1181 break;
1182
1183 case HCI_OP_WRITE_VOICE_SETTING:
1184 hci_cc_write_voice_setting(hdev, skb);
1185 break;
1186
1187 case HCI_OP_HOST_BUFFER_SIZE:
1188 hci_cc_host_buffer_size(hdev, skb);
1189 break;
1190
Marcel Holtmann333140b2008-07-14 20:13:48 +02001191 case HCI_OP_READ_SSP_MODE:
1192 hci_cc_read_ssp_mode(hdev, skb);
1193 break;
1194
1195 case HCI_OP_WRITE_SSP_MODE:
1196 hci_cc_write_ssp_mode(hdev, skb);
1197 break;
1198
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001199 case HCI_OP_READ_LOCAL_VERSION:
1200 hci_cc_read_local_version(hdev, skb);
1201 break;
1202
1203 case HCI_OP_READ_LOCAL_COMMANDS:
1204 hci_cc_read_local_commands(hdev, skb);
1205 break;
1206
1207 case HCI_OP_READ_LOCAL_FEATURES:
1208 hci_cc_read_local_features(hdev, skb);
1209 break;
1210
1211 case HCI_OP_READ_BUFFER_SIZE:
1212 hci_cc_read_buffer_size(hdev, skb);
1213 break;
1214
1215 case HCI_OP_READ_BD_ADDR:
1216 hci_cc_read_bd_addr(hdev, skb);
1217 break;
1218
1219 default:
1220 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1221 break;
1222 }
1223
1224 if (ev->ncmd) {
1225 atomic_set(&hdev->cmd_cnt, 1);
1226 if (!skb_queue_empty(&hdev->cmd_q))
1227 hci_sched_cmd(hdev);
1228 }
1229}
1230
1231static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1232{
1233 struct hci_ev_cmd_status *ev = (void *) skb->data;
1234 __u16 opcode;
1235
1236 skb_pull(skb, sizeof(*ev));
1237
1238 opcode = __le16_to_cpu(ev->opcode);
1239
1240 switch (opcode) {
1241 case HCI_OP_INQUIRY:
1242 hci_cs_inquiry(hdev, ev->status);
1243 break;
1244
1245 case HCI_OP_CREATE_CONN:
1246 hci_cs_create_conn(hdev, ev->status);
1247 break;
1248
1249 case HCI_OP_ADD_SCO:
1250 hci_cs_add_sco(hdev, ev->status);
1251 break;
1252
1253 case HCI_OP_REMOTE_NAME_REQ:
1254 hci_cs_remote_name_req(hdev, ev->status);
1255 break;
1256
Marcel Holtmann769be972008-07-14 20:13:49 +02001257 case HCI_OP_READ_REMOTE_FEATURES:
1258 hci_cs_read_remote_features(hdev, ev->status);
1259 break;
1260
1261 case HCI_OP_READ_REMOTE_EXT_FEATURES:
1262 hci_cs_read_remote_ext_features(hdev, ev->status);
1263 break;
1264
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001265 case HCI_OP_SETUP_SYNC_CONN:
1266 hci_cs_setup_sync_conn(hdev, ev->status);
1267 break;
1268
1269 case HCI_OP_SNIFF_MODE:
1270 hci_cs_sniff_mode(hdev, ev->status);
1271 break;
1272
1273 case HCI_OP_EXIT_SNIFF_MODE:
1274 hci_cs_exit_sniff_mode(hdev, ev->status);
1275 break;
1276
1277 default:
1278 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1279 break;
1280 }
1281
1282 if (ev->ncmd) {
1283 atomic_set(&hdev->cmd_cnt, 1);
1284 if (!skb_queue_empty(&hdev->cmd_q))
1285 hci_sched_cmd(hdev);
1286 }
1287}
1288
1289static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1290{
1291 struct hci_ev_role_change *ev = (void *) skb->data;
1292 struct hci_conn *conn;
1293
1294 BT_DBG("%s status %d", hdev->name, ev->status);
1295
1296 hci_dev_lock(hdev);
1297
1298 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1299 if (conn) {
1300 if (!ev->status) {
1301 if (ev->role)
1302 conn->link_mode &= ~HCI_LM_MASTER;
1303 else
1304 conn->link_mode |= HCI_LM_MASTER;
1305 }
1306
1307 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1308
1309 hci_role_switch_cfm(conn, ev->status, ev->role);
1310 }
1311
1312 hci_dev_unlock(hdev);
1313}
1314
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
1316{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001317 struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001318 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 int i;
1320
1321 skb_pull(skb, sizeof(*ev));
1322
1323 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
1324
1325 if (skb->len < ev->num_hndl * 4) {
1326 BT_DBG("%s bad parameters", hdev->name);
1327 return;
1328 }
1329
1330 tasklet_disable(&hdev->tx_task);
1331
Marcel Holtmann1ebb9252005-11-08 09:57:21 -08001332 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 struct hci_conn *conn;
1334 __u16 handle, count;
1335
Harvey Harrison83985312008-05-02 16:25:46 -07001336 handle = get_unaligned_le16(ptr++);
1337 count = get_unaligned_le16(ptr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
1339 conn = hci_conn_hash_lookup_handle(hdev, handle);
1340 if (conn) {
1341 conn->sent -= count;
1342
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001343 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 if ((hdev->acl_cnt += count) > hdev->acl_pkts)
1345 hdev->acl_cnt = hdev->acl_pkts;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +02001346 } else {
1347 if ((hdev->sco_cnt += count) > hdev->sco_pkts)
1348 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 }
1350 }
1351 }
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001352
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 hci_sched_tx(hdev);
1354
1355 tasklet_enable(&hdev->tx_task);
1356}
1357
Marcel Holtmann04837f62006-07-03 10:02:33 +02001358static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001360 struct hci_ev_mode_change *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001361 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363 BT_DBG("%s status %d", hdev->name, ev->status);
1364
1365 hci_dev_lock(hdev);
1366
Marcel Holtmann04837f62006-07-03 10:02:33 +02001367 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1368 if (conn) {
1369 conn->mode = ev->mode;
1370 conn->interval = __le16_to_cpu(ev->interval);
1371
1372 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
1373 if (conn->mode == HCI_CM_ACTIVE)
1374 conn->power_save = 1;
1375 else
1376 conn->power_save = 0;
1377 }
1378 }
1379
1380 hci_dev_unlock(hdev);
1381}
1382
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1384{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001385 BT_DBG("%s", hdev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386}
1387
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1389{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001390 BT_DBG("%s", hdev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391}
1392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
1394{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001395 BT_DBG("%s", hdev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396}
1397
Marcel Holtmann04837f62006-07-03 10:02:33 +02001398static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
1399{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001400 struct hci_ev_clock_offset *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001401 struct hci_conn *conn;
1402
1403 BT_DBG("%s status %d", hdev->name, ev->status);
1404
1405 hci_dev_lock(hdev);
1406
1407 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 if (conn && !ev->status) {
1409 struct inquiry_entry *ie;
1410
1411 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
1412 ie->data.clock_offset = ev->clock_offset;
1413 ie->timestamp = jiffies;
1414 }
1415 }
1416
1417 hci_dev_unlock(hdev);
1418}
1419
Marcel Holtmanna8746412008-07-14 20:13:46 +02001420static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1421{
1422 struct hci_ev_pkt_type_change *ev = (void *) skb->data;
1423 struct hci_conn *conn;
1424
1425 BT_DBG("%s status %d", hdev->name, ev->status);
1426
1427 hci_dev_lock(hdev);
1428
1429 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1430 if (conn && !ev->status)
1431 conn->pkt_type = __le16_to_cpu(ev->pkt_type);
1432
1433 hci_dev_unlock(hdev);
1434}
1435
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001436static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
1437{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001438 struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001439 struct inquiry_entry *ie;
1440
1441 BT_DBG("%s", hdev->name);
1442
1443 hci_dev_lock(hdev);
1444
1445 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) {
1446 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
1447 ie->timestamp = jiffies;
1448 }
1449
1450 hci_dev_unlock(hdev);
1451}
1452
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001453static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
1454{
1455 struct inquiry_data data;
1456 int num_rsp = *((__u8 *) skb->data);
1457
1458 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1459
1460 if (!num_rsp)
1461 return;
1462
1463 hci_dev_lock(hdev);
1464
1465 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
1466 struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
1467
1468 for (; num_rsp; num_rsp--) {
1469 bacpy(&data.bdaddr, &info->bdaddr);
1470 data.pscan_rep_mode = info->pscan_rep_mode;
1471 data.pscan_period_mode = info->pscan_period_mode;
1472 data.pscan_mode = info->pscan_mode;
1473 memcpy(data.dev_class, info->dev_class, 3);
1474 data.clock_offset = info->clock_offset;
1475 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001476 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001477 info++;
1478 hci_inquiry_cache_update(hdev, &data);
1479 }
1480 } else {
1481 struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
1482
1483 for (; num_rsp; num_rsp--) {
1484 bacpy(&data.bdaddr, &info->bdaddr);
1485 data.pscan_rep_mode = info->pscan_rep_mode;
1486 data.pscan_period_mode = info->pscan_period_mode;
1487 data.pscan_mode = 0x00;
1488 memcpy(data.dev_class, info->dev_class, 3);
1489 data.clock_offset = info->clock_offset;
1490 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001491 data.ssp_mode = 0x00;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001492 info++;
1493 hci_inquiry_cache_update(hdev, &data);
1494 }
1495 }
1496
1497 hci_dev_unlock(hdev);
1498}
1499
1500static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1501{
Marcel Holtmann41a96212008-07-14 20:13:48 +02001502 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
1503 struct hci_conn *conn;
1504
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001505 BT_DBG("%s", hdev->name);
Marcel Holtmann41a96212008-07-14 20:13:48 +02001506
Marcel Holtmann41a96212008-07-14 20:13:48 +02001507 hci_dev_lock(hdev);
1508
1509 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1510 if (conn) {
Marcel Holtmann769be972008-07-14 20:13:49 +02001511 if (!ev->status && ev->page == 0x01) {
1512 struct inquiry_entry *ie;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001513
Marcel Holtmann769be972008-07-14 20:13:49 +02001514 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
1515 ie->data.ssp_mode = (ev->features[0] & 0x01);
Marcel Holtmann41a96212008-07-14 20:13:48 +02001516
Marcel Holtmann769be972008-07-14 20:13:49 +02001517 conn->ssp_mode = (ev->features[0] & 0x01);
1518 }
1519
1520 if (conn->state == BT_CONFIG) {
1521 conn->state = BT_CONNECTED;
1522 hci_proto_connect_cfm(conn, ev->status);
1523 hci_conn_put(conn);
1524 }
Marcel Holtmann41a96212008-07-14 20:13:48 +02001525 }
1526
1527 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001528}
1529
1530static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1531{
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001532 struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
1533 struct hci_conn *conn;
1534
1535 BT_DBG("%s status %d", hdev->name, ev->status);
1536
1537 hci_dev_lock(hdev);
1538
1539 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
Marcel Holtmann9dc0a3a2008-07-14 20:13:46 +02001540 if (!conn) {
1541 if (ev->link_type == ESCO_LINK)
1542 goto unlock;
1543
1544 conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1545 if (!conn)
1546 goto unlock;
1547
1548 conn->type = SCO_LINK;
1549 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +02001550
1551 if (!ev->status) {
1552 conn->handle = __le16_to_cpu(ev->handle);
1553 conn->state = BT_CONNECTED;
1554 } else
1555 conn->state = BT_CLOSED;
1556
1557 hci_proto_connect_cfm(conn, ev->status);
1558 if (ev->status)
1559 hci_conn_del(conn);
1560
1561unlock:
1562 hci_dev_unlock(hdev);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001563}
1564
1565static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
1566{
1567 BT_DBG("%s", hdev->name);
1568}
1569
Marcel Holtmann04837f62006-07-03 10:02:33 +02001570static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
1571{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001572 struct hci_ev_sniff_subrate *ev = (void *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001573 struct hci_conn *conn;
1574
1575 BT_DBG("%s status %d", hdev->name, ev->status);
1576
1577 hci_dev_lock(hdev);
1578
1579 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1580 if (conn) {
1581 }
1582
1583 hci_dev_unlock(hdev);
1584}
1585
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001586static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
1587{
1588 struct inquiry_data data;
1589 struct extended_inquiry_info *info = (void *) (skb->data + 1);
1590 int num_rsp = *((__u8 *) skb->data);
1591
1592 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
1593
1594 if (!num_rsp)
1595 return;
1596
1597 hci_dev_lock(hdev);
1598
1599 for (; num_rsp; num_rsp--) {
1600 bacpy(&data.bdaddr, &info->bdaddr);
1601 data.pscan_rep_mode = info->pscan_rep_mode;
1602 data.pscan_period_mode = info->pscan_period_mode;
1603 data.pscan_mode = 0x00;
1604 memcpy(data.dev_class, info->dev_class, 3);
1605 data.clock_offset = info->clock_offset;
1606 data.rssi = info->rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +02001607 data.ssp_mode = 0x01;
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001608 info++;
1609 hci_inquiry_cache_update(hdev, &data);
1610 }
1611
1612 hci_dev_unlock(hdev);
1613}
1614
Marcel Holtmann04936842008-07-14 20:13:48 +02001615static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1616{
1617 struct hci_ev_io_capa_request *ev = (void *) skb->data;
1618 struct hci_conn *conn;
1619
1620 BT_DBG("%s", hdev->name);
1621
1622 hci_dev_lock(hdev);
1623
1624 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1625 if (conn)
1626 hci_conn_hold(conn);
1627
1628 hci_dev_unlock(hdev);
1629}
1630
1631static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1632{
1633 struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
1634 struct hci_conn *conn;
1635
1636 BT_DBG("%s", hdev->name);
1637
1638 hci_dev_lock(hdev);
1639
1640 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1641 if (conn)
1642 hci_conn_put(conn);
1643
1644 hci_dev_unlock(hdev);
1645}
1646
Marcel Holtmann41a96212008-07-14 20:13:48 +02001647static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1648{
1649 struct hci_ev_remote_host_features *ev = (void *) skb->data;
1650 struct inquiry_entry *ie;
1651
1652 BT_DBG("%s", hdev->name);
1653
1654 hci_dev_lock(hdev);
1655
1656 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr)))
1657 ie->data.ssp_mode = (ev->features[0] & 0x01);
1658
1659 hci_dev_unlock(hdev);
1660}
1661
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
1663{
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001664 struct hci_event_hdr *hdr = (void *) skb->data;
1665 __u8 event = hdr->evt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667 skb_pull(skb, HCI_EVENT_HDR_SIZE);
1668
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001669 switch (event) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 case HCI_EV_INQUIRY_COMPLETE:
1671 hci_inquiry_complete_evt(hdev, skb);
1672 break;
1673
1674 case HCI_EV_INQUIRY_RESULT:
1675 hci_inquiry_result_evt(hdev, skb);
1676 break;
1677
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001678 case HCI_EV_CONN_COMPLETE:
1679 hci_conn_complete_evt(hdev, skb);
Marcel Holtmann21d9e302005-09-13 01:32:25 +02001680 break;
1681
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 case HCI_EV_CONN_REQUEST:
1683 hci_conn_request_evt(hdev, skb);
1684 break;
1685
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 case HCI_EV_DISCONN_COMPLETE:
1687 hci_disconn_complete_evt(hdev, skb);
1688 break;
1689
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 case HCI_EV_AUTH_COMPLETE:
1691 hci_auth_complete_evt(hdev, skb);
1692 break;
1693
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001694 case HCI_EV_REMOTE_NAME:
1695 hci_remote_name_evt(hdev, skb);
1696 break;
1697
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 case HCI_EV_ENCRYPT_CHANGE:
1699 hci_encrypt_change_evt(hdev, skb);
1700 break;
1701
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001702 case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
1703 hci_change_link_key_complete_evt(hdev, skb);
1704 break;
1705
1706 case HCI_EV_REMOTE_FEATURES:
1707 hci_remote_features_evt(hdev, skb);
1708 break;
1709
1710 case HCI_EV_REMOTE_VERSION:
1711 hci_remote_version_evt(hdev, skb);
1712 break;
1713
1714 case HCI_EV_QOS_SETUP_COMPLETE:
1715 hci_qos_setup_complete_evt(hdev, skb);
1716 break;
1717
1718 case HCI_EV_CMD_COMPLETE:
1719 hci_cmd_complete_evt(hdev, skb);
1720 break;
1721
1722 case HCI_EV_CMD_STATUS:
1723 hci_cmd_status_evt(hdev, skb);
1724 break;
1725
1726 case HCI_EV_ROLE_CHANGE:
1727 hci_role_change_evt(hdev, skb);
1728 break;
1729
1730 case HCI_EV_NUM_COMP_PKTS:
1731 hci_num_comp_pkts_evt(hdev, skb);
1732 break;
1733
1734 case HCI_EV_MODE_CHANGE:
1735 hci_mode_change_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 break;
1737
1738 case HCI_EV_PIN_CODE_REQ:
1739 hci_pin_code_request_evt(hdev, skb);
1740 break;
1741
1742 case HCI_EV_LINK_KEY_REQ:
1743 hci_link_key_request_evt(hdev, skb);
1744 break;
1745
1746 case HCI_EV_LINK_KEY_NOTIFY:
1747 hci_link_key_notify_evt(hdev, skb);
1748 break;
1749
1750 case HCI_EV_CLOCK_OFFSET:
1751 hci_clock_offset_evt(hdev, skb);
1752 break;
1753
Marcel Holtmanna8746412008-07-14 20:13:46 +02001754 case HCI_EV_PKT_TYPE_CHANGE:
1755 hci_pkt_type_change_evt(hdev, skb);
1756 break;
1757
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001758 case HCI_EV_PSCAN_REP_MODE:
1759 hci_pscan_rep_mode_evt(hdev, skb);
1760 break;
1761
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001762 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
1763 hci_inquiry_result_with_rssi_evt(hdev, skb);
1764 break;
1765
1766 case HCI_EV_REMOTE_EXT_FEATURES:
1767 hci_remote_ext_features_evt(hdev, skb);
1768 break;
1769
1770 case HCI_EV_SYNC_CONN_COMPLETE:
1771 hci_sync_conn_complete_evt(hdev, skb);
1772 break;
1773
1774 case HCI_EV_SYNC_CONN_CHANGED:
1775 hci_sync_conn_changed_evt(hdev, skb);
1776 break;
1777
Marcel Holtmann04837f62006-07-03 10:02:33 +02001778 case HCI_EV_SNIFF_SUBRATE:
1779 hci_sniff_subrate_evt(hdev, skb);
1780 break;
1781
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001782 case HCI_EV_EXTENDED_INQUIRY_RESULT:
1783 hci_extended_inquiry_result_evt(hdev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 break;
1785
Marcel Holtmann04936842008-07-14 20:13:48 +02001786 case HCI_EV_IO_CAPA_REQUEST:
1787 hci_io_capa_request_evt(hdev, skb);
1788 break;
1789
1790 case HCI_EV_SIMPLE_PAIR_COMPLETE:
1791 hci_simple_pair_complete_evt(hdev, skb);
1792 break;
1793
Marcel Holtmann41a96212008-07-14 20:13:48 +02001794 case HCI_EV_REMOTE_HOST_FEATURES:
1795 hci_remote_host_features_evt(hdev, skb);
1796 break;
1797
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001798 default:
1799 BT_DBG("%s event 0x%x", hdev->name, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 break;
1801 }
1802
1803 kfree_skb(skb);
1804 hdev->stat.evt_rx++;
1805}
1806
1807/* Generate internal stack event */
1808void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
1809{
1810 struct hci_event_hdr *hdr;
1811 struct hci_ev_stack_internal *ev;
1812 struct sk_buff *skb;
1813
1814 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
1815 if (!skb)
1816 return;
1817
1818 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
1819 hdr->evt = HCI_EV_STACK_INTERNAL;
1820 hdr->plen = sizeof(*ev) + dlen;
1821
1822 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
1823 ev->type = type;
1824 memcpy(ev->data, data, dlen);
1825
Marcel Holtmann576c7d82005-08-06 12:36:54 +02001826 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001827 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02001828
Marcel Holtmann0d48d932005-08-09 20:30:28 -07001829 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 skb->dev = (void *) hdev;
1831 hci_send_to_sock(hdev, skb);
1832 kfree_skb(skb);
1833}