This source file includes following definitions.
- hci_eventstr
- hci_event
- hci_event_command_status
- hci_event_command_compl
- hci_event_num_compl_pkts
- hci_event_inquiry_result
- hci_event_con_compl
- hci_event_discon_compl
- hci_event_con_req
- hci_event_auth_compl
- hci_event_encryption_change
- hci_event_change_con_link_key_compl
- hci_cmd_read_bdaddr
- hci_cmd_read_buffer_size
- hci_cmd_read_local_features
- hci_cmd_reset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <sys/cdefs.h>
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/mbuf.h>
40 #include <sys/proc.h>
41 #include <sys/systm.h>
42
43 #include <netbt/bluetooth.h>
44 #include <netbt/hci.h>
45 #include <netbt/sco.h>
46
47 static void hci_event_inquiry_result(struct hci_unit *, struct mbuf *);
48 static void hci_event_command_status(struct hci_unit *, struct mbuf *);
49 static void hci_event_command_compl(struct hci_unit *, struct mbuf *);
50 static void hci_event_con_compl(struct hci_unit *, struct mbuf *);
51 static void hci_event_discon_compl(struct hci_unit *, struct mbuf *);
52 static void hci_event_con_req(struct hci_unit *, struct mbuf *);
53 static void hci_event_num_compl_pkts(struct hci_unit *, struct mbuf *);
54 static void hci_event_auth_compl(struct hci_unit *, struct mbuf *);
55 static void hci_event_encryption_change(struct hci_unit *, struct mbuf *);
56 static void hci_event_change_con_link_key_compl(struct hci_unit *, struct mbuf *);
57 static void hci_cmd_read_bdaddr(struct hci_unit *, struct mbuf *);
58 static void hci_cmd_read_buffer_size(struct hci_unit *, struct mbuf *);
59 static void hci_cmd_read_local_features(struct hci_unit *, struct mbuf *);
60 static void hci_cmd_reset(struct hci_unit *, struct mbuf *);
61
62 #ifdef BLUETOOTH_DEBUG
63 int bluetooth_debug = 0;
64
65 static const char *hci_eventnames[] = {
66 "NULL",
67 "INQUIRY COMPLETE",
68 "INQUIRY RESULT",
69 "CONN COMPLETE",
70 "CONN REQ",
71 "DISCONN COMPLETE",
72 "AUTH COMPLETE",
73 "REMOTE NAME REQ COMPLETE",
74 "ENCRYPTION CHANGE",
75 "CHANGE CONN LINK KEY COMPLETE",
76 "MASTER LINK KEY COMPLETE",
77 "READ REMOTE FEATURES COMPLETE",
78 "READ REMOTE VERSION INFO COMPLETE",
79 "QoS SETUP COMPLETE",
80 "COMMAND COMPLETE",
81 "COMMAND STATUS",
82 "HARDWARE ERROR",
83 "FLUSH OCCUR",
84 "ROLE CHANGE",
85 "NUM COMPLETED PACKETS",
86 "MODE CHANGE",
87 "RETURN LINK KEYS",
88 "PIN CODE REQ",
89 "LINK KEY REQ",
90 "LINK KEY NOTIFICATION",
91 "LOOPBACK COMMAND",
92 "DATA BUFFER OVERFLOW",
93 "MAX SLOT CHANGE",
94 "READ CLOCK OFFSET COMPLETE",
95 "CONN PKT TYPE CHANGED",
96 "QOS VIOLATION",
97 "PAGE SCAN MODE CHANGE",
98 "PAGE SCAN REP MODE CHANGE",
99 "FLOW SPECIFICATION COMPLETE",
100 "RSSI RESULT",
101 "READ REMOTE EXT FEATURES"
102 };
103
104 static const char *
105 hci_eventstr(unsigned int event)
106 {
107
108 if (event < (sizeof(hci_eventnames) / sizeof(*hci_eventnames)))
109 return hci_eventnames[event];
110
111 switch (event) {
112 case HCI_EVENT_SCO_CON_COMPL:
113 return "SCO CON COMPLETE";
114
115 case HCI_EVENT_SCO_CON_CHANGED:
116 return "SCO CON CHANGED";
117
118 case HCI_EVENT_BT_LOGO:
119 return "BT_LOGO";
120
121 case HCI_EVENT_VENDOR:
122 return "VENDOR";
123 }
124
125 return "UNRECOGNISED";
126 }
127 #endif
128
129
130
131
132
133
134
135
136
137 void
138 hci_event(struct mbuf *m, struct hci_unit *unit)
139 {
140 hci_event_hdr_t hdr;
141
142 KASSERT(m->m_flags & M_PKTHDR);
143
144 KASSERT(m->m_pkthdr.len >= sizeof(hdr));
145 m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
146 m_adj(m, sizeof(hdr));
147
148 KASSERT(hdr.type == HCI_EVENT_PKT);
149
150 DPRINTFN(1, "(%s) event %s\n", unit->hci_devname, hci_eventstr(hdr.event));
151
152 switch(hdr.event) {
153 case HCI_EVENT_COMMAND_STATUS:
154 hci_event_command_status(unit, m);
155 break;
156
157 case HCI_EVENT_COMMAND_COMPL:
158 hci_event_command_compl(unit, m);
159 break;
160
161 case HCI_EVENT_NUM_COMPL_PKTS:
162 hci_event_num_compl_pkts(unit, m);
163 break;
164
165 case HCI_EVENT_INQUIRY_RESULT:
166 hci_event_inquiry_result(unit, m);
167 break;
168
169 case HCI_EVENT_CON_COMPL:
170 hci_event_con_compl(unit, m);
171 break;
172
173 case HCI_EVENT_DISCON_COMPL:
174 hci_event_discon_compl(unit, m);
175 break;
176
177 case HCI_EVENT_CON_REQ:
178 hci_event_con_req(unit, m);
179 break;
180
181 case HCI_EVENT_AUTH_COMPL:
182 hci_event_auth_compl(unit, m);
183 break;
184
185 case HCI_EVENT_ENCRYPTION_CHANGE:
186 hci_event_encryption_change(unit, m);
187 break;
188
189 case HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL:
190 hci_event_change_con_link_key_compl(unit, m);
191 break;
192
193 case HCI_EVENT_SCO_CON_COMPL:
194 case HCI_EVENT_INQUIRY_COMPL:
195 case HCI_EVENT_REMOTE_NAME_REQ_COMPL:
196 case HCI_EVENT_MASTER_LINK_KEY_COMPL:
197 case HCI_EVENT_READ_REMOTE_FEATURES_COMPL:
198 case HCI_EVENT_READ_REMOTE_VER_INFO_COMPL:
199 case HCI_EVENT_QOS_SETUP_COMPL:
200 case HCI_EVENT_HARDWARE_ERROR:
201 case HCI_EVENT_FLUSH_OCCUR:
202 case HCI_EVENT_ROLE_CHANGE:
203 case HCI_EVENT_MODE_CHANGE:
204 case HCI_EVENT_RETURN_LINK_KEYS:
205 case HCI_EVENT_PIN_CODE_REQ:
206 case HCI_EVENT_LINK_KEY_REQ:
207 case HCI_EVENT_LINK_KEY_NOTIFICATION:
208 case HCI_EVENT_LOOPBACK_COMMAND:
209 case HCI_EVENT_DATA_BUFFER_OVERFLOW:
210 case HCI_EVENT_MAX_SLOT_CHANGE:
211 case HCI_EVENT_READ_CLOCK_OFFSET_COMPL:
212 case HCI_EVENT_CON_PKT_TYPE_CHANGED:
213 case HCI_EVENT_QOS_VIOLATION:
214 case HCI_EVENT_PAGE_SCAN_MODE_CHANGE:
215 case HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE:
216 case HCI_EVENT_FLOW_SPECIFICATION_COMPL:
217 case HCI_EVENT_RSSI_RESULT:
218 case HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES:
219 case HCI_EVENT_SCO_CON_CHANGED:
220 case HCI_EVENT_BT_LOGO:
221 case HCI_EVENT_VENDOR:
222 break;
223
224 default:
225 UNKNOWN(hdr.event);
226 break;
227 }
228
229 m_freem(m);
230 }
231
232
233
234
235
236
237
238 static void
239 hci_event_command_status(struct hci_unit *unit, struct mbuf *m)
240 {
241 hci_command_status_ep ep;
242 struct hci_link *link;
243
244 KASSERT(m->m_pkthdr.len >= sizeof(ep));
245 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
246 m_adj(m, sizeof(ep));
247
248 DPRINTFN(1, "(%s) opcode (%03x|%04x) status = 0x%x num_cmd_pkts = %d\n",
249 unit->hci_devname,
250 HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
251 ep.status,
252 ep.num_cmd_pkts);
253
254 unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
255
256
257
258
259 switch(letoh16(ep.opcode)) {
260 case HCI_CMD_CREATE_CON:
261 switch (ep.status) {
262 case 0x12:
263 DPRINTF("(%s) Invalid HCI command parameters\n",
264 unit->hci_devname);
265 while ((link = hci_link_lookup_state(unit,
266 HCI_LINK_ACL, HCI_LINK_WAIT_CONNECT)) != NULL)
267 hci_link_free(link, ECONNABORTED);
268 break;
269 }
270 break;
271 default:
272 break;
273 }
274
275 while (unit->hci_num_cmd_pkts > 0 && !IF_IS_EMPTY(&unit->hci_cmdwait)) {
276 IF_DEQUEUE(&unit->hci_cmdwait, m);
277 hci_output_cmd(unit, m);
278 }
279 }
280
281
282
283
284
285
286
287 static void
288 hci_event_command_compl(struct hci_unit *unit, struct mbuf *m)
289 {
290 hci_command_compl_ep ep;
291
292 KASSERT(m->m_pkthdr.len >= sizeof(ep));
293 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
294 m_adj(m, sizeof(ep));
295
296 DPRINTFN(1, "(%s) opcode (%03x|%04x) num_cmd_pkts = %d\n",
297 unit->hci_devname,
298 HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
299 ep.num_cmd_pkts);
300
301 unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
302
303
304
305
306 switch(letoh16(ep.opcode)) {
307 case HCI_CMD_READ_BDADDR:
308 hci_cmd_read_bdaddr(unit, m);
309 break;
310
311 case HCI_CMD_READ_BUFFER_SIZE:
312 hci_cmd_read_buffer_size(unit, m);
313 break;
314
315 case HCI_CMD_READ_LOCAL_FEATURES:
316 hci_cmd_read_local_features(unit, m);
317 break;
318
319 case HCI_CMD_RESET:
320 hci_cmd_reset(unit, m);
321 break;
322
323 default:
324 break;
325 }
326
327 while (unit->hci_num_cmd_pkts > 0 && !IF_IS_EMPTY(&unit->hci_cmdwait)) {
328 IF_DEQUEUE(&unit->hci_cmdwait, m);
329 hci_output_cmd(unit, m);
330 }
331 }
332
333
334
335
336
337
338
339
340
341
342 static void
343 hci_event_num_compl_pkts(struct hci_unit *unit, struct mbuf *m)
344 {
345 hci_num_compl_pkts_ep ep;
346 struct hci_link *link, *next;
347 uint16_t handle, num;
348 int num_acl = 0, num_sco = 0;
349
350 KASSERT(m->m_pkthdr.len >= sizeof(ep));
351 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
352 m_adj(m, sizeof(ep));
353
354 while (ep.num_con_handles--) {
355 m_copydata(m, 0, sizeof(handle), (caddr_t)&handle);
356 m_adj(m, sizeof(handle));
357 handle = letoh16(handle);
358
359 m_copydata(m, 0, sizeof(num), (caddr_t)&num);
360 m_adj(m, sizeof(num));
361 num = letoh16(num);
362
363 link = hci_link_lookup_handle(unit, handle);
364 if (link) {
365 if (link->hl_type == HCI_LINK_ACL) {
366 num_acl += num;
367 hci_acl_complete(link, num);
368 } else {
369 num_sco += num;
370 hci_sco_complete(link, num);
371 }
372 } else {
373
374 printf("%s: unknown handle %d! "
375 "(losing track of %d packet buffer%s)\n",
376 unit->hci_devname, handle,
377 num, (num == 1 ? "" : "s"));
378 }
379 }
380
381
382
383
384
385
386
387
388
389 unit->hci_num_acl_pkts += num_acl;
390 unit->hci_num_sco_pkts += num_sco;
391
392 link = TAILQ_FIRST(&unit->hci_links);
393 while (link && (unit->hci_num_acl_pkts > 0 || unit->hci_num_sco_pkts > 0)) {
394 next = TAILQ_NEXT(link, hl_next);
395
396 if (link->hl_type == HCI_LINK_ACL) {
397 if (unit->hci_num_acl_pkts > 0 && link->hl_txqlen > 0)
398 hci_acl_start(link);
399 } else {
400 if (unit->hci_num_sco_pkts > 0 && link->hl_txqlen > 0)
401 hci_sco_start(link);
402 }
403
404 link = next;
405 }
406 }
407
408
409
410
411
412
413
414 static void
415 hci_event_inquiry_result(struct hci_unit *unit, struct mbuf *m)
416 {
417 hci_inquiry_result_ep ep;
418 struct hci_memo *memo;
419 bdaddr_t bdaddr;
420
421 KASSERT(m->m_pkthdr.len >= sizeof(ep));
422 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
423 m_adj(m, sizeof(ep));
424
425 DPRINTFN(1, "%d response%s\n", ep.num_responses,
426 (ep.num_responses == 1 ? "" : "s"));
427
428 while(ep.num_responses--) {
429 m_copydata(m, 0, sizeof(bdaddr_t), (caddr_t)&bdaddr);
430
431 DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
432 bdaddr.b[5], bdaddr.b[4], bdaddr.b[3],
433 bdaddr.b[2], bdaddr.b[1], bdaddr.b[0]);
434
435 memo = hci_memo_find(unit, &bdaddr);
436 if (memo == NULL) {
437 memo = malloc(sizeof(struct hci_memo),
438 M_BLUETOOTH, M_NOWAIT);
439 if (memo == NULL) {
440 DPRINTFN(0, "out of memo memory!\n");
441 break;
442 }
443 bzero(memo, sizeof *memo);
444
445 LIST_INSERT_HEAD(&unit->hci_memos, memo, next);
446 }
447
448 microtime(&memo->time);
449 m_copydata(m, 0, sizeof(hci_inquiry_response),
450 (caddr_t)&memo->response);
451 m_adj(m, sizeof(hci_inquiry_response));
452
453 memo->response.clock_offset =
454 letoh16(memo->response.clock_offset);
455 }
456 }
457
458
459
460
461
462
463
464
465 static void
466 hci_event_con_compl(struct hci_unit *unit, struct mbuf *m)
467 {
468 hci_con_compl_ep ep;
469 hci_write_link_policy_settings_cp cp;
470 struct hci_link *link;
471 int err;
472
473 KASSERT(m->m_pkthdr.len >= sizeof(ep));
474 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
475 m_adj(m, sizeof(ep));
476
477 DPRINTFN(1, "(%s) %s connection complete for "
478 "%02x:%02x:%02x:%02x:%02x:%02x status %#x\n",
479 unit->hci_devname,
480 (ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"),
481 ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
482 ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
483 ep.status);
484
485 link = hci_link_lookup_bdaddr(unit, &ep.bdaddr, ep.link_type);
486
487 if (ep.status) {
488 if (link != NULL) {
489 switch (ep.status) {
490 case 0x04:
491 err = EHOSTDOWN;
492 break;
493
494 case 0x08:
495 case 0x10:
496 err = ETIMEDOUT;
497 break;
498
499 case 0x16:
500 err = 0;
501 break;
502
503 default:
504 err = ECONNREFUSED;
505 break;
506 }
507
508 hci_link_free(link, err);
509 }
510
511 return;
512 }
513
514 if (link == NULL) {
515 hci_discon_cp dp;
516
517 dp.con_handle = ep.con_handle;
518 dp.reason = 0x13;
519
520 hci_send_cmd(unit, HCI_CMD_DISCONNECT, &dp, sizeof(dp));
521 return;
522 }
523
524
525
526 if (ep.encryption_mode)
527 link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_ENCRYPT);
528
529 link->hl_state = HCI_LINK_OPEN;
530 link->hl_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
531
532 if (ep.link_type == HCI_LINK_ACL) {
533 cp.con_handle = ep.con_handle;
534 cp.settings = htole16(unit->hci_link_policy);
535 err = hci_send_cmd(unit, HCI_CMD_WRITE_LINK_POLICY_SETTINGS,
536 &cp, sizeof(cp));
537 if (err)
538 printf("%s: Warning, could not write link policy\n",
539 unit->hci_devname);
540
541 err = hci_acl_setmode(link);
542 if (err == EINPROGRESS)
543 return;
544
545 hci_acl_linkmode(link);
546 } else {
547 (*link->hl_sco->sp_proto->connected)(link->hl_sco->sp_upper);
548 }
549 }
550
551
552
553
554
555
556
557 static void
558 hci_event_discon_compl(struct hci_unit *unit, struct mbuf *m)
559 {
560 hci_discon_compl_ep ep;
561 struct hci_link *link;
562
563 KASSERT(m->m_pkthdr.len >= sizeof(ep));
564 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
565 m_adj(m, sizeof(ep));
566
567 ep.con_handle = letoh16(ep.con_handle);
568
569 DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
570
571 link = hci_link_lookup_handle(unit, HCI_CON_HANDLE(ep.con_handle));
572 if (link)
573 hci_link_free(link, ENOENT);
574 }
575
576
577
578
579
580
581
582 static void
583 hci_event_con_req(struct hci_unit *unit, struct mbuf *m)
584 {
585 hci_con_req_ep ep;
586 hci_accept_con_cp ap;
587 hci_reject_con_cp rp;
588 struct hci_link *link;
589
590 KASSERT(m->m_pkthdr.len >= sizeof(ep));
591 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
592 m_adj(m, sizeof(ep));
593
594 DPRINTFN(1, "bdaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
595 "class %2.2x%2.2x%2.2x type %s\n",
596 ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
597 ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
598 ep.uclass[0], ep.uclass[1], ep.uclass[2],
599 ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO");
600
601 if (ep.link_type == HCI_LINK_ACL)
602 link = hci_acl_newconn(unit, &ep.bdaddr);
603 else
604 link = hci_sco_newconn(unit, &ep.bdaddr);
605
606 if (link == NULL) {
607 memset(&rp, 0, sizeof(rp));
608 bdaddr_copy(&rp.bdaddr, &ep.bdaddr);
609 rp.reason = 0x0f;
610
611 hci_send_cmd(unit, HCI_CMD_REJECT_CON, &rp, sizeof(rp));
612 } else {
613 memset(&ap, 0, sizeof(ap));
614 bdaddr_copy(&ap.bdaddr, &ep.bdaddr);
615 if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
616 ap.role = HCI_ROLE_MASTER;
617 else
618 ap.role = HCI_ROLE_SLAVE;
619
620 hci_send_cmd(unit, HCI_CMD_ACCEPT_CON, &ap, sizeof(ap));
621 }
622 }
623
624
625
626
627
628
629
630 static void
631 hci_event_auth_compl(struct hci_unit *unit, struct mbuf *m)
632 {
633 hci_auth_compl_ep ep;
634 struct hci_link *link;
635 int err;
636
637 KASSERT(m->m_pkthdr.len >= sizeof(ep));
638 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
639 m_adj(m, sizeof(ep));
640
641 ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
642
643 DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
644
645 link = hci_link_lookup_handle(unit, ep.con_handle);
646 if (link == NULL || link->hl_type != HCI_LINK_ACL)
647 return;
648
649 if (ep.status == 0) {
650 link->hl_flags |= HCI_LINK_AUTH;
651
652 if (link->hl_state == HCI_LINK_WAIT_AUTH)
653 link->hl_state = HCI_LINK_OPEN;
654
655 err = hci_acl_setmode(link);
656 if (err == EINPROGRESS)
657 return;
658 }
659
660 hci_acl_linkmode(link);
661 }
662
663
664
665
666
667
668
669
670
671
672 static void
673 hci_event_encryption_change(struct hci_unit *unit, struct mbuf *m)
674 {
675 hci_encryption_change_ep ep;
676 struct hci_link *link;
677 int err;
678
679 KASSERT(m->m_pkthdr.len >= sizeof(ep));
680 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
681 m_adj(m, sizeof(ep));
682
683 ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
684
685 DPRINTFN(1, "handle #%d, status=0x%x, encryption_enable=0x%x\n",
686 ep.con_handle, ep.status, ep.encryption_enable);
687
688 link = hci_link_lookup_handle(unit, ep.con_handle);
689 if (link == NULL || link->hl_type != HCI_LINK_ACL)
690 return;
691
692 if (ep.status == 0) {
693 if (ep.encryption_enable == 0)
694 link->hl_flags &= ~HCI_LINK_ENCRYPT;
695 else
696 link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_ENCRYPT);
697
698 if (link->hl_state == HCI_LINK_WAIT_ENCRYPT)
699 link->hl_state = HCI_LINK_OPEN;
700
701 err = hci_acl_setmode(link);
702 if (err == EINPROGRESS)
703 return;
704 }
705
706 hci_acl_linkmode(link);
707 }
708
709
710
711
712
713
714
715
716 static void
717 hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m)
718 {
719 hci_change_con_link_key_compl_ep ep;
720 struct hci_link *link;
721 int err;
722
723 KASSERT(m->m_pkthdr.len >= sizeof(ep));
724 m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
725 m_adj(m, sizeof(ep));
726
727 ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
728
729 DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
730
731 link = hci_link_lookup_handle(unit, ep.con_handle);
732 if (link == NULL || link->hl_type != HCI_LINK_ACL)
733 return;
734
735 link->hl_flags &= ~HCI_LINK_SECURE_REQ;
736
737 if (ep.status == 0) {
738 link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_SECURE);
739
740 if (link->hl_state == HCI_LINK_WAIT_SECURE)
741 link->hl_state = HCI_LINK_OPEN;
742
743 err = hci_acl_setmode(link);
744 if (err == EINPROGRESS)
745 return;
746 }
747
748 hci_acl_linkmode(link);
749 }
750
751
752
753
754 static void
755 hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m)
756 {
757 hci_read_bdaddr_rp rp;
758 int s;
759
760 KASSERT(m->m_pkthdr.len >= sizeof(rp));
761 m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
762 m_adj(m, sizeof(rp));
763
764 if (rp.status > 0)
765 return;
766
767 if ((unit->hci_flags & BTF_INIT_BDADDR) == 0)
768 return;
769
770 bdaddr_copy(&unit->hci_bdaddr, &rp.bdaddr);
771
772 s = splraiseipl(unit->hci_ipl);
773 unit->hci_flags &= ~BTF_INIT_BDADDR;
774 splx(s);
775
776 wakeup(unit);
777 }
778
779
780
781
782 static void
783 hci_cmd_read_buffer_size(struct hci_unit *unit, struct mbuf *m)
784 {
785 hci_read_buffer_size_rp rp;
786 int s;
787
788 KASSERT(m->m_pkthdr.len >= sizeof(rp));
789 m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
790 m_adj(m, sizeof(rp));
791
792 if (rp.status > 0)
793 return;
794
795 if ((unit->hci_flags & BTF_INIT_BUFFER_SIZE) == 0)
796 return;
797
798 unit->hci_max_acl_size = letoh16(rp.max_acl_size);
799 unit->hci_num_acl_pkts = letoh16(rp.num_acl_pkts);
800 unit->hci_max_sco_size = rp.max_sco_size;
801 unit->hci_num_sco_pkts = letoh16(rp.num_sco_pkts);
802
803 s = splraiseipl(unit->hci_ipl);
804 unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE;
805 splx(s);
806
807 wakeup(unit);
808 }
809
810
811
812
813 static void
814 hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m)
815 {
816 hci_read_local_features_rp rp;
817 int s;
818
819 KASSERT(m->m_pkthdr.len >= sizeof(rp));
820 m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
821 m_adj(m, sizeof(rp));
822
823 if (rp.status > 0)
824 return;
825
826 if ((unit->hci_flags & BTF_INIT_FEATURES) == 0)
827 return;
828
829 unit->hci_lmp_mask = 0;
830
831 if (rp.features[0] & HCI_LMP_ROLE_SWITCH)
832 unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_ROLE_SWITCH;
833
834 if (rp.features[0] & HCI_LMP_HOLD_MODE)
835 unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_HOLD_MODE;
836
837 if (rp.features[0] & HCI_LMP_SNIFF_MODE)
838 unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_SNIFF_MODE;
839
840 if (rp.features[1] & HCI_LMP_PARK_MODE)
841 unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_PARK_MODE;
842
843
844 unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1;
845
846 if (rp.features[0] & HCI_LMP_3SLOT)
847 unit->hci_acl_mask |= HCI_PKT_DM3 | HCI_PKT_DH3;
848
849 if (rp.features[0] & HCI_LMP_5SLOT)
850 unit->hci_acl_mask |= HCI_PKT_DM5 | HCI_PKT_DH5;
851
852 if ((rp.features[3] & HCI_LMP_EDR_ACL_2MBPS) == 0)
853 unit->hci_acl_mask |= HCI_PKT_2MBPS_DH1
854 | HCI_PKT_2MBPS_DH3
855 | HCI_PKT_2MBPS_DH5;
856
857 if ((rp.features[3] & HCI_LMP_EDR_ACL_3MBPS) == 0)
858 unit->hci_acl_mask |= HCI_PKT_3MBPS_DH1
859 | HCI_PKT_3MBPS_DH3
860 | HCI_PKT_3MBPS_DH5;
861
862 if ((rp.features[4] & HCI_LMP_3SLOT_EDR_ACL) == 0)
863 unit->hci_acl_mask |= HCI_PKT_2MBPS_DH3
864 | HCI_PKT_3MBPS_DH3;
865
866 if ((rp.features[5] & HCI_LMP_5SLOT_EDR_ACL) == 0)
867 unit->hci_acl_mask |= HCI_PKT_2MBPS_DH5
868 | HCI_PKT_3MBPS_DH5;
869
870 unit->hci_packet_type = unit->hci_acl_mask;
871
872
873 unit->hci_sco_mask = 0;
874 if (rp.features[1] & HCI_LMP_SCO_LINK)
875 unit->hci_sco_mask |= HCI_PKT_HV1;
876
877 if (rp.features[1] & HCI_LMP_HV2_PKT)
878 unit->hci_sco_mask |= HCI_PKT_HV2;
879
880 if (rp.features[1] & HCI_LMP_HV3_PKT)
881 unit->hci_sco_mask |= HCI_PKT_HV3;
882
883 if (rp.features[3] & HCI_LMP_EV3_PKT)
884 unit->hci_sco_mask |= HCI_PKT_EV3;
885
886 if (rp.features[4] & HCI_LMP_EV4_PKT)
887 unit->hci_sco_mask |= HCI_PKT_EV4;
888
889 if (rp.features[4] & HCI_LMP_EV5_PKT)
890 unit->hci_sco_mask |= HCI_PKT_EV5;
891
892
893
894 s = splraiseipl(unit->hci_ipl);
895 unit->hci_flags &= ~BTF_INIT_FEATURES;
896 splx(s);
897
898 wakeup(unit);
899
900 DPRINTFN(1, "%s: lmp_mask %4.4x, acl_mask %4.4x, sco_mask %4.4x\n",
901 unit->hci_devname, unit->hci_lmp_mask,
902 unit->hci_acl_mask, unit->hci_sco_mask);
903 }
904
905
906
907
908
909
910
911 static void
912 hci_cmd_reset(struct hci_unit *unit, struct mbuf *m)
913 {
914 hci_reset_rp rp;
915 struct hci_link *link, *next;
916 int acl;
917
918 KASSERT(m->m_pkthdr.len >= sizeof(rp));
919 m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
920 m_adj(m, sizeof(rp));
921
922 if (rp.status != 0)
923 return;
924
925
926
927
928
929 for (acl = 0 ; acl < 2 ; acl++) {
930 next = TAILQ_FIRST(&unit->hci_links);
931 while ((link = next) != NULL) {
932 next = TAILQ_NEXT(link, hl_next);
933 if (acl || link->hl_type != HCI_LINK_ACL)
934 hci_link_free(link, ECONNABORTED);
935 }
936 }
937
938 unit->hci_num_acl_pkts = 0;
939 unit->hci_num_sco_pkts = 0;
940
941 if (hci_send_cmd(unit, HCI_CMD_READ_BDADDR, NULL, 0))
942 return;
943
944 if (hci_send_cmd(unit, HCI_CMD_READ_BUFFER_SIZE, NULL, 0))
945 return;
946
947 if (hci_send_cmd(unit, HCI_CMD_READ_LOCAL_FEATURES, NULL, 0))
948 return;
949 }