[BACK]Return to hci_link.c CVS log [TXT][DIR] Up to [local] / sys / netbt

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