Annotation of sys/netbt/hci_link.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: hci_link.c,v 1.5 2007/07/22 21:05:00 gwk Exp $ */
! 2: /* $NetBSD: hci_link.c,v 1.11 2007/04/21 06:15:23 plunky Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 2005 Iain Hibbert.
! 6: * Copyright (c) 2006 Itronix Inc.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. The name of Itronix Inc. may not be used to endorse
! 18: * or promote products derived from this software without specific
! 19: * prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 23: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 24: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
! 25: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 26: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
! 27: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
! 28: * ON ANY THEORY OF LIABILITY, WHETHER IN
! 29: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 30: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 31: * POSSIBILITY OF SUCH DAMAGE.
! 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/queue.h>
! 42: #include <sys/systm.h>
! 43:
! 44: #include <netbt/bluetooth.h>
! 45: #include <netbt/hci.h>
! 46: #include <netbt/l2cap.h>
! 47: #include <netbt/sco.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: struct hci_memo *memo;
! 72: hci_create_con_cp cp;
! 73: int err;
! 74:
! 75: KASSERT(unit != NULL);
! 76: KASSERT(bdaddr != NULL);
! 77:
! 78: link = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
! 79: if (link == NULL) {
! 80: link = hci_link_alloc(unit);
! 81: if (link == NULL)
! 82: return NULL;
! 83:
! 84: link->hl_type = HCI_LINK_ACL;
! 85: bdaddr_copy(&link->hl_bdaddr, bdaddr);
! 86: }
! 87:
! 88: switch(link->hl_state) {
! 89: case HCI_LINK_CLOSED:
! 90: /*
! 91: * open connection to remote device
! 92: */
! 93: memset(&cp, 0, sizeof(cp));
! 94: bdaddr_copy(&cp.bdaddr, bdaddr);
! 95: cp.pkt_type = htole16(unit->hci_packet_type);
! 96:
! 97: memo = hci_memo_find(unit, bdaddr);
! 98: if (memo != NULL) {
! 99: cp.page_scan_rep_mode = memo->response.page_scan_rep_mode;
! 100: cp.page_scan_mode = memo->response.page_scan_mode;
! 101: cp.clock_offset = htole16(memo->response.clock_offset);
! 102: }
! 103:
! 104: if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
! 105: cp.accept_role_switch = 1;
! 106:
! 107: err = hci_send_cmd(unit, HCI_CMD_CREATE_CON, &cp, sizeof(cp));
! 108: if (err) {
! 109: hci_link_free(link, err);
! 110: return NULL;
! 111: }
! 112:
! 113: link->hl_state = HCI_LINK_WAIT_CONNECT;
! 114: break;
! 115:
! 116: case HCI_LINK_WAIT_CONNECT:
! 117: case HCI_LINK_WAIT_AUTH:
! 118: case HCI_LINK_WAIT_ENCRYPT:
! 119: case HCI_LINK_WAIT_SECURE:
! 120: /*
! 121: * somebody else already trying to connect, we just
! 122: * sit on the bench with them..
! 123: */
! 124: break;
! 125:
! 126: case HCI_LINK_OPEN:
! 127: /*
! 128: * If already open, halt any expiry timeouts. We dont need
! 129: * to care about already invoking timeouts since refcnt >0
! 130: * will keep the link alive.
! 131: */
! 132: timeout_del(&link->hl_expire);
! 133: break;
! 134:
! 135: default:
! 136: UNKNOWN(link->hl_state);
! 137: return NULL;
! 138: }
! 139:
! 140: /* open */
! 141: link->hl_refcnt++;
! 142:
! 143: return link;
! 144: }
! 145:
! 146: /*
! 147: * Close ACL connection. When there are no more references to this link,
! 148: * we can either close it down or schedule a delayed closedown.
! 149: */
! 150: void
! 151: hci_acl_close(struct hci_link *link, int err)
! 152: {
! 153:
! 154: KASSERT(link != NULL);
! 155:
! 156: if (--link->hl_refcnt == 0) {
! 157: if (link->hl_state == HCI_LINK_CLOSED)
! 158: hci_link_free(link, err);
! 159: else if (hci_acl_expiry > 0)
! 160: timeout_add(&link->hl_expire, hci_acl_expiry * hz);
! 161: }
! 162: }
! 163:
! 164: /*
! 165: * Incoming ACL connection.
! 166: *
! 167: * For now, we accept all connections but it would be better to check
! 168: * the L2CAP listen list and only accept when there is a listener
! 169: * available.
! 170: *
! 171: * There should not be a link to the same bdaddr already, we check
! 172: * anyway though its left unhandled for now.
! 173: */
! 174: struct hci_link *
! 175: hci_acl_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
! 176: {
! 177: struct hci_link *link;
! 178:
! 179: link = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
! 180: if (link != NULL)
! 181: return NULL;
! 182:
! 183: link = hci_link_alloc(unit);
! 184: if (link != NULL) {
! 185: link->hl_state = HCI_LINK_WAIT_CONNECT;
! 186: link->hl_type = HCI_LINK_ACL;
! 187: bdaddr_copy(&link->hl_bdaddr, bdaddr);
! 188:
! 189: if (hci_acl_expiry > 0)
! 190: timeout_add(&link->hl_expire, hci_acl_expiry * hz);
! 191: }
! 192:
! 193: return link;
! 194: }
! 195:
! 196: void
! 197: hci_acl_timeout(void *arg)
! 198: {
! 199: struct hci_link *link = arg;
! 200: hci_discon_cp cp;
! 201: int s, err;
! 202:
! 203: s = splsoftnet();
! 204:
! 205: if (link->hl_refcnt > 0)
! 206: goto out;
! 207:
! 208: DPRINTF("link #%d expired\n", link->hl_handle);
! 209:
! 210: switch (link->hl_state) {
! 211: case HCI_LINK_CLOSED:
! 212: case HCI_LINK_WAIT_CONNECT:
! 213: hci_link_free(link, ECONNRESET);
! 214: break;
! 215:
! 216: case HCI_LINK_WAIT_AUTH:
! 217: case HCI_LINK_WAIT_ENCRYPT:
! 218: case HCI_LINK_WAIT_SECURE:
! 219: case HCI_LINK_OPEN:
! 220: cp.con_handle = htole16(link->hl_handle);
! 221: cp.reason = 0x13; /* "Remote User Terminated Connection" */
! 222:
! 223: err = hci_send_cmd(link->hl_unit, HCI_CMD_DISCONNECT,
! 224: &cp, sizeof(cp));
! 225:
! 226: if (err) {
! 227: DPRINTF("error %d sending HCI_CMD_DISCONNECT\n",
! 228: err);
! 229: }
! 230:
! 231: break;
! 232:
! 233: default:
! 234: UNKNOWN(link->hl_state);
! 235: break;
! 236: }
! 237:
! 238: out:
! 239: splx(s);
! 240: }
! 241:
! 242: /*
! 243: * Initiate any Link Mode change requests.
! 244: */
! 245: int
! 246: hci_acl_setmode(struct hci_link *link)
! 247: {
! 248: int err;
! 249:
! 250: KASSERT(link != NULL);
! 251: KASSERT(link->hl_unit != NULL);
! 252:
! 253: if (link->hl_state != HCI_LINK_OPEN)
! 254: return EINPROGRESS;
! 255:
! 256: if ((link->hl_flags & HCI_LINK_AUTH_REQ)
! 257: && !(link->hl_flags & HCI_LINK_AUTH)) {
! 258: hci_auth_req_cp cp;
! 259:
! 260: DPRINTF("requesting auth for handle #%d\n",
! 261: link->hl_handle);
! 262:
! 263: link->hl_state = HCI_LINK_WAIT_AUTH;
! 264: cp.con_handle = htole16(link->hl_handle);
! 265: err = hci_send_cmd(link->hl_unit, HCI_CMD_AUTH_REQ,
! 266: &cp, sizeof(cp));
! 267:
! 268: return (err == 0 ? EINPROGRESS : err);
! 269: }
! 270:
! 271: if ((link->hl_flags & HCI_LINK_ENCRYPT_REQ)
! 272: && !(link->hl_flags & HCI_LINK_ENCRYPT)) {
! 273: hci_set_con_encryption_cp cp;
! 274:
! 275: /* XXX we should check features for encryption capability */
! 276:
! 277: DPRINTF("requesting encryption for handle #%d\n",
! 278: link->hl_handle);
! 279:
! 280: link->hl_state = HCI_LINK_WAIT_ENCRYPT;
! 281: cp.con_handle = htole16(link->hl_handle);
! 282: cp.encryption_enable = 0x01;
! 283:
! 284: err = hci_send_cmd(link->hl_unit, HCI_CMD_SET_CON_ENCRYPTION,
! 285: &cp, sizeof(cp));
! 286:
! 287: return (err == 0 ? EINPROGRESS : err);
! 288: }
! 289:
! 290: if ((link->hl_flags & HCI_LINK_SECURE_REQ)) {
! 291: hci_change_con_link_key_cp cp;
! 292:
! 293: /* always change link key for SECURE requests */
! 294: link->hl_flags &= ~HCI_LINK_SECURE;
! 295:
! 296: DPRINTF("changing link key for handle #%d\n",
! 297: link->hl_handle);
! 298:
! 299: link->hl_state = HCI_LINK_WAIT_SECURE;
! 300: cp.con_handle = htole16(link->hl_handle);
! 301:
! 302: err = hci_send_cmd(link->hl_unit, HCI_CMD_CHANGE_CON_LINK_KEY,
! 303: &cp, sizeof(cp));
! 304:
! 305: return (err == 0 ? EINPROGRESS : err);
! 306: }
! 307:
! 308: return 0;
! 309: }
! 310:
! 311: /*
! 312: * Link Mode changed.
! 313: *
! 314: * This is called from event handlers when the mode change
! 315: * is complete. We notify upstream and restart the link.
! 316: */
! 317: void
! 318: hci_acl_linkmode(struct hci_link *link)
! 319: {
! 320: struct l2cap_channel *chan, *next;
! 321: int err, mode = 0;
! 322:
! 323: DPRINTF("handle #%d, auth %s, encrypt %s, secure %s\n",
! 324: link->hl_handle,
! 325: (link->hl_flags & HCI_LINK_AUTH ? "on" : "off"),
! 326: (link->hl_flags & HCI_LINK_ENCRYPT ? "on" : "off"),
! 327: (link->hl_flags & HCI_LINK_SECURE ? "on" : "off"));
! 328:
! 329: if (link->hl_flags & HCI_LINK_AUTH)
! 330: mode |= L2CAP_LM_AUTH;
! 331:
! 332: if (link->hl_flags & HCI_LINK_ENCRYPT)
! 333: mode |= L2CAP_LM_ENCRYPT;
! 334:
! 335: if (link->hl_flags & HCI_LINK_SECURE)
! 336: mode |= L2CAP_LM_SECURE;
! 337:
! 338: /*
! 339: * The link state will only be OPEN here if the mode change
! 340: * was successful. So, we can proceed with L2CAP connections,
! 341: * or notify already establshed channels, to allow any that
! 342: * are dissatisfied to disconnect before we restart.
! 343: */
! 344: next = LIST_FIRST(&l2cap_active_list);
! 345: while ((chan = next) != NULL) {
! 346: next = LIST_NEXT(chan, lc_ncid);
! 347:
! 348: if (chan->lc_link != link)
! 349: continue;
! 350:
! 351: switch(chan->lc_state) {
! 352: case L2CAP_WAIT_SEND_CONNECT_REQ: /* we are connecting */
! 353: if ((mode & chan->lc_mode) != chan->lc_mode) {
! 354: l2cap_close(chan, ECONNABORTED);
! 355: break;
! 356: }
! 357:
! 358: chan->lc_state = L2CAP_WAIT_RECV_CONNECT_RSP;
! 359: err = l2cap_send_connect_req(chan);
! 360: if (err) {
! 361: l2cap_close(chan, err);
! 362: break;
! 363: }
! 364: break;
! 365:
! 366: case L2CAP_WAIT_SEND_CONNECT_RSP: /* they are connecting */
! 367: if ((mode & chan->lc_mode) != chan->lc_mode) {
! 368: l2cap_send_connect_rsp(link, chan->lc_ident,
! 369: 0, chan->lc_rcid,
! 370: L2CAP_SECURITY_BLOCK);
! 371:
! 372: l2cap_close(chan, ECONNABORTED);
! 373: break;
! 374: }
! 375:
! 376: l2cap_send_connect_rsp(link, chan->lc_ident,
! 377: chan->lc_lcid, chan->lc_rcid,
! 378: L2CAP_SUCCESS);
! 379:
! 380: chan->lc_state = L2CAP_WAIT_CONFIG;
! 381: chan->lc_flags |= (L2CAP_WAIT_CONFIG_RSP | L2CAP_WAIT_CONFIG_REQ);
! 382: err = l2cap_send_config_req(chan);
! 383: if (err) {
! 384: l2cap_close(chan, err);
! 385: break;
! 386: }
! 387: break;
! 388:
! 389: case L2CAP_WAIT_RECV_CONNECT_RSP:
! 390: case L2CAP_WAIT_CONFIG:
! 391: case L2CAP_OPEN: /* already established */
! 392: (*chan->lc_proto->linkmode)(chan->lc_upper, mode);
! 393: break;
! 394:
! 395: default:
! 396: break;
! 397: }
! 398: }
! 399:
! 400: link->hl_state = HCI_LINK_OPEN;
! 401: hci_acl_start(link);
! 402: }
! 403:
! 404: /*
! 405: * Receive ACL Data
! 406: *
! 407: * we accumulate packet fragments on the hci_link structure
! 408: * until a full L2CAP frame is ready, then send it on.
! 409: */
! 410: void
! 411: hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
! 412: {
! 413: struct hci_link *link;
! 414: hci_acldata_hdr_t hdr;
! 415: uint16_t handle, want;
! 416: int pb, got;
! 417:
! 418: KASSERT(m != NULL);
! 419: KASSERT(unit != NULL);
! 420:
! 421: KASSERT(m->m_pkthdr.len >= sizeof(hdr));
! 422: m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
! 423: m_adj(m, sizeof(hdr));
! 424:
! 425: #ifdef DIAGNOSTIC
! 426: if (hdr.type != HCI_ACL_DATA_PKT) {
! 427: printf("%s: bad ACL packet type\n", unit->hci_devname);
! 428: goto bad;
! 429: }
! 430:
! 431: if (m->m_pkthdr.len != letoh16(hdr.length)) {
! 432: printf("%s: bad ACL packet length (%d != %d)\n",
! 433: unit->hci_devname, m->m_pkthdr.len, letoh16(hdr.length));
! 434: goto bad;
! 435: }
! 436: #endif
! 437:
! 438: hdr.length = letoh16(hdr.length);
! 439: hdr.con_handle = letoh16(hdr.con_handle);
! 440: handle = HCI_CON_HANDLE(hdr.con_handle);
! 441: pb = HCI_PB_FLAG(hdr.con_handle);
! 442:
! 443: link = hci_link_lookup_handle(unit, handle);
! 444: if (link == NULL) {
! 445: hci_discon_cp cp;
! 446:
! 447: DPRINTF("%s: dumping packet for unknown handle #%d\n",
! 448: unit->hci_devname, handle);
! 449:
! 450: /*
! 451: * There is no way to find out what this connection handle is
! 452: * for, just get rid of it. This may happen, if a USB dongle
! 453: * is plugged into a self powered hub and does not reset when
! 454: * the system is shut down.
! 455: */
! 456: cp.con_handle = htole16(handle);
! 457: cp.reason = 0x13; /* "Remote User Terminated Connection" */
! 458: hci_send_cmd(unit, HCI_CMD_DISCONNECT, &cp, sizeof(cp));
! 459: goto bad;
! 460: }
! 461:
! 462: switch (pb) {
! 463: case HCI_PACKET_START:
! 464: if (link->hl_rxp != NULL)
! 465: printf("%s: dropped incomplete ACL packet\n",
! 466: unit->hci_devname);
! 467:
! 468: if (m->m_pkthdr.len < sizeof(l2cap_hdr_t)) {
! 469: printf("%s: short ACL packet\n",
! 470: unit->hci_devname);
! 471:
! 472: goto bad;
! 473: }
! 474:
! 475: link->hl_rxp = m;
! 476: got = m->m_pkthdr.len;
! 477: break;
! 478:
! 479: case HCI_PACKET_FRAGMENT:
! 480: if (link->hl_rxp == NULL) {
! 481: printf("%s: unexpected packet fragment\n",
! 482: unit->hci_devname);
! 483:
! 484: goto bad;
! 485: }
! 486:
! 487: got = m->m_pkthdr.len + link->hl_rxp->m_pkthdr.len;
! 488: m_cat(link->hl_rxp, m);
! 489: m = link->hl_rxp;
! 490: m->m_pkthdr.len = got;
! 491: break;
! 492:
! 493: default:
! 494: printf("%s: unknown packet type\n",
! 495: unit->hci_devname);
! 496:
! 497: goto bad;
! 498: }
! 499:
! 500: m_copydata(m, 0, sizeof(want), (caddr_t)&want);
! 501: want = letoh16(want) + sizeof(l2cap_hdr_t) - got;
! 502:
! 503: if (want > 0)
! 504: return;
! 505:
! 506: link->hl_rxp = NULL;
! 507:
! 508: if (want == 0) {
! 509: l2cap_recv_frame(m, link);
! 510: return;
! 511: }
! 512:
! 513: bad:
! 514: m_freem(m);
! 515: }
! 516:
! 517: /*
! 518: * Send ACL data on link
! 519: *
! 520: * We must fragment packets into chunks of less than unit->hci_max_acl_size and
! 521: * prepend a relevant ACL header to each fragment. We keep a PDU structure
! 522: * attached to the link, so that completed fragments can be marked off and
! 523: * more data requested from above once the PDU is sent.
! 524: */
! 525: int
! 526: hci_acl_send(struct mbuf *m, struct hci_link *link,
! 527: struct l2cap_channel *chan)
! 528: {
! 529: struct l2cap_pdu *pdu;
! 530: struct mbuf *n = NULL;
! 531: int plen, mlen, num = 0;
! 532:
! 533: KASSERT(link != NULL);
! 534: KASSERT(m != NULL);
! 535: KASSERT(m->m_flags & M_PKTHDR);
! 536: KASSERT(m->m_pkthdr.len > 0);
! 537:
! 538: if (link->hl_state == HCI_LINK_CLOSED) {
! 539: m_freem(m);
! 540: return ENETDOWN;
! 541: }
! 542:
! 543: pdu = pool_get(&l2cap_pdu_pool, PR_NOWAIT);
! 544: if (pdu == NULL)
! 545: goto nomem;
! 546:
! 547: bzero(pdu, sizeof *pdu);
! 548: pdu->lp_chan = chan;
! 549: pdu->lp_pending = 0;
! 550:
! 551: plen = m->m_pkthdr.len;
! 552: mlen = link->hl_unit->hci_max_acl_size;
! 553:
! 554: DPRINTFN(5, "%s: handle #%d, plen = %d, max = %d\n",
! 555: link->hl_unit->hci_devname, link->hl_handle, plen, mlen);
! 556:
! 557: while (plen > 0) {
! 558: if (plen > mlen) {
! 559: n = m_split(m, mlen, M_DONTWAIT);
! 560: if (n == NULL)
! 561: goto nomem;
! 562: } else {
! 563: mlen = plen;
! 564: }
! 565:
! 566: if (num++ == 0)
! 567: m->m_flags |= M_PROTO1; /* tag first fragment */
! 568:
! 569: DPRINTFN(10, "chunk of %d (plen = %d) bytes\n", mlen, plen);
! 570: IF_ENQUEUE(&pdu->lp_data, m);
! 571: m = n;
! 572: plen -= mlen;
! 573: }
! 574:
! 575: TAILQ_INSERT_TAIL(&link->hl_txq, pdu, lp_next);
! 576: link->hl_txqlen += num;
! 577:
! 578: hci_acl_start(link);
! 579:
! 580: return 0;
! 581:
! 582: nomem:
! 583: if (m) m_freem(m);
! 584: if (pdu) {
! 585: IF_PURGE(&pdu->lp_data);
! 586: pool_put(&l2cap_pdu_pool, pdu);
! 587: }
! 588:
! 589: return ENOMEM;
! 590: }
! 591:
! 592: /*
! 593: * Start sending ACL data on link.
! 594: *
! 595: * This is called when the queue may need restarting: as new data
! 596: * is queued, after link mode changes have completed, or when device
! 597: * buffers have cleared.
! 598: *
! 599: * We may use all the available packet slots. The reason that we add
! 600: * the ACL encapsulation here rather than in hci_acl_send() is that L2CAP
! 601: * signal packets may be queued before the handle is given to us..
! 602: */
! 603: void
! 604: hci_acl_start(struct hci_link *link)
! 605: {
! 606: struct hci_unit *unit;
! 607: hci_acldata_hdr_t *hdr;
! 608: struct l2cap_pdu *pdu;
! 609: struct mbuf *m;
! 610: uint16_t handle;
! 611:
! 612: KASSERT(link != NULL);
! 613:
! 614: unit = link->hl_unit;
! 615: KASSERT(unit != NULL);
! 616:
! 617: /* this is mainly to block ourselves (below) */
! 618: if (link->hl_state != HCI_LINK_OPEN)
! 619: return;
! 620:
! 621: if (link->hl_txqlen == 0 || unit->hci_num_acl_pkts == 0)
! 622: return;
! 623:
! 624: /* find first PDU with data to send */
! 625: pdu = TAILQ_FIRST(&link->hl_txq);
! 626: for (;;) {
! 627: if (pdu == NULL)
! 628: return;
! 629:
! 630: if (!IF_IS_EMPTY(&pdu->lp_data))
! 631: break;
! 632:
! 633: pdu = TAILQ_NEXT(pdu, lp_next);
! 634: }
! 635:
! 636: while (unit->hci_num_acl_pkts > 0) {
! 637: IF_DEQUEUE(&pdu->lp_data, m);
! 638: KASSERT(m != NULL);
! 639:
! 640: if (m->m_flags & M_PROTO1)
! 641: handle = HCI_MK_CON_HANDLE(link->hl_handle,
! 642: HCI_PACKET_START, 0);
! 643: else
! 644: handle = HCI_MK_CON_HANDLE(link->hl_handle,
! 645: HCI_PACKET_FRAGMENT, 0);
! 646:
! 647: M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
! 648: if (m == NULL)
! 649: break;
! 650:
! 651: hdr = mtod(m, hci_acldata_hdr_t *);
! 652: hdr->type = HCI_ACL_DATA_PKT;
! 653: hdr->con_handle = htole16(handle);
! 654: hdr->length = htole16(m->m_pkthdr.len - sizeof(*hdr));
! 655:
! 656: link->hl_txqlen--;
! 657: pdu->lp_pending++;
! 658:
! 659: hci_output_acl(unit, m);
! 660:
! 661: if (IF_IS_EMPTY(&pdu->lp_data)) {
! 662: if (pdu->lp_chan) {
! 663: /*
! 664: * This should enable streaming of PDUs - when
! 665: * we have placed all the fragments on the acl
! 666: * output queue, we trigger the L2CAP layer to
! 667: * send us down one more. Use a false state so
! 668: * we dont run into ourselves coming back from
! 669: * the future..
! 670: */
! 671: link->hl_state = HCI_LINK_BLOCK;
! 672: l2cap_start(pdu->lp_chan);
! 673: link->hl_state = HCI_LINK_OPEN;
! 674: }
! 675:
! 676: pdu = TAILQ_NEXT(pdu, lp_next);
! 677: if (pdu == NULL)
! 678: break;
! 679: }
! 680: }
! 681:
! 682: /*
! 683: * We had our turn now, move to the back of the queue to let
! 684: * other links have a go at the output buffers..
! 685: */
! 686: if (TAILQ_NEXT(link, hl_next)) {
! 687: TAILQ_REMOVE(&unit->hci_links, link, hl_next);
! 688: TAILQ_INSERT_TAIL(&unit->hci_links, link, hl_next);
! 689: }
! 690: }
! 691:
! 692: /*
! 693: * Confirm ACL packets cleared from Controller buffers. We scan our PDU
! 694: * list to clear pending fragments and signal upstream for more data
! 695: * when a PDU is complete.
! 696: */
! 697: void
! 698: hci_acl_complete(struct hci_link *link, int num)
! 699: {
! 700: struct l2cap_pdu *pdu;
! 701: struct l2cap_channel *chan;
! 702:
! 703: DPRINTFN(5, "handle #%d (%d)\n", link->hl_handle, num);
! 704:
! 705: while (num > 0) {
! 706: pdu = TAILQ_FIRST(&link->hl_txq);
! 707: if (pdu == NULL) {
! 708: printf("%s: %d packets completed on handle #%x "
! 709: "but none pending!\n",
! 710: link->hl_unit->hci_devname, num,
! 711: link->hl_handle);
! 712: return;
! 713: }
! 714:
! 715: if (num >= pdu->lp_pending) {
! 716: num -= pdu->lp_pending;
! 717: pdu->lp_pending = 0;
! 718:
! 719: if (IF_IS_EMPTY(&pdu->lp_data)) {
! 720: TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
! 721: chan = pdu->lp_chan;
! 722: if (chan != NULL) {
! 723: chan->lc_pending--;
! 724: (*chan->lc_proto->complete)
! 725: (chan->lc_upper, 1);
! 726:
! 727: if (chan->lc_pending == 0)
! 728: l2cap_start(chan);
! 729: }
! 730:
! 731: pool_put(&l2cap_pdu_pool, pdu);
! 732: }
! 733: } else {
! 734: pdu->lp_pending -= num;
! 735: num = 0;
! 736: }
! 737: }
! 738: }
! 739:
! 740: /*******************************************************************************
! 741: *
! 742: * HCI SCO Connections
! 743: */
! 744:
! 745: /*
! 746: * Incoming SCO Connection. We check the list for anybody willing
! 747: * to take it.
! 748: */
! 749: struct hci_link *
! 750: hci_sco_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
! 751: {
! 752: struct sockaddr_bt laddr, raddr;
! 753: struct sco_pcb *pcb, *new;
! 754: struct hci_link *sco, *acl;
! 755:
! 756: memset(&laddr, 0, sizeof(laddr));
! 757: laddr.bt_len = sizeof(laddr);
! 758: laddr.bt_family = AF_BLUETOOTH;
! 759: bdaddr_copy(&laddr.bt_bdaddr, &unit->hci_bdaddr);
! 760:
! 761: memset(&raddr, 0, sizeof(raddr));
! 762: raddr.bt_len = sizeof(raddr);
! 763: raddr.bt_family = AF_BLUETOOTH;
! 764: bdaddr_copy(&raddr.bt_bdaddr, bdaddr);
! 765:
! 766: /*
! 767: * There should already be an ACL link up and running before
! 768: * the controller sends us SCO connection requests, but you
! 769: * never know..
! 770: */
! 771: acl = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
! 772: if (acl == NULL || acl->hl_state != HCI_LINK_OPEN)
! 773: return NULL;
! 774:
! 775: LIST_FOREACH(pcb, &sco_pcb, sp_next) {
! 776: if ((pcb->sp_flags & SP_LISTENING) == 0)
! 777: continue;
! 778:
! 779: new = (*pcb->sp_proto->newconn)(pcb->sp_upper, &laddr, &raddr);
! 780: if (new == NULL)
! 781: continue;
! 782:
! 783: /*
! 784: * Ok, got new pcb so we can start a new link and fill
! 785: * in all the details.
! 786: */
! 787: bdaddr_copy(&new->sp_laddr, &unit->hci_bdaddr);
! 788: bdaddr_copy(&new->sp_raddr, bdaddr);
! 789:
! 790: sco = hci_link_alloc(unit);
! 791: if (sco == NULL) {
! 792: sco_detach(&new);
! 793: return NULL;
! 794: }
! 795:
! 796: sco->hl_type = HCI_LINK_SCO;
! 797: bdaddr_copy(&sco->hl_bdaddr, bdaddr);
! 798:
! 799: sco->hl_link = hci_acl_open(unit, bdaddr);
! 800: KASSERT(sco->hl_link == acl);
! 801:
! 802: sco->hl_sco = new;
! 803: new->sp_link = sco;
! 804:
! 805: new->sp_mtu = unit->hci_max_sco_size;
! 806: return sco;
! 807: }
! 808:
! 809: return NULL;
! 810: }
! 811:
! 812: /*
! 813: * receive SCO packet, we only need to strip the header and send
! 814: * it to the right handler
! 815: */
! 816: void
! 817: hci_sco_recv(struct mbuf *m, struct hci_unit *unit)
! 818: {
! 819: struct hci_link *link;
! 820: hci_scodata_hdr_t hdr;
! 821: uint16_t handle;
! 822:
! 823: KASSERT(m != NULL);
! 824: KASSERT(unit != NULL);
! 825:
! 826: KASSERT(m->m_pkthdr.len >= sizeof(hdr));
! 827: m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
! 828: m_adj(m, sizeof(hdr));
! 829:
! 830: #ifdef DIAGNOSTIC
! 831: if (hdr.type != HCI_SCO_DATA_PKT) {
! 832: printf("%s: bad SCO packet type\n", unit->hci_devname);
! 833: goto bad;
! 834: }
! 835:
! 836: if (m->m_pkthdr.len != hdr.length) {
! 837: printf("%s: bad SCO packet length (%d != %d)\n",
! 838: unit->hci_devname, m->m_pkthdr.len, hdr.length);
! 839: goto bad;
! 840: }
! 841: #endif
! 842:
! 843: hdr.con_handle = letoh16(hdr.con_handle);
! 844: handle = HCI_CON_HANDLE(hdr.con_handle);
! 845:
! 846: link = hci_link_lookup_handle(unit, handle);
! 847: if (link == NULL || link->hl_type == HCI_LINK_ACL) {
! 848: DPRINTF("%s: dumping packet for unknown handle #%d\n",
! 849: unit->hci_devname, handle);
! 850:
! 851: goto bad;
! 852: }
! 853:
! 854: (*link->hl_sco->sp_proto->input)(link->hl_sco->sp_upper, m);
! 855: return;
! 856:
! 857: bad:
! 858: m_freem(m);
! 859: }
! 860:
! 861: void
! 862: hci_sco_start(struct hci_link *link)
! 863: {
! 864: }
! 865:
! 866: /*
! 867: * SCO packets have completed at the controller, so we can
! 868: * signal up to free the buffer space.
! 869: */
! 870: void
! 871: hci_sco_complete(struct hci_link *link, int num)
! 872: {
! 873:
! 874: DPRINTFN(5, "handle #%d (num=%d)\n", link->hl_handle, num);
! 875: link->hl_sco->sp_pending--;
! 876: (*link->hl_sco->sp_proto->complete)(link->hl_sco->sp_upper, num);
! 877: }
! 878:
! 879: /*******************************************************************************
! 880: *
! 881: * Generic HCI Connection alloc/free/lookup etc
! 882: */
! 883:
! 884: struct hci_link *
! 885: hci_link_alloc(struct hci_unit *unit)
! 886: {
! 887: struct hci_link *link;
! 888:
! 889: KASSERT(unit != NULL);
! 890:
! 891: link = malloc(sizeof *link, M_BLUETOOTH, M_NOWAIT);
! 892: if (link == NULL)
! 893: return NULL;
! 894: bzero(link, sizeof *link);
! 895:
! 896: link->hl_unit = unit;
! 897: link->hl_state = HCI_LINK_CLOSED;
! 898:
! 899: /* init ACL portion */
! 900: timeout_set(&link->hl_expire, hci_acl_timeout, link);
! 901:
! 902: TAILQ_INIT(&link->hl_txq); /* outgoing packets */
! 903: TAILQ_INIT(&link->hl_reqs); /* request queue */
! 904:
! 905: link->hl_mtu = L2CAP_MTU_DEFAULT; /* L2CAP signal mtu */
! 906: link->hl_flush = L2CAP_FLUSH_TIMO_DEFAULT; /* flush timeout */
! 907:
! 908: /* attach to unit */
! 909: TAILQ_INSERT_HEAD(&unit->hci_links, link, hl_next);
! 910: return link;
! 911: }
! 912:
! 913: void
! 914: hci_link_free(struct hci_link *link, int err)
! 915: {
! 916: struct l2cap_req *req;
! 917: struct l2cap_pdu *pdu;
! 918: struct l2cap_channel *chan, *next;
! 919:
! 920: KASSERT(link != NULL);
! 921:
! 922: DPRINTF("#%d, type = %d, state = %d, refcnt = %d\n",
! 923: link->hl_handle, link->hl_type,
! 924: link->hl_state, link->hl_refcnt);
! 925:
! 926: /* ACL reference count */
! 927: if (link->hl_refcnt > 0) {
! 928: next = LIST_FIRST(&l2cap_active_list);
! 929: while ((chan = next) != NULL) {
! 930: next = LIST_NEXT(chan, lc_ncid);
! 931: if (chan->lc_link == link)
! 932: l2cap_close(chan, err);
! 933: }
! 934: }
! 935: KASSERT(link->hl_refcnt == 0);
! 936:
! 937: /* ACL L2CAP requests.. */
! 938: while ((req = TAILQ_FIRST(&link->hl_reqs)) != NULL)
! 939: l2cap_request_free(req);
! 940:
! 941: KASSERT(TAILQ_EMPTY(&link->hl_reqs));
! 942:
! 943: /* ACL outgoing data queue */
! 944: while ((pdu = TAILQ_FIRST(&link->hl_txq)) != NULL) {
! 945: TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
! 946: IF_PURGE(&pdu->lp_data);
! 947: if (pdu->lp_pending)
! 948: link->hl_unit->hci_num_acl_pkts += pdu->lp_pending;
! 949:
! 950: pool_put(&l2cap_pdu_pool, pdu);
! 951: }
! 952:
! 953: KASSERT(TAILQ_EMPTY(&link->hl_txq));
! 954:
! 955: /* ACL incoming data packet */
! 956: if (link->hl_rxp != NULL) {
! 957: m_freem(link->hl_rxp);
! 958: link->hl_rxp = NULL;
! 959: }
! 960:
! 961: /* SCO master ACL link */
! 962: if (link->hl_link != NULL) {
! 963: hci_acl_close(link->hl_link, err);
! 964: link->hl_link = NULL;
! 965: }
! 966:
! 967: /* SCO pcb */
! 968: if (link->hl_sco != NULL) {
! 969: struct sco_pcb *pcb;
! 970:
! 971: pcb = link->hl_sco;
! 972: pcb->sp_link = NULL;
! 973: link->hl_sco = NULL;
! 974: (*pcb->sp_proto->disconnected)(pcb->sp_upper, err);
! 975: }
! 976:
! 977: /* flush any SCO data */
! 978: IF_PURGE(&link->hl_data);
! 979:
! 980: /*
! 981: * Halt the timeout - if its already running we cannot free the
! 982: * link structure but the timeout function will call us back in
! 983: * any case.
! 984: */
! 985: link->hl_state = HCI_LINK_CLOSED;
! 986: timeout_del(&link->hl_expire);
! 987: if (timeout_triggered(&link->hl_expire))
! 988: return;
! 989:
! 990: TAILQ_REMOVE(&link->hl_unit->hci_links, link, hl_next);
! 991: free(link, M_BLUETOOTH);
! 992: }
! 993:
! 994: /*
! 995: * Lookup HCI link by type and state.
! 996: */
! 997: struct hci_link *
! 998: hci_link_lookup_state(struct hci_unit *unit, uint16_t type, uint16_t state)
! 999: {
! 1000: struct hci_link *link;
! 1001:
! 1002: TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
! 1003: if (link->hl_type == type && link->hl_state == state)
! 1004: break;
! 1005: }
! 1006:
! 1007: return link;
! 1008: }
! 1009:
! 1010: /*
! 1011: * Lookup HCI link by address and type. Note that for SCO links there may
! 1012: * be more than one link per address, so we only return links with no
! 1013: * handle (ie new links)
! 1014: */
! 1015: struct hci_link *
! 1016: hci_link_lookup_bdaddr(struct hci_unit *unit, bdaddr_t *bdaddr, uint16_t type)
! 1017: {
! 1018: struct hci_link *link;
! 1019:
! 1020: KASSERT(unit != NULL);
! 1021: KASSERT(bdaddr != NULL);
! 1022:
! 1023: TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
! 1024: if (link->hl_type != type)
! 1025: continue;
! 1026:
! 1027: if (type == HCI_LINK_SCO && link->hl_handle != 0)
! 1028: continue;
! 1029:
! 1030: if (bdaddr_same(&link->hl_bdaddr, bdaddr))
! 1031: break;
! 1032: }
! 1033:
! 1034: return link;
! 1035: }
! 1036:
! 1037: struct hci_link *
! 1038: hci_link_lookup_handle(struct hci_unit *unit, uint16_t handle)
! 1039: {
! 1040: struct hci_link *link;
! 1041:
! 1042: KASSERT(unit != NULL);
! 1043:
! 1044: TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
! 1045: if (handle == link->hl_handle)
! 1046: break;
! 1047: }
! 1048:
! 1049: return link;
! 1050: }
CVSweb