blob: bb94e6da223cb6f3535f5fecd611e91d3c0c067f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 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
15 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
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 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/sched.h>
33#include <linux/slab.h>
34#include <linux/poll.h>
35#include <linux/fcntl.h>
36#include <linux/init.h>
37#include <linux/skbuff.h>
38#include <linux/interrupt.h>
39#include <linux/notifier.h>
40#include <net/sock.h>
41
42#include <asm/system.h>
43#include <asm/uaccess.h>
44#include <asm/unaligned.h>
45
46#include <net/bluetooth/bluetooth.h>
47#include <net/bluetooth/hci_core.h>
48
49#ifndef CONFIG_BT_HCI_CORE_DEBUG
50#undef BT_DBG
51#define BT_DBG(D...)
52#endif
53
54/* Handle HCI Event packets */
55
56/* Command Complete OGF LINK_CTL */
57static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
58{
59 __u8 status;
Marcel Holtmann6bd57412006-11-18 22:14:22 +010060 struct hci_conn *pend;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
62 BT_DBG("%s ocf 0x%x", hdev->name, ocf);
63
64 switch (ocf) {
65 case OCF_INQUIRY_CANCEL:
Marcel Holtmanndefc7612006-09-21 16:04:00 +020066 case OCF_EXIT_PERIODIC_INQ:
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 status = *((__u8 *) skb->data);
68
69 if (status) {
70 BT_DBG("%s Inquiry cancel error: status 0x%x", hdev->name, status);
71 } else {
72 clear_bit(HCI_INQUIRY, &hdev->flags);
73 hci_req_complete(hdev, status);
74 }
Marcel Holtmann6bd57412006-11-18 22:14:22 +010075
76 hci_dev_lock(hdev);
77
78 pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
79 if (pend)
80 hci_acl_connect(pend);
81
82 hci_dev_unlock(hdev);
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 break;
85
86 default:
87 BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf);
88 break;
89 }
90}
91
92/* Command Complete OGF LINK_POLICY */
93static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
94{
95 struct hci_conn *conn;
96 struct hci_rp_role_discovery *rd;
Marcel Holtmann04837f62006-07-03 10:02:33 +020097 struct hci_rp_write_link_policy *lp;
98 void *sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100 BT_DBG("%s ocf 0x%x", hdev->name, ocf);
101
102 switch (ocf) {
103 case OCF_ROLE_DISCOVERY:
104 rd = (void *) skb->data;
105
106 if (rd->status)
107 break;
108
109 hci_dev_lock(hdev);
110
111 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rd->handle));
112 if (conn) {
113 if (rd->role)
114 conn->link_mode &= ~HCI_LM_MASTER;
115 else
116 conn->link_mode |= HCI_LM_MASTER;
117 }
118
119 hci_dev_unlock(hdev);
120 break;
121
Marcel Holtmann04837f62006-07-03 10:02:33 +0200122 case OCF_WRITE_LINK_POLICY:
123 sent = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY);
124 if (!sent)
125 break;
126
127 lp = (struct hci_rp_write_link_policy *) skb->data;
128
129 if (lp->status)
130 break;
131
132 hci_dev_lock(hdev);
133
134 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(lp->handle));
135 if (conn) {
136 __le16 policy = get_unaligned((__le16 *) (sent + 2));
137 conn->link_policy = __le16_to_cpu(policy);
138 }
139
140 hci_dev_unlock(hdev);
141 break;
142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 default:
144 BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x",
145 hdev->name, ocf);
146 break;
147 }
148}
149
150/* Command Complete OGF HOST_CTL */
151static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
152{
153 __u8 status, param;
154 __u16 setting;
155 struct hci_rp_read_voice_setting *vs;
156 void *sent;
157
158 BT_DBG("%s ocf 0x%x", hdev->name, ocf);
159
160 switch (ocf) {
161 case OCF_RESET:
162 status = *((__u8 *) skb->data);
163 hci_req_complete(hdev, status);
164 break;
165
166 case OCF_SET_EVENT_FLT:
167 status = *((__u8 *) skb->data);
168 if (status) {
169 BT_DBG("%s SET_EVENT_FLT failed %d", hdev->name, status);
170 } else {
171 BT_DBG("%s SET_EVENT_FLT succeseful", hdev->name);
172 }
173 break;
174
175 case OCF_WRITE_AUTH_ENABLE:
176 sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE);
177 if (!sent)
178 break;
179
180 status = *((__u8 *) skb->data);
181 param = *((__u8 *) sent);
182
183 if (!status) {
184 if (param == AUTH_ENABLED)
185 set_bit(HCI_AUTH, &hdev->flags);
186 else
187 clear_bit(HCI_AUTH, &hdev->flags);
188 }
189 hci_req_complete(hdev, status);
190 break;
191
192 case OCF_WRITE_ENCRYPT_MODE:
193 sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE);
194 if (!sent)
195 break;
196
197 status = *((__u8 *) skb->data);
198 param = *((__u8 *) sent);
199
200 if (!status) {
201 if (param)
202 set_bit(HCI_ENCRYPT, &hdev->flags);
203 else
204 clear_bit(HCI_ENCRYPT, &hdev->flags);
205 }
206 hci_req_complete(hdev, status);
207 break;
208
209 case OCF_WRITE_CA_TIMEOUT:
210 status = *((__u8 *) skb->data);
211 if (status) {
212 BT_DBG("%s OCF_WRITE_CA_TIMEOUT failed %d", hdev->name, status);
213 } else {
214 BT_DBG("%s OCF_WRITE_CA_TIMEOUT succeseful", hdev->name);
215 }
216 break;
217
218 case OCF_WRITE_PG_TIMEOUT:
219 status = *((__u8 *) skb->data);
220 if (status) {
221 BT_DBG("%s OCF_WRITE_PG_TIMEOUT failed %d", hdev->name, status);
222 } else {
223 BT_DBG("%s: OCF_WRITE_PG_TIMEOUT succeseful", hdev->name);
224 }
225 break;
226
227 case OCF_WRITE_SCAN_ENABLE:
228 sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE);
229 if (!sent)
230 break;
231
232 status = *((__u8 *) skb->data);
233 param = *((__u8 *) sent);
234
235 BT_DBG("param 0x%x", param);
236
237 if (!status) {
238 clear_bit(HCI_PSCAN, &hdev->flags);
239 clear_bit(HCI_ISCAN, &hdev->flags);
240 if (param & SCAN_INQUIRY)
241 set_bit(HCI_ISCAN, &hdev->flags);
242
243 if (param & SCAN_PAGE)
244 set_bit(HCI_PSCAN, &hdev->flags);
245 }
246 hci_req_complete(hdev, status);
247 break;
248
249 case OCF_READ_VOICE_SETTING:
250 vs = (struct hci_rp_read_voice_setting *) skb->data;
251
252 if (vs->status) {
253 BT_DBG("%s READ_VOICE_SETTING failed %d", hdev->name, vs->status);
254 break;
255 }
256
257 setting = __le16_to_cpu(vs->voice_setting);
258
259 if (hdev->voice_setting != setting ) {
260 hdev->voice_setting = setting;
261
262 BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
263
264 if (hdev->notify) {
265 tasklet_disable(&hdev->tx_task);
266 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
267 tasklet_enable(&hdev->tx_task);
268 }
269 }
270 break;
271
272 case OCF_WRITE_VOICE_SETTING:
273 sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING);
274 if (!sent)
275 break;
276
277 status = *((__u8 *) skb->data);
Marcel Holtmann1ebb9252005-11-08 09:57:21 -0800278 setting = __le16_to_cpu(get_unaligned((__le16 *) sent));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
280 if (!status && hdev->voice_setting != setting) {
281 hdev->voice_setting = setting;
282
283 BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
284
285 if (hdev->notify) {
286 tasklet_disable(&hdev->tx_task);
287 hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
288 tasklet_enable(&hdev->tx_task);
289 }
290 }
291 hci_req_complete(hdev, status);
292 break;
293
294 case OCF_HOST_BUFFER_SIZE:
295 status = *((__u8 *) skb->data);
296 if (status) {
297 BT_DBG("%s OCF_BUFFER_SIZE failed %d", hdev->name, status);
298 hci_req_complete(hdev, status);
299 }
300 break;
301
302 default:
303 BT_DBG("%s Command complete: ogf HOST_CTL ocf %x", hdev->name, ocf);
304 break;
305 }
306}
307
308/* Command Complete OGF INFO_PARAM */
309static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
310{
Marcel Holtmann1143e5a2006-09-23 09:57:20 +0200311 struct hci_rp_read_loc_version *lv;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200312 struct hci_rp_read_local_features *lf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 struct hci_rp_read_buffer_size *bs;
314 struct hci_rp_read_bd_addr *ba;
315
316 BT_DBG("%s ocf 0x%x", hdev->name, ocf);
317
318 switch (ocf) {
Marcel Holtmann1143e5a2006-09-23 09:57:20 +0200319 case OCF_READ_LOCAL_VERSION:
320 lv = (struct hci_rp_read_loc_version *) skb->data;
321
322 if (lv->status) {
323 BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status);
324 break;
325 }
326
327 hdev->hci_ver = lv->hci_ver;
328 hdev->hci_rev = btohs(lv->hci_rev);
329 hdev->manufacturer = btohs(lv->manufacturer);
330
331 BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name,
332 hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
333
334 break;
335
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 case OCF_READ_LOCAL_FEATURES:
Marcel Holtmann04837f62006-07-03 10:02:33 +0200337 lf = (struct hci_rp_read_local_features *) skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
339 if (lf->status) {
340 BT_DBG("%s READ_LOCAL_FEATURES failed %d", hdev->name, lf->status);
341 break;
342 }
343
344 memcpy(hdev->features, lf->features, sizeof(hdev->features));
345
346 /* Adjust default settings according to features
347 * supported by device. */
348 if (hdev->features[0] & LMP_3SLOT)
349 hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
350
351 if (hdev->features[0] & LMP_5SLOT)
352 hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
353
354 if (hdev->features[1] & LMP_HV2)
355 hdev->pkt_type |= (HCI_HV2);
356
357 if (hdev->features[1] & LMP_HV3)
358 hdev->pkt_type |= (HCI_HV3);
359
Marcel Holtmann1143e5a2006-09-23 09:57:20 +0200360 BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
361 lf->features[0], lf->features[1], lf->features[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
363 break;
364
365 case OCF_READ_BUFFER_SIZE:
366 bs = (struct hci_rp_read_buffer_size *) skb->data;
367
368 if (bs->status) {
369 BT_DBG("%s READ_BUFFER_SIZE failed %d", hdev->name, bs->status);
370 hci_req_complete(hdev, bs->status);
371 break;
372 }
373
374 hdev->acl_mtu = __le16_to_cpu(bs->acl_mtu);
Marcel Holtmannda1f5192006-07-03 10:02:29 +0200375 hdev->sco_mtu = bs->sco_mtu;
376 hdev->acl_pkts = __le16_to_cpu(bs->acl_max_pkt);
377 hdev->sco_pkts = __le16_to_cpu(bs->sco_max_pkt);
378
379 if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
380 hdev->sco_mtu = 64;
381 hdev->sco_pkts = 8;
382 }
383
384 hdev->acl_cnt = hdev->acl_pkts;
385 hdev->sco_cnt = hdev->sco_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387 BT_DBG("%s mtu: acl %d, sco %d max_pkt: acl %d, sco %d", hdev->name,
388 hdev->acl_mtu, hdev->sco_mtu, hdev->acl_pkts, hdev->sco_pkts);
389 break;
390
391 case OCF_READ_BD_ADDR:
392 ba = (struct hci_rp_read_bd_addr *) skb->data;
393
394 if (!ba->status) {
395 bacpy(&hdev->bdaddr, &ba->bdaddr);
396 } else {
397 BT_DBG("%s: READ_BD_ADDR failed %d", hdev->name, ba->status);
398 }
399
400 hci_req_complete(hdev, ba->status);
401 break;
402
403 default:
404 BT_DBG("%s Command complete: ogf INFO_PARAM ocf %x", hdev->name, ocf);
405 break;
406 }
407}
408
409/* Command Status OGF LINK_CTL */
410static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
411{
412 struct hci_conn *conn;
413 struct hci_cp_create_conn *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_CREATE_CONN);
414
415 if (!cp)
416 return;
417
418 hci_dev_lock(hdev);
419
420 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
421
422 BT_DBG("%s status 0x%x bdaddr %s conn %p", hdev->name,
423 status, batostr(&cp->bdaddr), conn);
424
425 if (status) {
426 if (conn && conn->state == BT_CONNECT) {
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200427 if (status != 0x0c || conn->attempt > 2) {
428 conn->state = BT_CLOSED;
429 hci_proto_connect_cfm(conn, status);
430 hci_conn_del(conn);
431 } else
432 conn->state = BT_CONNECT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 }
434 } else {
435 if (!conn) {
436 conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
437 if (conn) {
438 conn->out = 1;
439 conn->link_mode |= HCI_LM_MASTER;
440 } else
441 BT_ERR("No memmory for new connection");
442 }
443 }
444
445 hci_dev_unlock(hdev);
446}
447
448static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
449{
450 BT_DBG("%s ocf 0x%x", hdev->name, ocf);
451
452 switch (ocf) {
453 case OCF_CREATE_CONN:
454 hci_cs_create_conn(hdev, status);
455 break;
456
457 case OCF_ADD_SCO:
458 if (status) {
459 struct hci_conn *acl, *sco;
460 struct hci_cp_add_sco *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_ADD_SCO);
461 __u16 handle;
462
463 if (!cp)
464 break;
465
466 handle = __le16_to_cpu(cp->handle);
467
468 BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status);
469
470 hci_dev_lock(hdev);
471
472 acl = hci_conn_hash_lookup_handle(hdev, handle);
473 if (acl && (sco = acl->link)) {
474 sco->state = BT_CLOSED;
475
476 hci_proto_connect_cfm(sco, status);
477 hci_conn_del(sco);
478 }
479
480 hci_dev_unlock(hdev);
481 }
482 break;
483
484 case OCF_INQUIRY:
485 if (status) {
486 BT_DBG("%s Inquiry error: status 0x%x", hdev->name, status);
487 hci_req_complete(hdev, status);
488 } else {
489 set_bit(HCI_INQUIRY, &hdev->flags);
490 }
491 break;
492
493 default:
494 BT_DBG("%s Command status: ogf LINK_CTL ocf %x status %d",
495 hdev->name, ocf, status);
496 break;
497 }
498}
499
500/* Command Status OGF LINK_POLICY */
501static void hci_cs_link_policy(struct hci_dev *hdev, __u16 ocf, __u8 status)
502{
503 BT_DBG("%s ocf 0x%x", hdev->name, ocf);
504
505 switch (ocf) {
Marcel Holtmann04837f62006-07-03 10:02:33 +0200506 case OCF_SNIFF_MODE:
507 if (status) {
508 struct hci_conn *conn;
509 struct hci_cp_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_SNIFF_MODE);
510
511 if (!cp)
512 break;
513
514 hci_dev_lock(hdev);
515
516 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
517 if (conn) {
518 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
519 }
520
521 hci_dev_unlock(hdev);
522 }
523 break;
524
525 case OCF_EXIT_SNIFF_MODE:
526 if (status) {
527 struct hci_conn *conn;
528 struct hci_cp_exit_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_EXIT_SNIFF_MODE);
529
530 if (!cp)
531 break;
532
533 hci_dev_lock(hdev);
534
535 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
536 if (conn) {
537 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
538 }
539
540 hci_dev_unlock(hdev);
541 }
542 break;
543
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 default:
Marcel Holtmann04837f62006-07-03 10:02:33 +0200545 BT_DBG("%s Command status: ogf LINK_POLICY ocf %x", hdev->name, ocf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 break;
547 }
548}
549
550/* Command Status OGF HOST_CTL */
551static void hci_cs_host_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
552{
553 BT_DBG("%s ocf 0x%x", hdev->name, ocf);
554
555 switch (ocf) {
556 default:
557 BT_DBG("%s Command status: ogf HOST_CTL ocf %x", hdev->name, ocf);
558 break;
559 }
560}
561
562/* Command Status OGF INFO_PARAM */
563static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status)
564{
565 BT_DBG("%s: hci_cs_info_param: ocf 0x%x", hdev->name, ocf);
566
567 switch (ocf) {
568 default:
569 BT_DBG("%s Command status: ogf INFO_PARAM ocf %x", hdev->name, ocf);
570 break;
571 }
572}
573
574/* Inquiry Complete */
575static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
576{
577 __u8 status = *((__u8 *) skb->data);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100578 struct hci_conn *pend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
580 BT_DBG("%s status %d", hdev->name, status);
581
582 clear_bit(HCI_INQUIRY, &hdev->flags);
583 hci_req_complete(hdev, status);
Marcel Holtmann6bd57412006-11-18 22:14:22 +0100584
585 hci_dev_lock(hdev);
586
587 pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
588 if (pend)
589 hci_acl_connect(pend);
590
591 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592}
593
594/* Inquiry Result */
595static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
596{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700597 struct inquiry_data data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1);
599 int num_rsp = *((__u8 *) skb->data);
600
601 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
602
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700603 if (!num_rsp)
604 return;
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700607
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 for (; num_rsp; num_rsp--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 bacpy(&data.bdaddr, &info->bdaddr);
610 data.pscan_rep_mode = info->pscan_rep_mode;
611 data.pscan_period_mode = info->pscan_period_mode;
612 data.pscan_mode = info->pscan_mode;
613 memcpy(data.dev_class, info->dev_class, 3);
614 data.clock_offset = info->clock_offset;
615 data.rssi = 0x00;
616 info++;
617 hci_inquiry_cache_update(hdev, &data);
618 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 hci_dev_unlock(hdev);
621}
622
623/* Inquiry Result With RSSI */
624static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
625{
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700626 struct inquiry_data data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 int num_rsp = *((__u8 *) skb->data);
628
629 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
630
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700631 if (!num_rsp)
632 return;
633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 hci_dev_lock(hdev);
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700635
636 if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
637 struct inquiry_info_with_rssi_and_pscan_mode *info =
638 (struct inquiry_info_with_rssi_and_pscan_mode *) (skb->data + 1);
639
640 for (; num_rsp; num_rsp--) {
641 bacpy(&data.bdaddr, &info->bdaddr);
642 data.pscan_rep_mode = info->pscan_rep_mode;
643 data.pscan_period_mode = info->pscan_period_mode;
644 data.pscan_mode = info->pscan_mode;
645 memcpy(data.dev_class, info->dev_class, 3);
646 data.clock_offset = info->clock_offset;
647 data.rssi = info->rssi;
648 info++;
649 hci_inquiry_cache_update(hdev, &data);
650 }
651 } else {
652 struct inquiry_info_with_rssi *info =
653 (struct inquiry_info_with_rssi *) (skb->data + 1);
654
655 for (; num_rsp; num_rsp--) {
656 bacpy(&data.bdaddr, &info->bdaddr);
657 data.pscan_rep_mode = info->pscan_rep_mode;
658 data.pscan_period_mode = info->pscan_period_mode;
659 data.pscan_mode = 0x00;
660 memcpy(data.dev_class, info->dev_class, 3);
661 data.clock_offset = info->clock_offset;
662 data.rssi = info->rssi;
663 info++;
664 hci_inquiry_cache_update(hdev, &data);
665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 }
Marcel Holtmann45bb4bf2005-08-09 20:27:49 -0700667
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 hci_dev_unlock(hdev);
669}
670
Marcel Holtmann21d9e302005-09-13 01:32:25 +0200671/* Extended Inquiry Result */
672static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
673{
674 struct inquiry_data data;
675 struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1);
676 int num_rsp = *((__u8 *) skb->data);
677
678 BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
679
680 if (!num_rsp)
681 return;
682
683 hci_dev_lock(hdev);
684
685 for (; num_rsp; num_rsp--) {
686 bacpy(&data.bdaddr, &info->bdaddr);
687 data.pscan_rep_mode = info->pscan_rep_mode;
688 data.pscan_period_mode = info->pscan_period_mode;
689 data.pscan_mode = 0x00;
690 memcpy(data.dev_class, info->dev_class, 3);
691 data.clock_offset = info->clock_offset;
692 data.rssi = info->rssi;
693 info++;
694 hci_inquiry_cache_update(hdev, &data);
695 }
696
697 hci_dev_unlock(hdev);
698}
699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700/* Connect Request */
701static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
702{
703 struct hci_ev_conn_request *ev = (struct hci_ev_conn_request *) skb->data;
704 int mask = hdev->link_mode;
705
706 BT_DBG("%s Connection request: %s type 0x%x", hdev->name,
707 batostr(&ev->bdaddr), ev->link_type);
708
709 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
710
711 if (mask & HCI_LM_ACCEPT) {
712 /* Connection accepted */
713 struct hci_conn *conn;
714 struct hci_cp_accept_conn_req cp;
715
716 hci_dev_lock(hdev);
717 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
718 if (!conn) {
719 if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
720 BT_ERR("No memmory for new connection");
721 hci_dev_unlock(hdev);
722 return;
723 }
724 }
725 memcpy(conn->dev_class, ev->dev_class, 3);
726 conn->state = BT_CONNECT;
727 hci_dev_unlock(hdev);
728
729 bacpy(&cp.bdaddr, &ev->bdaddr);
730
731 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
732 cp.role = 0x00; /* Become master */
733 else
734 cp.role = 0x01; /* Remain slave */
735
Marcel Holtmann04837f62006-07-03 10:02:33 +0200736 hci_send_cmd(hdev, OGF_LINK_CTL,
737 OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 } else {
739 /* Connection rejected */
740 struct hci_cp_reject_conn_req cp;
741
742 bacpy(&cp.bdaddr, &ev->bdaddr);
743 cp.reason = 0x0f;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200744 hci_send_cmd(hdev, OGF_LINK_CTL,
745 OCF_REJECT_CONN_REQ, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
747}
748
749/* Connect Complete */
750static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
751{
752 struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200753 struct hci_conn *conn, *pend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 BT_DBG("%s", hdev->name);
756
757 hci_dev_lock(hdev);
758
759 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
760 if (!conn) {
761 hci_dev_unlock(hdev);
762 return;
763 }
764
765 if (!ev->status) {
766 conn->handle = __le16_to_cpu(ev->handle);
767 conn->state = BT_CONNECTED;
768
769 if (test_bit(HCI_AUTH, &hdev->flags))
770 conn->link_mode |= HCI_LM_AUTH;
771
772 if (test_bit(HCI_ENCRYPT, &hdev->flags))
773 conn->link_mode |= HCI_LM_ENCRYPT;
774
Marcel Holtmann04837f62006-07-03 10:02:33 +0200775 /* Get remote features */
776 if (conn->type == ACL_LINK) {
777 struct hci_cp_read_remote_features cp;
778 cp.handle = ev->handle;
779 hci_send_cmd(hdev, OGF_LINK_CTL,
780 OCF_READ_REMOTE_FEATURES, sizeof(cp), &cp);
781 }
782
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 /* Set link policy */
784 if (conn->type == ACL_LINK && hdev->link_policy) {
785 struct hci_cp_write_link_policy cp;
786 cp.handle = ev->handle;
787 cp.policy = __cpu_to_le16(hdev->link_policy);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200788 hci_send_cmd(hdev, OGF_LINK_POLICY,
789 OCF_WRITE_LINK_POLICY, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 }
791
792 /* Set packet type for incoming connection */
793 if (!conn->out) {
794 struct hci_cp_change_conn_ptype cp;
795 cp.handle = ev->handle;
796 cp.pkt_type = (conn->type == ACL_LINK) ?
797 __cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK):
798 __cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
799
Marcel Holtmann04837f62006-07-03 10:02:33 +0200800 hci_send_cmd(hdev, OGF_LINK_CTL,
801 OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
Marcel Holtmann37e97b42006-09-28 15:29:09 -0700802 } else {
803 /* Update disconnect timer */
804 hci_conn_hold(conn);
805 hci_conn_put(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 }
807 } else
808 conn->state = BT_CLOSED;
809
810 if (conn->type == ACL_LINK) {
811 struct hci_conn *sco = conn->link;
812 if (sco) {
813 if (!ev->status)
814 hci_add_sco(sco, conn->handle);
815 else {
816 hci_proto_connect_cfm(sco, ev->status);
817 hci_conn_del(sco);
818 }
819 }
820 }
821
822 hci_proto_connect_cfm(conn, ev->status);
823 if (ev->status)
824 hci_conn_del(conn);
825
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200826 pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
827 if (pend)
828 hci_acl_connect(pend);
829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 hci_dev_unlock(hdev);
831}
832
833/* Disconnect Complete */
834static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
835{
836 struct hci_ev_disconn_complete *ev = (struct hci_ev_disconn_complete *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200837 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
839 BT_DBG("%s status %d", hdev->name, ev->status);
840
841 if (ev->status)
842 return;
843
844 hci_dev_lock(hdev);
845
Marcel Holtmann04837f62006-07-03 10:02:33 +0200846 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 if (conn) {
848 conn->state = BT_CLOSED;
849 hci_proto_disconn_ind(conn, ev->reason);
850 hci_conn_del(conn);
851 }
852
853 hci_dev_unlock(hdev);
854}
855
856/* Number of completed packets */
857static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
858{
859 struct hci_ev_num_comp_pkts *ev = (struct hci_ev_num_comp_pkts *) skb->data;
Marcel Holtmann1ebb9252005-11-08 09:57:21 -0800860 __le16 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 int i;
862
863 skb_pull(skb, sizeof(*ev));
864
865 BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
866
867 if (skb->len < ev->num_hndl * 4) {
868 BT_DBG("%s bad parameters", hdev->name);
869 return;
870 }
871
872 tasklet_disable(&hdev->tx_task);
873
Marcel Holtmann1ebb9252005-11-08 09:57:21 -0800874 for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 struct hci_conn *conn;
876 __u16 handle, count;
877
878 handle = __le16_to_cpu(get_unaligned(ptr++));
879 count = __le16_to_cpu(get_unaligned(ptr++));
880
881 conn = hci_conn_hash_lookup_handle(hdev, handle);
882 if (conn) {
883 conn->sent -= count;
884
885 if (conn->type == SCO_LINK) {
886 if ((hdev->sco_cnt += count) > hdev->sco_pkts)
887 hdev->sco_cnt = hdev->sco_pkts;
888 } else {
889 if ((hdev->acl_cnt += count) > hdev->acl_pkts)
890 hdev->acl_cnt = hdev->acl_pkts;
891 }
892 }
893 }
894 hci_sched_tx(hdev);
895
896 tasklet_enable(&hdev->tx_task);
897}
898
899/* Role Change */
900static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
901{
902 struct hci_ev_role_change *ev = (struct hci_ev_role_change *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200903 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 BT_DBG("%s status %d", hdev->name, ev->status);
906
907 hci_dev_lock(hdev);
908
909 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
910 if (conn) {
911 if (!ev->status) {
912 if (ev->role)
913 conn->link_mode &= ~HCI_LM_MASTER;
914 else
915 conn->link_mode |= HCI_LM_MASTER;
916 }
917
918 clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
919
920 hci_role_switch_cfm(conn, ev->status, ev->role);
921 }
922
923 hci_dev_unlock(hdev);
924}
925
Marcel Holtmann04837f62006-07-03 10:02:33 +0200926/* Mode Change */
927static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200929 struct hci_ev_mode_change *ev = (struct hci_ev_mode_change *) skb->data;
930 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
932 BT_DBG("%s status %d", hdev->name, ev->status);
933
934 hci_dev_lock(hdev);
935
Marcel Holtmann04837f62006-07-03 10:02:33 +0200936 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
937 if (conn) {
938 conn->mode = ev->mode;
939 conn->interval = __le16_to_cpu(ev->interval);
940
941 if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
942 if (conn->mode == HCI_CM_ACTIVE)
943 conn->power_save = 1;
944 else
945 conn->power_save = 0;
946 }
947 }
948
949 hci_dev_unlock(hdev);
950}
951
952/* Authentication Complete */
953static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
954{
955 struct hci_ev_auth_complete *ev = (struct hci_ev_auth_complete *) skb->data;
956 struct hci_conn *conn;
957
958 BT_DBG("%s status %d", hdev->name, ev->status);
959
960 hci_dev_lock(hdev);
961
962 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 if (conn) {
964 if (!ev->status)
965 conn->link_mode |= HCI_LM_AUTH;
966
967 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
968
969 hci_auth_cfm(conn, ev->status);
970
971 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
972 if (!ev->status) {
973 struct hci_cp_set_conn_encrypt cp;
974 cp.handle = __cpu_to_le16(conn->handle);
975 cp.encrypt = 1;
976 hci_send_cmd(conn->hdev, OGF_LINK_CTL,
Marcel Holtmann04837f62006-07-03 10:02:33 +0200977 OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 } else {
979 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
980 hci_encrypt_cfm(conn, ev->status, 0x00);
981 }
982 }
983 }
984
985 hci_dev_unlock(hdev);
986}
987
988/* Encryption Change */
989static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
990{
991 struct hci_ev_encrypt_change *ev = (struct hci_ev_encrypt_change *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200992 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994 BT_DBG("%s status %d", hdev->name, ev->status);
995
996 hci_dev_lock(hdev);
997
Marcel Holtmann04837f62006-07-03 10:02:33 +0200998 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 if (conn) {
1000 if (!ev->status) {
1001 if (ev->encrypt)
1002 conn->link_mode |= HCI_LM_ENCRYPT;
1003 else
1004 conn->link_mode &= ~HCI_LM_ENCRYPT;
1005 }
1006
1007 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1008
1009 hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1010 }
1011
1012 hci_dev_unlock(hdev);
1013}
1014
1015/* Change Connection Link Key Complete */
1016static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1017{
1018 struct hci_ev_change_conn_link_key_complete *ev = (struct hci_ev_change_conn_link_key_complete *) skb->data;
Marcel Holtmann04837f62006-07-03 10:02:33 +02001019 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
1021 BT_DBG("%s status %d", hdev->name, ev->status);
1022
1023 hci_dev_lock(hdev);
1024
Marcel Holtmann04837f62006-07-03 10:02:33 +02001025 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 if (conn) {
1027 if (!ev->status)
1028 conn->link_mode |= HCI_LM_SECURE;
1029
1030 clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1031
1032 hci_key_change_cfm(conn, ev->status);
1033 }
1034
1035 hci_dev_unlock(hdev);
1036}
1037
1038/* Pin Code Request*/
1039static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1040{
1041}
1042
1043/* Link Key Request */
1044static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1045{
1046}
1047
1048/* Link Key Notification */
1049static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
1050{
1051}
1052
Marcel Holtmann04837f62006-07-03 10:02:33 +02001053/* Remote Features */
1054static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055{
Marcel Holtmann04837f62006-07-03 10:02:33 +02001056 struct hci_ev_remote_features *ev = (struct hci_ev_remote_features *) skb->data;
1057 struct hci_conn *conn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
1059 BT_DBG("%s status %d", hdev->name, ev->status);
1060
1061 hci_dev_lock(hdev);
1062
Marcel Holtmann04837f62006-07-03 10:02:33 +02001063 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1064 if (conn && !ev->status) {
1065 memcpy(conn->features, ev->features, sizeof(conn->features));
1066 }
1067
1068 hci_dev_unlock(hdev);
1069}
1070
1071/* Clock Offset */
1072static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
1073{
1074 struct hci_ev_clock_offset *ev = (struct hci_ev_clock_offset *) skb->data;
1075 struct hci_conn *conn;
1076
1077 BT_DBG("%s status %d", hdev->name, ev->status);
1078
1079 hci_dev_lock(hdev);
1080
1081 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 if (conn && !ev->status) {
1083 struct inquiry_entry *ie;
1084
1085 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
1086 ie->data.clock_offset = ev->clock_offset;
1087 ie->timestamp = jiffies;
1088 }
1089 }
1090
1091 hci_dev_unlock(hdev);
1092}
1093
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001094/* Page Scan Repetition Mode */
1095static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
1096{
1097 struct hci_ev_pscan_rep_mode *ev = (struct hci_ev_pscan_rep_mode *) skb->data;
1098 struct inquiry_entry *ie;
1099
1100 BT_DBG("%s", hdev->name);
1101
1102 hci_dev_lock(hdev);
1103
1104 if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) {
1105 ie->data.pscan_rep_mode = ev->pscan_rep_mode;
1106 ie->timestamp = jiffies;
1107 }
1108
1109 hci_dev_unlock(hdev);
1110}
1111
Marcel Holtmann04837f62006-07-03 10:02:33 +02001112/* Sniff Subrate */
1113static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
1114{
1115 struct hci_ev_sniff_subrate *ev = (struct hci_ev_sniff_subrate *) skb->data;
1116 struct hci_conn *conn;
1117
1118 BT_DBG("%s status %d", hdev->name, ev->status);
1119
1120 hci_dev_lock(hdev);
1121
1122 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1123 if (conn) {
1124 }
1125
1126 hci_dev_unlock(hdev);
1127}
1128
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
1130{
1131 struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data;
1132 struct hci_ev_cmd_complete *ec;
1133 struct hci_ev_cmd_status *cs;
1134 u16 opcode, ocf, ogf;
1135
1136 skb_pull(skb, HCI_EVENT_HDR_SIZE);
1137
1138 BT_DBG("%s evt 0x%x", hdev->name, hdr->evt);
1139
1140 switch (hdr->evt) {
1141 case HCI_EV_NUM_COMP_PKTS:
1142 hci_num_comp_pkts_evt(hdev, skb);
1143 break;
1144
1145 case HCI_EV_INQUIRY_COMPLETE:
1146 hci_inquiry_complete_evt(hdev, skb);
1147 break;
1148
1149 case HCI_EV_INQUIRY_RESULT:
1150 hci_inquiry_result_evt(hdev, skb);
1151 break;
1152
1153 case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
1154 hci_inquiry_result_with_rssi_evt(hdev, skb);
1155 break;
1156
Marcel Holtmann21d9e302005-09-13 01:32:25 +02001157 case HCI_EV_EXTENDED_INQUIRY_RESULT:
1158 hci_extended_inquiry_result_evt(hdev, skb);
1159 break;
1160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 case HCI_EV_CONN_REQUEST:
1162 hci_conn_request_evt(hdev, skb);
1163 break;
1164
1165 case HCI_EV_CONN_COMPLETE:
1166 hci_conn_complete_evt(hdev, skb);
1167 break;
1168
1169 case HCI_EV_DISCONN_COMPLETE:
1170 hci_disconn_complete_evt(hdev, skb);
1171 break;
1172
1173 case HCI_EV_ROLE_CHANGE:
1174 hci_role_change_evt(hdev, skb);
1175 break;
1176
Marcel Holtmann04837f62006-07-03 10:02:33 +02001177 case HCI_EV_MODE_CHANGE:
1178 hci_mode_change_evt(hdev, skb);
1179 break;
1180
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 case HCI_EV_AUTH_COMPLETE:
1182 hci_auth_complete_evt(hdev, skb);
1183 break;
1184
1185 case HCI_EV_ENCRYPT_CHANGE:
1186 hci_encrypt_change_evt(hdev, skb);
1187 break;
1188
1189 case HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE:
1190 hci_change_conn_link_key_complete_evt(hdev, skb);
1191 break;
1192
1193 case HCI_EV_PIN_CODE_REQ:
1194 hci_pin_code_request_evt(hdev, skb);
1195 break;
1196
1197 case HCI_EV_LINK_KEY_REQ:
1198 hci_link_key_request_evt(hdev, skb);
1199 break;
1200
1201 case HCI_EV_LINK_KEY_NOTIFY:
1202 hci_link_key_notify_evt(hdev, skb);
1203 break;
1204
Marcel Holtmann04837f62006-07-03 10:02:33 +02001205 case HCI_EV_REMOTE_FEATURES:
1206 hci_remote_features_evt(hdev, skb);
1207 break;
1208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 case HCI_EV_CLOCK_OFFSET:
1210 hci_clock_offset_evt(hdev, skb);
1211 break;
1212
Marcel Holtmann85a1e932005-08-09 20:28:02 -07001213 case HCI_EV_PSCAN_REP_MODE:
1214 hci_pscan_rep_mode_evt(hdev, skb);
1215 break;
1216
Marcel Holtmann04837f62006-07-03 10:02:33 +02001217 case HCI_EV_SNIFF_SUBRATE:
1218 hci_sniff_subrate_evt(hdev, skb);
1219 break;
1220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 case HCI_EV_CMD_STATUS:
1222 cs = (struct hci_ev_cmd_status *) skb->data;
1223 skb_pull(skb, sizeof(cs));
1224
1225 opcode = __le16_to_cpu(cs->opcode);
1226 ogf = hci_opcode_ogf(opcode);
1227 ocf = hci_opcode_ocf(opcode);
1228
1229 switch (ogf) {
1230 case OGF_INFO_PARAM:
1231 hci_cs_info_param(hdev, ocf, cs->status);
1232 break;
1233
1234 case OGF_HOST_CTL:
1235 hci_cs_host_ctl(hdev, ocf, cs->status);
1236 break;
1237
1238 case OGF_LINK_CTL:
1239 hci_cs_link_ctl(hdev, ocf, cs->status);
1240 break;
1241
1242 case OGF_LINK_POLICY:
1243 hci_cs_link_policy(hdev, ocf, cs->status);
1244 break;
1245
1246 default:
1247 BT_DBG("%s Command Status OGF %x", hdev->name, ogf);
1248 break;
1249 }
1250
1251 if (cs->ncmd) {
1252 atomic_set(&hdev->cmd_cnt, 1);
1253 if (!skb_queue_empty(&hdev->cmd_q))
1254 hci_sched_cmd(hdev);
1255 }
1256 break;
1257
1258 case HCI_EV_CMD_COMPLETE:
1259 ec = (struct hci_ev_cmd_complete *) skb->data;
1260 skb_pull(skb, sizeof(*ec));
1261
1262 opcode = __le16_to_cpu(ec->opcode);
1263 ogf = hci_opcode_ogf(opcode);
1264 ocf = hci_opcode_ocf(opcode);
1265
1266 switch (ogf) {
1267 case OGF_INFO_PARAM:
1268 hci_cc_info_param(hdev, ocf, skb);
1269 break;
1270
1271 case OGF_HOST_CTL:
1272 hci_cc_host_ctl(hdev, ocf, skb);
1273 break;
1274
1275 case OGF_LINK_CTL:
1276 hci_cc_link_ctl(hdev, ocf, skb);
1277 break;
1278
1279 case OGF_LINK_POLICY:
1280 hci_cc_link_policy(hdev, ocf, skb);
1281 break;
1282
1283 default:
1284 BT_DBG("%s Command Completed OGF %x", hdev->name, ogf);
1285 break;
1286 }
1287
1288 if (ec->ncmd) {
1289 atomic_set(&hdev->cmd_cnt, 1);
1290 if (!skb_queue_empty(&hdev->cmd_q))
1291 hci_sched_cmd(hdev);
1292 }
1293 break;
1294 }
1295
1296 kfree_skb(skb);
1297 hdev->stat.evt_rx++;
1298}
1299
1300/* Generate internal stack event */
1301void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
1302{
1303 struct hci_event_hdr *hdr;
1304 struct hci_ev_stack_internal *ev;
1305 struct sk_buff *skb;
1306
1307 skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
1308 if (!skb)
1309 return;
1310
1311 hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
1312 hdr->evt = HCI_EV_STACK_INTERNAL;
1313 hdr->plen = sizeof(*ev) + dlen;
1314
1315 ev = (void *) skb_put(skb, sizeof(*ev) + dlen);
1316 ev->type = type;
1317 memcpy(ev->data, data, dlen);
1318
Marcel Holtmann576c7d82005-08-06 12:36:54 +02001319 bt_cb(skb)->incoming = 1;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001320 __net_timestamp(skb);
Marcel Holtmann576c7d82005-08-06 12:36:54 +02001321
Marcel Holtmann0d48d932005-08-09 20:30:28 -07001322 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 skb->dev = (void *) hdev;
1324 hci_send_to_sock(hdev, skb);
1325 kfree_skb(skb);
1326}