183aacedeSHasso Tepper /* $DragonFly: src/sys/netbt/l2cap_lower.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
283aacedeSHasso Tepper /* $OpenBSD: src/sys/netbt/l2cap_lower.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
383aacedeSHasso Tepper /* $NetBSD: l2cap_lower.c,v 1.7 2007/11/10 23:12:23 plunky Exp $ */
40a9108ebSHasso Tepper
50a9108ebSHasso Tepper /*-
60a9108ebSHasso Tepper * Copyright (c) 2005 Iain Hibbert.
70a9108ebSHasso Tepper * Copyright (c) 2006 Itronix Inc.
80a9108ebSHasso Tepper * All rights reserved.
90a9108ebSHasso Tepper *
100a9108ebSHasso Tepper * Redistribution and use in source and binary forms, with or without
110a9108ebSHasso Tepper * modification, are permitted provided that the following conditions
120a9108ebSHasso Tepper * are met:
130a9108ebSHasso Tepper * 1. Redistributions of source code must retain the above copyright
140a9108ebSHasso Tepper * notice, this list of conditions and the following disclaimer.
150a9108ebSHasso Tepper * 2. Redistributions in binary form must reproduce the above copyright
160a9108ebSHasso Tepper * notice, this list of conditions and the following disclaimer in the
170a9108ebSHasso Tepper * documentation and/or other materials provided with the distribution.
180a9108ebSHasso Tepper * 3. The name of Itronix Inc. may not be used to endorse
190a9108ebSHasso Tepper * or promote products derived from this software without specific
200a9108ebSHasso Tepper * prior written permission.
210a9108ebSHasso Tepper *
220a9108ebSHasso Tepper * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
230a9108ebSHasso Tepper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
240a9108ebSHasso Tepper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
250a9108ebSHasso Tepper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
260a9108ebSHasso Tepper * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
270a9108ebSHasso Tepper * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
280a9108ebSHasso Tepper * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
290a9108ebSHasso Tepper * ON ANY THEORY OF LIABILITY, WHETHER IN
300a9108ebSHasso Tepper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
310a9108ebSHasso Tepper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
320a9108ebSHasso Tepper * POSSIBILITY OF SUCH DAMAGE.
330a9108ebSHasso Tepper */
340a9108ebSHasso Tepper
350a9108ebSHasso Tepper #include <sys/param.h>
360a9108ebSHasso Tepper #include <sys/kernel.h>
370a9108ebSHasso Tepper #include <sys/malloc.h>
380a9108ebSHasso Tepper #include <sys/mbuf.h>
390a9108ebSHasso Tepper #include <sys/proc.h>
400a9108ebSHasso Tepper #include <sys/queue.h>
410a9108ebSHasso Tepper #include <sys/systm.h>
420a9108ebSHasso Tepper #include <sys/endian.h>
430a9108ebSHasso Tepper
440a9108ebSHasso Tepper #include <netbt/bluetooth.h>
450a9108ebSHasso Tepper #include <netbt/hci.h>
460a9108ebSHasso Tepper #include <netbt/l2cap.h>
470a9108ebSHasso Tepper
480a9108ebSHasso Tepper /****************************************************************************
490a9108ebSHasso Tepper *
500a9108ebSHasso Tepper * L2CAP Channel Lower Layer interface
510a9108ebSHasso Tepper */
520a9108ebSHasso Tepper
530a9108ebSHasso Tepper /*
540a9108ebSHasso Tepper * L2CAP channel is disconnected, could be:
550a9108ebSHasso Tepper *
560a9108ebSHasso Tepper * HCI layer received "Disconnect Complete" event for ACL link
570a9108ebSHasso Tepper * some Request timed out
580a9108ebSHasso Tepper * Config failed
590a9108ebSHasso Tepper * Other end reported invalid CID
600a9108ebSHasso Tepper * Normal disconnection
610a9108ebSHasso Tepper * Change link mode failed
620a9108ebSHasso Tepper */
630a9108ebSHasso Tepper void
l2cap_close(struct l2cap_channel * chan,int err)640a9108ebSHasso Tepper l2cap_close(struct l2cap_channel *chan, int err)
650a9108ebSHasso Tepper {
660a9108ebSHasso Tepper struct l2cap_pdu *pdu;
670a9108ebSHasso Tepper struct l2cap_req *req, *n;
680a9108ebSHasso Tepper
690a9108ebSHasso Tepper if (chan->lc_state == L2CAP_CLOSED)
700a9108ebSHasso Tepper return;
710a9108ebSHasso Tepper
720a9108ebSHasso Tepper /*
730a9108ebSHasso Tepper * Since any potential PDU could be half sent we just let it go,
740a9108ebSHasso Tepper * but disassociate ourselves from it as links deal with ownerless
750a9108ebSHasso Tepper * PDU's in any case. We could try harder to flush unsent packets
760a9108ebSHasso Tepper * but maybe its better to leave them in the queue?
770a9108ebSHasso Tepper */
780a9108ebSHasso Tepper TAILQ_FOREACH(pdu, &chan->lc_link->hl_txq, lp_next) {
790a9108ebSHasso Tepper if (pdu->lp_chan == chan)
800a9108ebSHasso Tepper pdu->lp_chan = NULL;
810a9108ebSHasso Tepper }
820a9108ebSHasso Tepper
830a9108ebSHasso Tepper /*
840a9108ebSHasso Tepper * and clear any outstanding requests..
850a9108ebSHasso Tepper */
860a9108ebSHasso Tepper req = TAILQ_FIRST(&chan->lc_link->hl_reqs);
870a9108ebSHasso Tepper while (req != NULL) {
880a9108ebSHasso Tepper n = TAILQ_NEXT(req, lr_next);
890a9108ebSHasso Tepper if (req->lr_chan == chan)
900a9108ebSHasso Tepper l2cap_request_free(req);
910a9108ebSHasso Tepper
920a9108ebSHasso Tepper req = n;
930a9108ebSHasso Tepper }
940a9108ebSHasso Tepper
950a9108ebSHasso Tepper chan->lc_pending = 0;
960a9108ebSHasso Tepper chan->lc_state = L2CAP_CLOSED;
970a9108ebSHasso Tepper hci_acl_close(chan->lc_link, err);
980a9108ebSHasso Tepper chan->lc_link = NULL;
990a9108ebSHasso Tepper
1000a9108ebSHasso Tepper (*chan->lc_proto->disconnected)(chan->lc_upper, err);
1010a9108ebSHasso Tepper }
1020a9108ebSHasso Tepper
1030a9108ebSHasso Tepper /*
1040a9108ebSHasso Tepper * Process incoming L2CAP frame from ACL link. We take off the B-Frame
1050a9108ebSHasso Tepper * header (which is present in all packets), verify the data length
1060a9108ebSHasso Tepper * and distribute the rest of the frame to the relevant channel
1070a9108ebSHasso Tepper * handler.
1080a9108ebSHasso Tepper */
1090a9108ebSHasso Tepper void
l2cap_recv_frame(struct mbuf * m,struct hci_link * link)1100a9108ebSHasso Tepper l2cap_recv_frame(struct mbuf *m, struct hci_link *link)
1110a9108ebSHasso Tepper {
1120a9108ebSHasso Tepper struct l2cap_channel *chan;
1130a9108ebSHasso Tepper l2cap_hdr_t hdr;
1140a9108ebSHasso Tepper
115*05d02a38SAaron LI m_copydata(m, 0, sizeof(hdr), &hdr);
1160a9108ebSHasso Tepper m_adj(m, sizeof(hdr));
1170a9108ebSHasso Tepper
1180a9108ebSHasso Tepper hdr.length = letoh16(hdr.length);
1190a9108ebSHasso Tepper hdr.dcid = letoh16(hdr.dcid);
1200a9108ebSHasso Tepper
1210a9108ebSHasso Tepper DPRINTFN(5, "(%s) received packet (%d bytes)\n",
12283aacedeSHasso Tepper device_get_nameunit(link->hl_unit->hci_dev), hdr.length);
1230a9108ebSHasso Tepper
1240a9108ebSHasso Tepper if (hdr.length != m->m_pkthdr.len)
1250a9108ebSHasso Tepper goto failed;
1260a9108ebSHasso Tepper
1270a9108ebSHasso Tepper if (hdr.dcid == L2CAP_SIGNAL_CID) {
1280a9108ebSHasso Tepper l2cap_recv_signal(m, link);
1290a9108ebSHasso Tepper return;
1300a9108ebSHasso Tepper }
1310a9108ebSHasso Tepper
1320a9108ebSHasso Tepper if (hdr.dcid == L2CAP_CLT_CID) {
1330a9108ebSHasso Tepper m_freem(m); /* TODO */
1340a9108ebSHasso Tepper return;
1350a9108ebSHasso Tepper }
1360a9108ebSHasso Tepper
1370a9108ebSHasso Tepper chan = l2cap_cid_lookup(hdr.dcid);
1380a9108ebSHasso Tepper if (chan != NULL && chan->lc_link == link
1390a9108ebSHasso Tepper && chan->lc_state == L2CAP_OPEN) {
1400a9108ebSHasso Tepper (*chan->lc_proto->input)(chan->lc_upper, m);
1410a9108ebSHasso Tepper return;
1420a9108ebSHasso Tepper }
1430a9108ebSHasso Tepper
1440a9108ebSHasso Tepper DPRINTF("(%s) dropping %d L2CAP data bytes for unknown CID #%d\n",
14583aacedeSHasso Tepper device_get_nameunit(link->hl_unit->hci_dev), hdr.length,
14683aacedeSHasso Tepper hdr.dcid);
1470a9108ebSHasso Tepper
1480a9108ebSHasso Tepper failed:
1490a9108ebSHasso Tepper m_freem(m);
1500a9108ebSHasso Tepper }
1510a9108ebSHasso Tepper
1520a9108ebSHasso Tepper /*
1530a9108ebSHasso Tepper * Start another L2CAP packet on its way. This is called from l2cap_send
1540a9108ebSHasso Tepper * (when no PDU is pending) and hci_acl_start (when PDU has been placed on
1550a9108ebSHasso Tepper * device queue). Thus we can have more than one PDU waiting at the device
1560a9108ebSHasso Tepper * if space is available but no single channel will hog the link.
1570a9108ebSHasso Tepper */
1580a9108ebSHasso Tepper int
l2cap_start(struct l2cap_channel * chan)1590a9108ebSHasso Tepper l2cap_start(struct l2cap_channel *chan)
1600a9108ebSHasso Tepper {
1610a9108ebSHasso Tepper struct mbuf *m;
1620a9108ebSHasso Tepper int err = 0;
1630a9108ebSHasso Tepper
1640a9108ebSHasso Tepper if (chan->lc_state != L2CAP_OPEN)
1650a9108ebSHasso Tepper return 0;
1660a9108ebSHasso Tepper
1670a9108ebSHasso Tepper if (IF_QEMPTY(&chan->lc_txq)) {
1680a9108ebSHasso Tepper DPRINTFN(5, "no data, pending = %d\n", chan->lc_pending);
1690a9108ebSHasso Tepper /*
1700a9108ebSHasso Tepper * If we are just waiting for the queue to flush
1710a9108ebSHasso Tepper * and it has, we may disconnect..
1720a9108ebSHasso Tepper */
1730a9108ebSHasso Tepper if (chan->lc_flags & L2CAP_SHUTDOWN
1740a9108ebSHasso Tepper && chan->lc_pending == 0) {
1750a9108ebSHasso Tepper chan->lc_state = L2CAP_WAIT_DISCONNECT;
1760a9108ebSHasso Tepper err = l2cap_send_disconnect_req(chan);
1770a9108ebSHasso Tepper if (err)
1780a9108ebSHasso Tepper l2cap_close(chan, err);
1790a9108ebSHasso Tepper }
1800a9108ebSHasso Tepper
1810a9108ebSHasso Tepper return err;
1820a9108ebSHasso Tepper }
1830a9108ebSHasso Tepper
1840a9108ebSHasso Tepper /*
1850a9108ebSHasso Tepper * We could check QoS/RFC mode here and optionally not send
1860a9108ebSHasso Tepper * the packet if we are not ready for any reason
1870a9108ebSHasso Tepper *
1880a9108ebSHasso Tepper * Also to support flush timeout then we might want to start
1890a9108ebSHasso Tepper * the timer going? (would need to keep some kind of record
1900a9108ebSHasso Tepper * of packets sent, possibly change it so that we allocate
1910a9108ebSHasso Tepper * the l2cap_pdu and fragment the packet, then hand it down
1920a9108ebSHasso Tepper * and get it back when its completed). Hm.
1930a9108ebSHasso Tepper */
1940a9108ebSHasso Tepper
1950a9108ebSHasso Tepper IF_DEQUEUE(&chan->lc_txq, m);
1960a9108ebSHasso Tepper
1970a9108ebSHasso Tepper KKASSERT(chan->lc_link != NULL);
1980a9108ebSHasso Tepper KKASSERT(m != NULL);
1990a9108ebSHasso Tepper
2000a9108ebSHasso Tepper DPRINTFN(5, "CID #%d sending packet (%d bytes)\n",
2010a9108ebSHasso Tepper chan->lc_lcid, m->m_pkthdr.len);
2020a9108ebSHasso Tepper
2030a9108ebSHasso Tepper chan->lc_pending++;
2040a9108ebSHasso Tepper return hci_acl_send(m, chan->lc_link, chan);
2050a9108ebSHasso Tepper }
206