The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netbt/l2cap_misc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $OpenBSD: src/sys/netbt/l2cap_misc.c,v 1.3 2008/02/24 21:34:48 uwe Exp $ */
    2 /* $NetBSD: l2cap_misc.c,v 1.5 2007/11/03 17:20:17 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/param.h>
   35 #include <sys/kernel.h>
   36 #include <sys/mbuf.h>
   37 #include <sys/proc.h>
   38 #include <sys/queue.h>
   39 #include <sys/systm.h>
   40 #include <net/if.h>
   41 
   42 #include <netbt/bluetooth.h>
   43 #include <netbt/hci.h>
   44 #include <netbt/l2cap.h>
   45 
   46 struct l2cap_channel_list
   47         l2cap_active_list = LIST_HEAD_INITIALIZER(l2cap_active_list);
   48 struct l2cap_channel_list
   49         l2cap_listen_list = LIST_HEAD_INITIALIZER(l2cap_listen_list);
   50 
   51 vm_zone_t l2cap_req_pool;
   52 vm_zone_t l2cap_pdu_pool;
   53 
   54 const l2cap_qos_t l2cap_default_qos = {
   55         0,                      /* flags */
   56         L2CAP_QOS_BEST_EFFORT,  /* service type */
   57         0x00000000,             /* token rate */
   58         0x00000000,             /* token bucket size */
   59         0x00000000,             /* peak bandwidth */
   60         0xffffffff,             /* latency */
   61         0xffffffff              /* delay variation */
   62 };
   63 
   64 /*
   65  * L2CAP request timeouts
   66  */
   67 int l2cap_response_timeout = 30;                /* seconds */
   68 int l2cap_response_extended_timeout = 180;      /* seconds */
   69 
   70 void
   71 l2cap_init(void)
   72 {
   73 }
   74 
   75 /*
   76  * Set Link Mode on channel
   77  */
   78 int
   79 l2cap_setmode(struct l2cap_channel *chan)
   80 {
   81         KKASSERT(chan != NULL);
   82         KKASSERT(chan->lc_link != NULL);
   83 
   84         DPRINTF("(%s) CID #%d, auth %s, encrypt %s, secure %s\n",
   85             device_get_nameunit(chan->lc_link->hl_unit->hci_dev), chan->lc_lcid,
   86             (chan->lc_mode & L2CAP_LM_AUTH ? "yes" : "no"),
   87             (chan->lc_mode & L2CAP_LM_ENCRYPT ? "yes" : "no"),
   88             (chan->lc_mode & L2CAP_LM_SECURE ? "yes" : "no"));
   89 
   90         if (chan->lc_mode & L2CAP_LM_AUTH)
   91                 chan->lc_link->hl_flags |= HCI_LINK_AUTH_REQ;
   92 
   93         if (chan->lc_mode & L2CAP_LM_ENCRYPT)
   94                 chan->lc_link->hl_flags |= HCI_LINK_ENCRYPT_REQ;
   95 
   96         if (chan->lc_mode & L2CAP_LM_SECURE)
   97                 chan->lc_link->hl_flags |= HCI_LINK_SECURE_REQ;
   98 
   99         return hci_acl_setmode(chan->lc_link);
  100 }
  101 
  102 /*
  103  * Allocate a new Request structure & ID and set the timer going
  104  */
  105 int
  106 l2cap_request_alloc(struct l2cap_channel *chan, uint8_t code)
  107 {
  108         struct hci_link *link = chan->lc_link;
  109         struct l2cap_req *req;
  110         int next_id;
  111 
  112         if (link == NULL)
  113                 return ENETDOWN;
  114 
  115         /* find next ID (0 is not allowed) */
  116         next_id = link->hl_lastid + 1;
  117         if (next_id > 0xff)
  118                 next_id = 1;
  119 
  120         /* Ouroboros check */
  121         req = TAILQ_FIRST(&link->hl_reqs);
  122         if (req && req->lr_id == next_id)
  123                 return ENFILE;
  124 
  125         req = zalloc(l2cap_req_pool);
  126         if (req == NULL)
  127                 return ENOMEM;
  128 
  129         req->lr_id = link->hl_lastid = next_id;
  130 
  131         req->lr_code = code;
  132         req->lr_chan = chan;
  133         req->lr_link = link;
  134 
  135         callout_init(&req->lr_rtx);
  136         callout_reset(&req->lr_rtx, l2cap_response_timeout * hz,
  137             l2cap_rtx, req);
  138 
  139         TAILQ_INSERT_TAIL(&link->hl_reqs, req, lr_next);
  140 
  141         return 0;
  142 }
  143 
  144 /*
  145  * Find a running request for this link
  146  */
  147 struct l2cap_req *
  148 l2cap_request_lookup(struct hci_link *link, uint8_t id)
  149 {
  150         struct l2cap_req *req;
  151 
  152         TAILQ_FOREACH(req, &link->hl_reqs, lr_next) {
  153                 if (req->lr_id == id)
  154                         return req;
  155         }
  156 
  157         return NULL;
  158 }
  159 
  160 /*
  161  * Halt and free a request
  162  */
  163 void
  164 l2cap_request_free(struct l2cap_req *req)
  165 {
  166         struct hci_link *link = req->lr_link;
  167 
  168         callout_stop(&req->lr_rtx);
  169         if (callout_active(&req->lr_rtx))
  170                 return;
  171 
  172         TAILQ_REMOVE(&link->hl_reqs, req, lr_next);
  173         zfree(l2cap_req_pool, req);
  174 }
  175 
  176 /*
  177  * Response Timeout eXpired
  178  *
  179  * No response to our request, so deal with it as best we can.
  180  *
  181  * XXX should try again at least with ertx?
  182  */
  183 void
  184 l2cap_rtx(void *arg)
  185 {
  186         struct l2cap_req *req = arg;
  187         struct l2cap_channel *chan;
  188 
  189         chan = req->lr_chan;
  190         l2cap_request_free(req);
  191 
  192         DPRINTF("cid %d, ident %d\n", (chan ? chan->lc_lcid : 0), req->lr_id);
  193 
  194         if (chan && chan->lc_state != L2CAP_CLOSED)
  195                 l2cap_close(chan, ETIMEDOUT);
  196 
  197 }
  198 
  199 /*
  200  * Allocate next available CID to channel. We keep a single
  201  * ordered list of channels, so find the first gap.
  202  *
  203  * If this turns out to be not enough (!), could use a
  204  * list per HCI unit..
  205  */
  206 int
  207 l2cap_cid_alloc(struct l2cap_channel *chan)
  208 {
  209         struct l2cap_channel *used, *prev = NULL;
  210         uint16_t cid = L2CAP_FIRST_CID;
  211 
  212         if (chan->lc_lcid != L2CAP_NULL_CID || chan->lc_state != L2CAP_CLOSED)
  213                 return EISCONN;
  214 
  215         LIST_FOREACH(used, &l2cap_active_list, lc_ncid) {
  216                 if (used->lc_lcid > cid)
  217                         break;  /* found our gap */
  218 
  219                 KKASSERT(used->lc_lcid == cid);
  220                 cid++;
  221 
  222                 if (cid == L2CAP_LAST_CID)
  223                         return ENFILE;
  224 
  225                 prev = used;    /* for insert after */
  226         }
  227 
  228         chan->lc_lcid = cid;
  229 
  230         if (prev)
  231                 LIST_INSERT_AFTER(prev, chan, lc_ncid);
  232         else
  233                 LIST_INSERT_HEAD(&l2cap_active_list, chan, lc_ncid);
  234 
  235         return 0;
  236 }
  237 
  238 /*
  239  * Find channel with CID
  240  */
  241 struct l2cap_channel *
  242 l2cap_cid_lookup(uint16_t cid)
  243 {
  244         struct l2cap_channel *chan;
  245 
  246         LIST_FOREACH(chan, &l2cap_active_list, lc_ncid) {
  247                 if (chan->lc_lcid == cid)
  248                         return chan;
  249 
  250                 if (chan->lc_lcid > cid)
  251                         return NULL;
  252         }
  253 
  254         return NULL;
  255 }

Cache object: 41ce99010f54df6dd9c0b5df638d8abc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.