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

Annotation of sys/netbt/l2cap_lower.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: l2cap_lower.c,v 1.1 2007/05/30 03:42:53 uwe Exp $     */
                      2: /*     $NetBSD: l2cap_lower.c,v 1.6 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:
                     48: /****************************************************************************
                     49:  *
                     50:  *     L2CAP Channel Lower Layer interface
                     51:  */
                     52:
                     53: /*
                     54:  * L2CAP channel is disconnected, could be:
                     55:  *
                     56:  * HCI layer received "Disconnect Complete" event for ACL link
                     57:  * some Request timed out
                     58:  * Config failed
                     59:  * Other end reported invalid CID
                     60:  * Normal disconnection
                     61:  * Change link mode failed
                     62:  */
                     63: void
                     64: l2cap_close(struct l2cap_channel *chan, int err)
                     65: {
                     66:        struct l2cap_pdu *pdu;
                     67:        struct l2cap_req *req, *n;
                     68:
                     69:        if (chan->lc_state == L2CAP_CLOSED)
                     70:                return;
                     71:
                     72:        /*
                     73:         * Since any potential PDU could be half sent we just let it go,
                     74:         * but disassociate ourselves from it as links deal with ownerless
                     75:         * PDU's in any case.  We could try harder to flush unsent packets
                     76:         * but maybe its better to leave them in the queue?
                     77:         */
                     78:        TAILQ_FOREACH(pdu, &chan->lc_link->hl_txq, lp_next) {
                     79:                if (pdu->lp_chan == chan)
                     80:                        pdu->lp_chan = NULL;
                     81:        }
                     82:
                     83:        /*
                     84:         * and clear any outstanding requests..
                     85:         */
                     86:        req = TAILQ_FIRST(&chan->lc_link->hl_reqs);
                     87:        while (req != NULL) {
                     88:                n = TAILQ_NEXT(req, lr_next);
                     89:                if (req->lr_chan == chan)
                     90:                        l2cap_request_free(req);
                     91:
                     92:                req = n;
                     93:        }
                     94:
                     95:        chan->lc_pending = 0;
                     96:        chan->lc_state = L2CAP_CLOSED;
                     97:        hci_acl_close(chan->lc_link, err);
                     98:        chan->lc_link = NULL;
                     99:
                    100:        (*chan->lc_proto->disconnected)(chan->lc_upper, err);
                    101: }
                    102:
                    103: /*
                    104:  * Process incoming L2CAP frame from ACL link. We take off the B-Frame
                    105:  * header (which is present in all packets), verify the data length
                    106:  * and distribute the rest of the frame to the relevant channel
                    107:  * handler.
                    108:  */
                    109: void
                    110: l2cap_recv_frame(struct mbuf *m, struct hci_link *link)
                    111: {
                    112:        struct l2cap_channel *chan;
                    113:        l2cap_hdr_t hdr;
                    114:
                    115:        m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
                    116:        m_adj(m, sizeof(hdr));
                    117:
                    118:        hdr.length = letoh16(hdr.length);
                    119:        hdr.dcid = letoh16(hdr.dcid);
                    120:
                    121:        DPRINTFN(5, "(%s) received packet (%d bytes)\n",
                    122:                    link->hl_unit->hci_devname, hdr.length);
                    123:
                    124:        if (hdr.length != m->m_pkthdr.len)
                    125:                goto failed;
                    126:
                    127:        if (hdr.dcid == L2CAP_SIGNAL_CID) {
                    128:                l2cap_recv_signal(m, link);
                    129:                return;
                    130:        }
                    131:
                    132:        if (hdr.dcid == L2CAP_CLT_CID) {
                    133:                m_freem(m);     /* TODO */
                    134:                return;
                    135:        }
                    136:
                    137:        chan = l2cap_cid_lookup(hdr.dcid);
                    138:        if (chan != NULL && chan->lc_link == link
                    139:            && chan->lc_state == L2CAP_OPEN) {
                    140:                (*chan->lc_proto->input)(chan->lc_upper, m);
                    141:                return;
                    142:        }
                    143:
                    144:        DPRINTF("(%s) dropping %d L2CAP data bytes for unknown CID #%d\n",
                    145:                link->hl_unit->hci_devname, hdr.length, hdr.dcid);
                    146:
                    147: failed:
                    148:        m_freem(m);
                    149: }
                    150:
                    151: /*
                    152:  * Start another L2CAP packet on its way. This is called from l2cap_send
                    153:  * (when no PDU is pending) and hci_acl_start (when PDU has been placed on
                    154:  * device queue). Thus we can have more than one PDU waiting at the device
                    155:  * if space is available but no single channel will hog the link.
                    156:  */
                    157: int
                    158: l2cap_start(struct l2cap_channel *chan)
                    159: {
                    160:        struct mbuf *m;
                    161:        int err = 0;
                    162:
                    163:        if (chan->lc_state != L2CAP_OPEN)
                    164:                return 0;
                    165:
                    166:        if (IF_IS_EMPTY(&chan->lc_txq)) {
                    167:                DPRINTFN(5, "no data, pending = %d\n", chan->lc_pending);
                    168:                /*
                    169:                 * If we are just waiting for the queue to flush
                    170:                 * and it has, we may disconnect..
                    171:                 */
                    172:                if (chan->lc_flags & L2CAP_SHUTDOWN
                    173:                    && chan->lc_pending == 0) {
                    174:                        chan->lc_state = L2CAP_WAIT_DISCONNECT;
                    175:                        err = l2cap_send_disconnect_req(chan);
                    176:                        if (err)
                    177:                                l2cap_close(chan, err);
                    178:                }
                    179:
                    180:                return err;
                    181:        }
                    182:
                    183:        /*
                    184:         * We could check QoS/RFC mode here and optionally not send
                    185:         * the packet if we are not ready for any reason
                    186:         *
                    187:         * Also to support flush timeout then we might want to start
                    188:         * the timer going? (would need to keep some kind of record
                    189:         * of packets sent, possibly change it so that we allocate
                    190:         * the l2cap_pdu and fragment the packet, then hand it down
                    191:         * and get it back when its completed). Hm.
                    192:         */
                    193:
                    194:        IF_DEQUEUE(&chan->lc_txq, m);
                    195:
                    196:        KASSERT(chan->lc_link != NULL);
                    197:        KASSERT(m != NULL);
                    198:
                    199:        DPRINTFN(5, "CID #%d sending packet (%d bytes)\n",
                    200:                chan->lc_lcid, m->m_pkthdr.len);
                    201:
                    202:        chan->lc_pending++;
                    203:        return hci_acl_send(m, chan->lc_link, chan);
                    204: }

CVSweb