hci_link.c revision 1.1 1 /* $NetBSD: hci_link.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */
2
3 /*-
4 * Copyright (c) 2005 Iain Hibbert.
5 * Copyright (c) 2006 Itronix Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of Itronix Inc. may not be used to endorse
17 * or promote products derived from this software without specific
18 * prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: hci_link.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $");
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/queue.h>
42 #include <sys/systm.h>
43
44 #include <netbt/bluetooth.h>
45 #include <netbt/hci.h>
46 #include <netbt/sco.h>
47 #include <netbt/l2cap.h>
48
49 /*******************************************************************************
50 *
51 * HCI ACL Connections
52 */
53
54 /*
55 * Automatically expire unused ACL connections after this number of
56 * seconds (if zero, do not expire unused connections) [sysctl]
57 */
58 int hci_acl_expiry = 10; /* seconds */
59
60 /*
61 * hci_acl_open(unit, bdaddr)
62 *
63 * open ACL connection to remote bdaddr. Only one ACL connection is permitted
64 * between any two Bluetooth devices, so we look for an existing one before
65 * trying to start a new one.
66 */
67 struct hci_link *
68 hci_acl_open(struct hci_unit *unit, bdaddr_t *bdaddr)
69 {
70 struct hci_link *link;
71 hci_create_con_cp cp;
72 int err;
73
74 KASSERT(unit);
75 KASSERT(bdaddr);
76
77 link = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
78 if (link == NULL) {
79 link = hci_link_alloc(unit);
80 if (link == NULL)
81 return NULL;
82
83 link->hl_type = HCI_LINK_ACL;
84 bdaddr_copy(&link->hl_bdaddr, bdaddr);
85 }
86
87 switch(link->hl_state) {
88 case HCI_LINK_CLOSED:
89 /*
90 * open connection to remote device
91 */
92 memset(&cp, 0, sizeof(cp));
93 bdaddr_copy(&cp.bdaddr, bdaddr);
94 cp.pkt_type = htole16(unit->hci_packet_type);
95 if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
96 cp.accept_role_switch = 1;
97
98 err = hci_send_cmd(unit, HCI_CMD_CREATE_CON, &cp, sizeof(cp));
99 if (err) {
100 hci_link_free(link, err);
101 return NULL;
102 }
103
104 link->hl_state = HCI_LINK_WAIT_CONNECT;
105 break;
106
107 case HCI_LINK_WAIT_CONNECT:
108 /*
109 * somebody else already trying to connect, we just
110 * sit on the bench with them..
111 */
112 break;
113
114 case HCI_LINK_OPEN:
115 /*
116 * If already open, halt any expiry timeouts. We dont need
117 * to care about already invoking timeouts since refcnt >0
118 * will keep the link alive.
119 */
120 callout_stop(&link->hl_expire);
121 break;
122
123 default:
124 UNKNOWN(link->hl_state);
125 return NULL;
126 }
127
128 /* open */
129 link->hl_refcnt++;
130
131 return link;
132 }
133
134 /*
135 * Close ACL connection. When there are no more references to this link,
136 * we can either close it down or schedule a delayed closedown.
137 */
138 void
139 hci_acl_close(struct hci_link *link, int err)
140 {
141
142 KASSERT(link);
143
144 if (--link->hl_refcnt == 0) {
145 if (link->hl_state == HCI_LINK_CLOSED)
146 hci_link_free(link, err);
147 else if (hci_acl_expiry > 0)
148 callout_schedule(&link->hl_expire, hci_acl_expiry * hz);
149 }
150 }
151
152 /*
153 * Incoming ACL connection. For now, we accept all connections but it
154 * would be better to check the L2CAP listen list and only accept when
155 * there is a listener available.
156 */
157 struct hci_link *
158 hci_acl_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
159 {
160 struct hci_link *link;
161
162 link = hci_link_alloc(unit);
163 if (link != NULL) {
164 link->hl_state = HCI_LINK_WAIT_CONNECT;
165 link->hl_type = HCI_LINK_ACL;
166 bdaddr_copy(&link->hl_bdaddr, bdaddr);
167
168 if (hci_acl_expiry > 0)
169 callout_schedule(&link->hl_expire, hci_acl_expiry * hz);
170 }
171
172 return link;
173 }
174
175 void
176 hci_acl_timeout(void *arg)
177 {
178 struct hci_link *link = arg;
179 hci_discon_cp cp;
180 int s, err;
181
182 s = splsoftnet();
183 callout_ack(&link->hl_expire);
184
185 if (link->hl_refcnt > 0)
186 goto out;
187
188 DPRINTF("link #%d expired\n", link->hl_handle);
189
190 switch (link->hl_state) {
191 case HCI_LINK_CLOSED:
192 case HCI_LINK_WAIT_CONNECT:
193 hci_link_free(link, ECONNRESET);
194 break;
195
196 case HCI_LINK_OPEN:
197 cp.con_handle = htole16(link->hl_handle);
198 cp.reason = 0x13; /* "Remote User Terminated Connection" */
199
200 err = hci_send_cmd(link->hl_unit, HCI_CMD_DISCONNECT,
201 &cp, sizeof(cp));
202
203 if (err)
204 DPRINTF("error %d sending HCI_CMD_DISCONNECT\n",
205 err);
206
207 break;
208
209 default:
210 UNKNOWN(link->hl_state);
211 break;
212 }
213
214 out:
215 splx(s);
216 }
217
218 /*
219 * Receive ACL Data
220 *
221 * we accumulate packet fragments on the hci_link structure
222 * until a full L2CAP frame is ready, then send it on.
223 */
224 void
225 hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
226 {
227 struct hci_link *link;
228 hci_acldata_hdr_t hdr;
229 uint16_t handle, want;
230 int pb, got;
231
232 KASSERT(m);
233 KASSERT(unit);
234
235 KASSERT(m->m_pkthdr.len >= sizeof(hdr));
236 m_copydata(m, 0, sizeof(hdr), &hdr);
237 m_adj(m, sizeof(hdr));
238
239 #ifdef DIAGNOSTIC
240 if (hdr.type != HCI_ACL_DATA_PKT) {
241 printf("%s: bad ACL packet type\n", unit->hci_devname);
242 goto bad;
243 }
244
245 if (m->m_pkthdr.len != le16toh(hdr.length)) {
246 printf("%s: bad ACL packet length\n", unit->hci_devname);
247 goto bad;
248 }
249 #endif
250
251 hdr.length = le16toh(hdr.length);
252 hdr.con_handle = le16toh(hdr.con_handle);
253 handle = HCI_CON_HANDLE(hdr.con_handle);
254 pb = HCI_PB_FLAG(hdr.con_handle);
255
256 link = hci_link_lookup_handle(unit, handle);
257 if (link == NULL) {
258 hci_discon_cp cp;
259
260 DPRINTF("%s: dumping packet for unknown handle #%d\n",
261 unit->hci_devname, handle);
262
263 /*
264 * There is no way to find out what this connection handle is
265 * for, just get rid of it. This may happen, if a USB dongle
266 * is plugged into a self powered hub and does not reset when
267 * the system is shut down.
268 */
269 cp.con_handle = htole16(handle);
270 cp.reason = 0x13; /* "Remote User Terminated Connection" */
271 hci_send_cmd(unit, HCI_CMD_DISCONNECT, &cp, sizeof(cp));
272 goto bad;
273 }
274
275 switch (pb) {
276 case HCI_PACKET_START:
277 if (link->hl_rxp != NULL)
278 printf("%s: dropped incomplete ACL packet\n",
279 unit->hci_devname);
280
281 if (m->m_pkthdr.len < sizeof(l2cap_hdr_t)) {
282 printf("%s: short ACL packet\n",
283 unit->hci_devname);
284
285 goto bad;
286 }
287
288 link->hl_rxp = m;
289 got = m->m_pkthdr.len;
290 break;
291
292 case HCI_PACKET_FRAGMENT:
293 if (link->hl_rxp == NULL) {
294 printf("%s: unexpected packet fragment\n",
295 unit->hci_devname);
296
297 goto bad;
298 }
299
300 got = m->m_pkthdr.len + link->hl_rxp->m_pkthdr.len;
301 m_cat(link->hl_rxp, m);
302 m = link->hl_rxp;
303 m->m_pkthdr.len = got;
304 break;
305
306 default:
307 printf("%s: unknown packet type\n",
308 unit->hci_devname);
309
310 goto bad;
311 }
312
313 m_copydata(m, 0, sizeof(want), &want);
314 want = le16toh(want) + sizeof(l2cap_hdr_t) - got;
315
316 if (want > 0)
317 return;
318
319 link->hl_rxp = NULL;
320
321 if (want == 0) {
322 l2cap_recv_frame(m, link);
323 return;
324 }
325
326 bad:
327 m_freem(m);
328 }
329
330 /*
331 * Send ACL data on link
332 *
333 * We must fragment packets into chunks of less than unit->hci_max_acl_size and
334 * prepend a relevant ACL header to each fragment. We keep a PDU structure
335 * attached to the link, so that completed fragments can be marked off and
336 * more data requested from above once the PDU is sent.
337 */
338 int
339 hci_acl_send(struct mbuf *m, struct hci_link *link,
340 struct l2cap_channel *chan)
341 {
342 struct l2cap_pdu *pdu;
343 struct mbuf *n = NULL;
344 int plen, mlen, num = 0;
345
346 KASSERT(link);
347 KASSERT(m);
348 KASSERT(m->m_flags & M_PKTHDR);
349 KASSERT(m->m_pkthdr.len > 0);
350
351 if (link->hl_state == HCI_LINK_CLOSED) {
352 m_freem(m);
353 return ENETDOWN;
354 }
355
356 pdu = pool_get(&l2cap_pdu_pool, PR_NOWAIT);
357 if (pdu == NULL)
358 goto nomem;
359
360 pdu->lp_chan = chan;
361 pdu->lp_pending = 0;
362 MBUFQ_INIT(&pdu->lp_data);
363
364 plen = m->m_pkthdr.len;
365 mlen = link->hl_unit->hci_max_acl_size;
366
367 DPRINTFN(5, "%s: handle #%d, plen = %d, max = %d\n",
368 link->hl_unit->hci_devname, link->hl_handle, plen, mlen);
369
370 while (plen > 0) {
371 if (plen > mlen) {
372 n = m_split(m, mlen, M_DONTWAIT);
373 if (n == NULL)
374 goto nomem;
375 } else {
376 mlen = plen;
377 }
378
379 if (num++ == 0)
380 m->m_flags |= M_PROTO1; /* tag first fragment */
381
382 DPRINTFN(10, "chunk of %d (plen = %d) bytes\n", mlen, plen);
383 MBUFQ_ENQUEUE(&pdu->lp_data, m);
384 m = n;
385 plen -= mlen;
386 }
387
388 TAILQ_INSERT_TAIL(&link->hl_txq, pdu, lp_next);
389 link->hl_txqlen += num;
390
391 hci_acl_start(link);
392
393 return 0;
394
395 nomem:
396 if (m) m_freem(m);
397 if (n) m_freem(n);
398 if (pdu) {
399 MBUFQ_DRAIN(&pdu->lp_data);
400 pool_put(&l2cap_pdu_pool, pdu);
401 }
402
403 return ENOMEM;
404 }
405
406 /*
407 * Start sending ACL data on link.
408 *
409 * We may use all the available packet slots. The reason that we add
410 * the ACL encapsulation here rather than in hci_acl_send() is that L2CAP
411 * signal packets may be queued before the handle is given to us..
412 *
413 * this is called from hci_acl_send() above, and the event processing
414 * code (for CON_COMPL and NUM_COMPL_PKTS)
415 */
416 void
417 hci_acl_start(struct hci_link *link)
418 {
419 struct hci_unit *unit;
420 hci_acldata_hdr_t *hdr;
421 struct l2cap_pdu *pdu;
422 struct mbuf *m;
423 uint16_t handle;
424
425 KASSERT(link);
426
427 unit = link->hl_unit;
428 KASSERT(unit);
429
430 /* this is mainly to block ourselves (below) */
431 if (link->hl_state != HCI_LINK_OPEN)
432 return;
433
434 if (link->hl_txqlen == 0 || unit->hci_num_acl_pkts == 0)
435 return;
436
437 /* find first PDU with data to send */
438 pdu = TAILQ_FIRST(&link->hl_txq);
439 for (;;) {
440 if (pdu == NULL)
441 return;
442
443 if (MBUFQ_FIRST(&pdu->lp_data) != NULL)
444 break;
445
446 pdu = TAILQ_NEXT(pdu, lp_next);
447 }
448
449 while (unit->hci_num_acl_pkts > 0) {
450 MBUFQ_DEQUEUE(&pdu->lp_data, m);
451 KASSERT(m != NULL);
452
453 if (m->m_flags & M_PROTO1)
454 handle = HCI_MK_CON_HANDLE(link->hl_handle,
455 HCI_PACKET_START, 0);
456 else
457 handle = HCI_MK_CON_HANDLE(link->hl_handle,
458 HCI_PACKET_FRAGMENT, 0);
459
460 M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
461 if (m == NULL)
462 break;
463
464 hdr = mtod(m, hci_acldata_hdr_t *);
465 hdr->type = HCI_ACL_DATA_PKT;
466 hdr->con_handle = htole16(handle);
467 hdr->length = htole16(m->m_pkthdr.len - sizeof(*hdr));
468
469 link->hl_txqlen--;
470 pdu->lp_pending++;
471
472 hci_output_acl(unit, m);
473
474 if (MBUFQ_FIRST(&pdu->lp_data) == NULL) {
475 if (pdu->lp_chan) {
476 /*
477 * This should enable streaming of PDUs - when
478 * we have placed all the fragments on the acl
479 * output queue, we trigger the L2CAP layer to
480 * send us down one more. Use a false state so
481 * we dont run into ourselves coming back from
482 * the future..
483 */
484 link->hl_state = HCI_LINK_BLOCK;
485 l2cap_start(pdu->lp_chan);
486 link->hl_state = HCI_LINK_OPEN;
487 }
488
489 pdu = TAILQ_NEXT(pdu, lp_next);
490 if (pdu == NULL)
491 break;
492 }
493 }
494
495 /*
496 * We had our turn now, move to the back of the queue to let
497 * other links have a go at the output buffers..
498 */
499 if (TAILQ_NEXT(link, hl_next)) {
500 TAILQ_REMOVE(&unit->hci_links, link, hl_next);
501 TAILQ_INSERT_TAIL(&unit->hci_links, link, hl_next);
502 }
503 }
504
505 /*
506 * Confirm ACL packets cleared from Controller buffers. We scan our PDU
507 * list to clear pending fragments and signal upstream for more data
508 * when a PDU is complete.
509 */
510 void
511 hci_acl_complete(struct hci_link *link, int num)
512 {
513 struct l2cap_pdu *pdu;
514 struct l2cap_channel *chan;
515
516 DPRINTFN(5, "handle #%d (%d)\n", link->hl_handle, num);
517
518 while (num > 0) {
519 pdu = TAILQ_FIRST(&link->hl_txq);
520 if (pdu == NULL) {
521 printf("%s: %d packets completed on handle #%x "
522 "but none pending!\n",
523 link->hl_unit->hci_devname, num,
524 link->hl_handle);
525 return;
526 }
527
528 if (num >= pdu->lp_pending) {
529 num -= pdu->lp_pending;
530 pdu->lp_pending = 0;
531
532 if (MBUFQ_FIRST(&pdu->lp_data) == NULL) {
533 TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
534 chan = pdu->lp_chan;
535 if (chan != NULL) {
536 chan->lc_pending--;
537 (*chan->lc_proto->complete)
538 (chan->lc_upper, 1);
539
540 if (chan->lc_pending == 0)
541 l2cap_start(chan);
542 }
543
544 pool_put(&l2cap_pdu_pool, pdu);
545 }
546 } else {
547 pdu->lp_pending -= num;
548 num = 0;
549 }
550 }
551 }
552
553 /*******************************************************************************
554 *
555 * HCI SCO Connections
556 */
557
558 /*
559 * Incoming SCO Connection. Not yet implemented
560 */
561 struct hci_link *
562 hci_sco_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
563 {
564
565 return NULL;
566 }
567
568 /*
569 * receive SCO packet, we only need to strip the header and send
570 * it to the right handler
571 */
572 void
573 hci_sco_recv(struct mbuf *m, struct hci_unit *unit)
574 {
575 struct hci_link *link;
576 hci_scodata_hdr_t hdr;
577 uint16_t handle;
578
579 KASSERT(m);
580 KASSERT(unit);
581
582 KASSERT(m->m_pkthdr.len >= sizeof(hdr));
583 m_copydata(m, 0, sizeof(hdr), &hdr);
584 m_adj(m, sizeof(hdr));
585
586 #ifdef DIAGNOSTIC
587 if (hdr.type != HCI_SCO_DATA_PKT) {
588 printf("%s: bad SCO packet type\n", unit->hci_devname);
589 goto bad;
590 }
591
592 if (m->m_pkthdr.len != hdr.length) {
593 printf("%s: bad SCO packet length (%d != %d)\n", unit->hci_devname, m->m_pkthdr.len, hdr.length);
594 goto bad;
595 }
596 #endif
597
598 hdr.con_handle = le16toh(hdr.con_handle);
599 handle = HCI_CON_HANDLE(hdr.con_handle);
600
601 link = hci_link_lookup_handle(unit, handle);
602 if (link == NULL || link->hl_type == HCI_LINK_ACL) {
603 DPRINTF("%s: dumping packet for unknown handle #%d\n",
604 unit->hci_devname, handle);
605
606 goto bad;
607 }
608
609 (*link->hl_sco->sp_proto->input)(link->hl_sco->sp_upper, m);
610 return;
611
612 bad:
613 m_freem(m);
614 }
615
616 void
617 hci_sco_start(struct hci_link *link)
618 {
619 }
620
621 /*
622 * SCO packets have completed at the controller, so we can
623 * signal up to free the buffer space.
624 */
625 void
626 hci_sco_complete(struct hci_link *link, int num)
627 {
628
629 DPRINTFN(5, "handle #%d (num=%d)\n", link->hl_handle, num);
630 link->hl_sco->sp_pending--;
631 (*link->hl_sco->sp_proto->complete)(link->hl_sco->sp_upper, num);
632 }
633
634 /*******************************************************************************
635 *
636 * Generic HCI Connection alloc/free/lookup etc
637 */
638
639 struct hci_link *
640 hci_link_alloc(struct hci_unit *unit)
641 {
642 struct hci_link *link;
643
644 KASSERT(unit);
645
646 link = malloc(sizeof(struct hci_link), M_BLUETOOTH, M_NOWAIT | M_ZERO);
647 if (link == NULL)
648 return NULL;
649
650 link->hl_unit = unit;
651 link->hl_state = HCI_LINK_CLOSED;
652
653 /* init ACL portion */
654 callout_init(&link->hl_expire);
655 callout_setfunc(&link->hl_expire, hci_acl_timeout, link);
656
657 TAILQ_INIT(&link->hl_txq); /* outgoing packets */
658 TAILQ_INIT(&link->hl_reqs); /* request queue */
659
660 link->hl_mtu = L2CAP_MTU_DEFAULT; /* L2CAP signal mtu */
661 link->hl_flush = L2CAP_FLUSH_TIMO_DEFAULT; /* flush timeout */
662
663 /* init SCO portion */
664 MBUFQ_INIT(&link->hl_data);
665
666 /* attach to unit */
667 TAILQ_INSERT_HEAD(&unit->hci_links, link, hl_next);
668 return link;
669 }
670
671 void
672 hci_link_free(struct hci_link *link, int err)
673 {
674 struct l2cap_req *req;
675 struct l2cap_pdu *pdu;
676 struct l2cap_channel *chan;
677
678 KASSERT(link);
679
680 DPRINTF("#%d, type = %d, state = %d, refcnt = %d\n",
681 link->hl_handle, link->hl_type,
682 link->hl_state, link->hl_refcnt);
683
684 /* ACL reference count */
685 if (link->hl_refcnt > 0) {
686 LIST_FOREACH(chan, &l2cap_active_list, lc_ncid) {
687 if (chan->lc_link == link)
688 l2cap_close(chan, err);
689 }
690 }
691 KASSERT(link->hl_refcnt == 0);
692
693 /* ACL L2CAP requests.. */
694 while ((req = TAILQ_FIRST(&link->hl_reqs)) != NULL)
695 l2cap_request_free(req);
696
697 KASSERT(TAILQ_EMPTY(&link->hl_reqs));
698
699 /* ACL outgoing data queue */
700 while ((pdu = TAILQ_FIRST(&link->hl_txq)) != NULL) {
701 TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
702 MBUFQ_DRAIN(&pdu->lp_data);
703 if (pdu->lp_pending)
704 link->hl_unit->hci_num_acl_pkts += pdu->lp_pending;
705
706 pool_put(&l2cap_pdu_pool, pdu);
707 }
708
709 KASSERT(TAILQ_EMPTY(&link->hl_txq));
710
711 /* ACL incoming data packet */
712 if (link->hl_rxp != NULL) {
713 m_freem(link->hl_rxp);
714 link->hl_rxp = NULL;
715 }
716
717 /* SCO master ACL link */
718 if (link->hl_link != NULL) {
719 hci_acl_close(link->hl_link, err);
720 link->hl_link = NULL;
721 }
722
723 /* SCO pcb */
724 if (link->hl_sco != NULL) {
725 struct sco_pcb *pcb;
726
727 pcb = link->hl_sco;
728 pcb->sp_link = NULL;
729 link->hl_sco = NULL;
730 (*pcb->sp_proto->disconnected)(pcb->sp_upper, err);
731 }
732
733 /* flush any SCO data */
734 MBUFQ_DRAIN(&link->hl_data);
735
736 /*
737 * Halt the callout - if its already running we cannot free the
738 * link structure but the timeout function will call us back in
739 * any case.
740 */
741 link->hl_state = HCI_LINK_CLOSED;
742 callout_stop(&link->hl_expire);
743 if (callout_invoking(&link->hl_expire))
744 return;
745
746 TAILQ_REMOVE(&link->hl_unit->hci_links, link, hl_next);
747 free(link, M_BLUETOOTH);
748 }
749
750 /*
751 * Lookup HCI link by address and type. Note that for SCO links there may
752 * be more than one link per address, so we only return links with no
753 * handle (ie new links)
754 */
755 struct hci_link *
756 hci_link_lookup_bdaddr(struct hci_unit *unit, bdaddr_t *bdaddr, uint16_t type)
757 {
758 struct hci_link *link;
759
760 KASSERT(unit);
761 KASSERT(bdaddr);
762
763 TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
764 if (link->hl_type != type)
765 continue;
766
767 if (type == HCI_LINK_SCO && link->hl_handle != 0)
768 continue;
769
770 if (bdaddr_same(&link->hl_bdaddr, bdaddr))
771 break;
772 }
773
774 return link;
775 }
776
777 struct hci_link *
778 hci_link_lookup_handle(struct hci_unit *unit, uint16_t handle)
779 {
780 struct hci_link *link;
781
782 KASSERT(unit);
783
784 TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
785 if (handle == link->hl_handle)
786 break;
787 }
788
789 return link;
790 }
791