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 /*      $NetBSD: l2cap_misc.c,v 1.7 2009/09/13 18:45:11 pooka Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 2005 Iain Hibbert.
    5  * Copyright (c) 2006 Itronix Inc.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of Itronix Inc. may not be used to endorse
   17  *    or promote products derived from this software without specific
   18  *    prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   27  * ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: l2cap_misc.c,v 1.7 2009/09/13 18:45:11 pooka Exp $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/proc.h>
   40 #include <sys/queue.h>
   41 #include <sys/systm.h>
   42 
   43 #include <netbt/bluetooth.h>
   44 #include <netbt/hci.h>
   45 #include <netbt/l2cap.h>
   46 
   47 struct l2cap_channel_list
   48         l2cap_active_list = LIST_HEAD_INITIALIZER(l2cap_active_list);
   49 struct l2cap_channel_list
   50         l2cap_listen_list = LIST_HEAD_INITIALIZER(l2cap_listen_list);
   51 
   52 struct pool l2cap_req_pool, 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         pool_init(&l2cap_req_pool, sizeof(struct l2cap_req), 0, 0, 0,
   75             "l2cap_req", NULL, IPL_SOFTNET);
   76         pool_init(&l2cap_pdu_pool, sizeof(struct l2cap_pdu), 0, 0, 0,
   77             "l2cap_pdu", NULL, IPL_SOFTNET);
   78 }
   79 
   80 /*
   81  * Set Link Mode on channel
   82  */
   83 int
   84 l2cap_setmode(struct l2cap_channel *chan)
   85 {
   86 
   87         KASSERT(chan != NULL);
   88         KASSERT(chan->lc_link != NULL);
   89 
   90         DPRINTF("CID #%d, auth %s, encrypt %s, secure %s\n", chan->lc_lcid,
   91                 (chan->lc_mode & L2CAP_LM_AUTH ? "yes" : "no"),
   92                 (chan->lc_mode & L2CAP_LM_ENCRYPT ? "yes" : "no"),
   93                 (chan->lc_mode & L2CAP_LM_SECURE ? "yes" : "no"));
   94 
   95         if (chan->lc_mode & L2CAP_LM_AUTH)
   96                 chan->lc_link->hl_flags |= HCI_LINK_AUTH_REQ;
   97 
   98         if (chan->lc_mode & L2CAP_LM_ENCRYPT)
   99                 chan->lc_link->hl_flags |= HCI_LINK_ENCRYPT_REQ;
  100 
  101         if (chan->lc_mode & L2CAP_LM_SECURE)
  102                 chan->lc_link->hl_flags |= HCI_LINK_SECURE_REQ;
  103 
  104         return hci_acl_setmode(chan->lc_link);
  105 }
  106 
  107 /*
  108  * Allocate a new Request structure & ID and set the timer going
  109  */
  110 int
  111 l2cap_request_alloc(struct l2cap_channel *chan, uint8_t code)
  112 {
  113         struct hci_link *link = chan->lc_link;
  114         struct l2cap_req *req;
  115         int next_id;
  116 
  117         if (link == NULL)
  118                 return ENETDOWN;
  119 
  120         /* find next ID (0 is not allowed) */
  121         next_id = link->hl_lastid + 1;
  122         if (next_id > 0xff)
  123                 next_id = 1;
  124 
  125         /* Ouroboros check */
  126         req = TAILQ_FIRST(&link->hl_reqs);
  127         if (req && req->lr_id == next_id)
  128                 return ENFILE;
  129 
  130         req = pool_get(&l2cap_req_pool, PR_NOWAIT);
  131         if (req == NULL)
  132                 return ENOMEM;
  133 
  134         req->lr_id = link->hl_lastid = next_id;
  135 
  136         req->lr_code = code;
  137         req->lr_chan = chan;
  138         req->lr_link = link;
  139 
  140         callout_init(&req->lr_rtx, 0);
  141         callout_setfunc(&req->lr_rtx, l2cap_rtx, req);
  142         callout_schedule(&req->lr_rtx, l2cap_response_timeout * hz);
  143 
  144         TAILQ_INSERT_TAIL(&link->hl_reqs, req, lr_next);
  145 
  146         return 0;
  147 }
  148 
  149 /*
  150  * Find a running request for this link
  151  */
  152 struct l2cap_req *
  153 l2cap_request_lookup(struct hci_link *link, uint8_t id)
  154 {
  155         struct l2cap_req *req;
  156 
  157         TAILQ_FOREACH(req, &link->hl_reqs, lr_next) {
  158                 if (req->lr_id == id)
  159                         return req;
  160         }
  161 
  162         return NULL;
  163 }
  164 
  165 /*
  166  * Halt and free a request
  167  */
  168 void
  169 l2cap_request_free(struct l2cap_req *req)
  170 {
  171         struct hci_link *link = req->lr_link;
  172 
  173         callout_stop(&req->lr_rtx);
  174         if (callout_invoking(&req->lr_rtx))
  175                 return;
  176 
  177         callout_destroy(&req->lr_rtx);
  178 
  179         TAILQ_REMOVE(&link->hl_reqs, req, lr_next);
  180         pool_put(&l2cap_req_pool, req);
  181 }
  182 
  183 /*
  184  * Response Timeout eXpired
  185  *
  186  * No response to our request, so deal with it as best we can.
  187  *
  188  * XXX should try again at least with ertx?
  189  */
  190 void
  191 l2cap_rtx(void *arg)
  192 {
  193         struct l2cap_req *req = arg;
  194         struct l2cap_channel *chan;
  195 
  196         mutex_enter(bt_lock);
  197         callout_ack(&req->lr_rtx);
  198 
  199         chan = req->lr_chan;
  200         l2cap_request_free(req);
  201 
  202         DPRINTF("cid %d, ident %d\n", (chan ? chan->lc_lcid : 0), req->lr_id);
  203 
  204         if (chan && chan->lc_state != L2CAP_CLOSED)
  205                 l2cap_close(chan, ETIMEDOUT);
  206 
  207         mutex_exit(bt_lock);
  208 }
  209 
  210 /*
  211  * Allocate next available CID to channel. We keep a single
  212  * ordered list of channels, so find the first gap.
  213  *
  214  * If this turns out to be not enough (!), could use a
  215  * list per HCI unit..
  216  */
  217 int
  218 l2cap_cid_alloc(struct l2cap_channel *chan)
  219 {
  220         struct l2cap_channel *used, *prev = NULL;
  221         uint16_t cid = L2CAP_FIRST_CID;
  222 
  223         if (chan->lc_lcid != L2CAP_NULL_CID || chan->lc_state != L2CAP_CLOSED)
  224                 return EISCONN;
  225 
  226         LIST_FOREACH(used, &l2cap_active_list, lc_ncid) {
  227                 if (used->lc_lcid > cid)
  228                         break;  /* found our gap */
  229 
  230                 KASSERT(used->lc_lcid == cid);
  231                 cid++;
  232 
  233                 if (cid == L2CAP_LAST_CID)
  234                         return ENFILE;
  235 
  236                 prev = used;    /* for insert after */
  237         }
  238 
  239         chan->lc_lcid = cid;
  240 
  241         if (prev)
  242                 LIST_INSERT_AFTER(prev, chan, lc_ncid);
  243         else
  244                 LIST_INSERT_HEAD(&l2cap_active_list, chan, lc_ncid);
  245 
  246         return 0;
  247 }
  248 
  249 /*
  250  * Find channel with CID
  251  */
  252 struct l2cap_channel *
  253 l2cap_cid_lookup(uint16_t cid)
  254 {
  255         struct l2cap_channel *chan;
  256 
  257         LIST_FOREACH(chan, &l2cap_active_list, lc_ncid) {
  258                 if (chan->lc_lcid == cid)
  259                         return chan;
  260 
  261                 if (chan->lc_lcid > cid)
  262                         return NULL;
  263         }
  264 
  265         return NULL;
  266 }

Cache object: 2695818a3572fdedbed42cd20b66a406


[ 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.