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/netgraph/bluetooth/l2cap/ng_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 /*
    2  * ng_l2cap_misc.c
    3  */
    4 
    5 /*-
    6  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    7  *
    8  * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com>
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $Id: ng_l2cap_misc.c,v 1.5 2003/09/08 19:11:45 max Exp $
   33  * $FreeBSD$
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/queue.h>
   42 #include <netgraph/ng_message.h>
   43 #include <netgraph/netgraph.h>
   44 #include <netgraph/bluetooth/include/ng_bluetooth.h>
   45 #include <netgraph/bluetooth/include/ng_hci.h>
   46 #include <netgraph/bluetooth/include/ng_l2cap.h>
   47 #include <netgraph/bluetooth/l2cap/ng_l2cap_var.h>
   48 #include <netgraph/bluetooth/l2cap/ng_l2cap_cmds.h>
   49 #include <netgraph/bluetooth/l2cap/ng_l2cap_evnt.h>
   50 #include <netgraph/bluetooth/l2cap/ng_l2cap_llpi.h>
   51 #include <netgraph/bluetooth/l2cap/ng_l2cap_ulpi.h>
   52 #include <netgraph/bluetooth/l2cap/ng_l2cap_misc.h>
   53 
   54 static u_int16_t        ng_l2cap_get_cid        (ng_l2cap_p, int);
   55 
   56 /******************************************************************************
   57  ******************************************************************************
   58  **                              Utility routines
   59  ******************************************************************************
   60  ******************************************************************************/
   61 
   62 /*
   63  * Send hook information to the upper layer
   64  */
   65 
   66 void
   67 ng_l2cap_send_hook_info(node_p node, hook_p hook, void *arg1, int arg2)
   68 {
   69         ng_l2cap_p       l2cap = NULL;
   70         struct ng_mesg  *msg = NULL;
   71         int              error = 0;
   72         ng_l2cap_node_hook_info_ep *ep ;
   73 
   74         if (node == NULL || NG_NODE_NOT_VALID(node) ||
   75             hook == NULL || NG_HOOK_NOT_VALID(hook))
   76                 return;
   77 
   78         l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node);
   79         if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci) ||
   80             bcmp(&l2cap->bdaddr, NG_HCI_BDADDR_ANY, sizeof(l2cap->bdaddr)) == 0)
   81                 return;
   82 
   83         NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_NODE_HOOK_INFO,
   84                      sizeof(*ep), M_NOWAIT);
   85 
   86         if (msg != NULL) {
   87                 ep = (ng_l2cap_node_hook_info_ep *) &msg->data;
   88                 bcopy(&l2cap->bdaddr, &ep->addr, sizeof(bdaddr_t));
   89                 NG_SEND_MSG_HOOK(error, node, msg, hook, 0);
   90         } else
   91                 error = ENOMEM;
   92 
   93         if (error != 0)
   94                 NG_L2CAP_INFO(
   95 "%s: %s - failed to send HOOK_INFO message to hook \"%s\", error=%d\n",
   96                         __func__, NG_NODE_NAME(l2cap->node), NG_HOOK_NAME(hook),
   97                         error);
   98 } /* ng_l2cap_send_hook_info */
   99 
  100 /*
  101  * Create new connection descriptor for the "remote" unit. 
  102  * Will link connection descriptor to the l2cap node.
  103  */
  104 
  105 ng_l2cap_con_p
  106 ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr, int type)
  107 {
  108         static int      fake_con_handle = 0x0f00;
  109         ng_l2cap_con_p  con = NULL;
  110 
  111         /* Create new connection descriptor */
  112         con = malloc(sizeof(*con), M_NETGRAPH_L2CAP,
  113                 M_NOWAIT|M_ZERO);
  114         if (con == NULL)
  115                 return (NULL);
  116 
  117         con->l2cap = l2cap;
  118         con->state = NG_L2CAP_CON_CLOSED;
  119         con->encryption = 0;
  120         /*
  121          * XXX
  122          *
  123          * Assign fake connection handle to the connection descriptor.
  124          * Bluetooth specification marks 0x0f00 - 0x0fff connection 
  125          * handles as reserved. We need this fake connection handles 
  126          * for timeouts. Connection handle will be passed as argument
  127          * to timeout so when timeout happens we can find the right
  128          * connection descriptor. We can not pass pointers, because
  129          * timeouts are external (to Netgraph) events and there might
  130          * be a race when node/hook goes down and timeout event already
  131          * went into node's queue
  132          */
  133 
  134         con->con_handle = fake_con_handle ++;
  135         if (fake_con_handle > 0x0fff)
  136                 fake_con_handle = 0x0f00;
  137 
  138         bcopy(bdaddr, &con->remote, sizeof(con->remote));
  139         con->linktype = type;
  140         ng_callout_init(&con->con_timo);
  141 
  142         con->ident = NG_L2CAP_FIRST_IDENT - 1;
  143         TAILQ_INIT(&con->cmd_list);
  144 
  145         /* Link connection */
  146         LIST_INSERT_HEAD(&l2cap->con_list, con, next); 
  147 
  148         return (con);
  149 } /* ng_l2cap_new_con */
  150 
  151 /*
  152  * Add reference to the connection descriptor
  153  */
  154 
  155 void
  156 ng_l2cap_con_ref(ng_l2cap_con_p con)
  157 {
  158         con->refcnt ++;
  159 
  160         if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) {
  161                 if ((con->state != NG_L2CAP_CON_OPEN) ||
  162                     (con->flags & NG_L2CAP_CON_OUTGOING) == 0)
  163                         panic(
  164 "%s: %s - bad auto disconnect timeout, state=%d, flags=%#x\n",
  165                                 __func__, NG_NODE_NAME(con->l2cap->node),
  166                                 con->state, con->flags);
  167 
  168                 ng_l2cap_discon_untimeout(con);
  169         }
  170 } /* ng_l2cap_con_ref */
  171 
  172 /*
  173  * Remove reference from the connection descriptor
  174  */
  175 
  176 void
  177 ng_l2cap_con_unref(ng_l2cap_con_p con)
  178 {
  179         con->refcnt --;
  180 
  181         if (con->refcnt < 0)
  182                 panic(
  183 "%s: %s - con->refcnt < 0\n", __func__, NG_NODE_NAME(con->l2cap->node));
  184 
  185         /*
  186          * Set auto disconnect timer only if the following conditions are met:
  187          * 1) we have no reference on the connection
  188          * 2) connection is in OPEN state
  189          * 3) it is an outgoing connection
  190          * 4) disconnect timeout > 0
  191          * 5) connection is not dying
  192          */
  193 
  194         if ((con->refcnt == 0) &&
  195             (con->state == NG_L2CAP_CON_OPEN) &&
  196             (con->flags & NG_L2CAP_CON_OUTGOING) && 
  197             (con->l2cap->discon_timo > 0) &&
  198             ((con->flags & NG_L2CAP_CON_DYING) == 0))
  199                 ng_l2cap_discon_timeout(con);
  200 } /* ng_l2cap_con_unref */
  201 
  202 /*
  203  * Set auto disconnect timeout
  204  * XXX FIXME: check return code from ng_callout
  205  */
  206 
  207 int
  208 ng_l2cap_discon_timeout(ng_l2cap_con_p con)
  209 {
  210         if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
  211                 panic(
  212 "%s: %s - invalid timeout, state=%d, flags=%#x\n",
  213                         __func__, NG_NODE_NAME(con->l2cap->node),
  214                         con->state, con->flags);
  215 
  216         con->flags |= NG_L2CAP_CON_AUTO_DISCON_TIMO;
  217         ng_callout(&con->con_timo, con->l2cap->node, NULL,
  218                                 con->l2cap->discon_timo * hz,
  219                                 ng_l2cap_process_discon_timeout, NULL,
  220                                 con->con_handle);
  221 
  222         return (0);
  223 } /* ng_l2cap_discon_timeout */
  224 
  225 /*
  226  * Unset auto disconnect timeout
  227  */
  228 
  229 int
  230 ng_l2cap_discon_untimeout(ng_l2cap_con_p con)
  231 {
  232         if (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO))
  233                 panic(
  234 "%s: %s - no disconnect timeout, state=%d, flags=%#x\n",
  235                         __func__,  NG_NODE_NAME(con->l2cap->node),
  236                         con->state, con->flags);
  237 
  238         if (ng_uncallout(&con->con_timo, con->l2cap->node) < 1)
  239                 return (ETIMEDOUT);
  240 
  241         con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
  242 
  243         return (0);
  244 } /* ng_l2cap_discon_untimeout */
  245 
  246 /*
  247  * Free connection descriptor. Will unlink connection and free everything.
  248  */
  249 
  250 void
  251 ng_l2cap_free_con(ng_l2cap_con_p con)
  252 {
  253         ng_l2cap_chan_p f = NULL, n = NULL;
  254 
  255         con->state = NG_L2CAP_CON_CLOSED;
  256 
  257         while (con->tx_pkt != NULL) {
  258                 struct mbuf     *m = con->tx_pkt->m_nextpkt;
  259 
  260                 m_freem(con->tx_pkt);
  261                 con->tx_pkt = m;
  262         }
  263 
  264         NG_FREE_M(con->rx_pkt);
  265 
  266         for (f = LIST_FIRST(&con->l2cap->chan_list); f != NULL; ) {
  267                 n = LIST_NEXT(f, next);
  268 
  269                 if (f->con == con)
  270                         ng_l2cap_free_chan(f);
  271 
  272                 f = n;
  273         }
  274 
  275         while (!TAILQ_EMPTY(&con->cmd_list)) {
  276                 ng_l2cap_cmd_p  cmd = TAILQ_FIRST(&con->cmd_list);
  277 
  278                 ng_l2cap_unlink_cmd(cmd);
  279                 if (cmd->flags & NG_L2CAP_CMD_PENDING)
  280                         ng_l2cap_command_untimeout(cmd);
  281                 ng_l2cap_free_cmd(cmd);
  282         }
  283 
  284         if (con->flags & (NG_L2CAP_CON_AUTO_DISCON_TIMO|NG_L2CAP_CON_LP_TIMO))
  285                 panic(
  286 "%s: %s - timeout pending! state=%d, flags=%#x\n",
  287                         __func__,  NG_NODE_NAME(con->l2cap->node),
  288                         con->state, con->flags);
  289 
  290         LIST_REMOVE(con, next);
  291 
  292         bzero(con, sizeof(*con));
  293         free(con, M_NETGRAPH_L2CAP);
  294 } /* ng_l2cap_free_con */
  295 
  296 /*
  297  * Get connection by "remote" address
  298  */
  299 
  300 ng_l2cap_con_p
  301 ng_l2cap_con_by_addr(ng_l2cap_p l2cap, bdaddr_p bdaddr, unsigned int type)
  302 {
  303         ng_l2cap_con_p  con = NULL;
  304 
  305         LIST_FOREACH(con, &l2cap->con_list, next)
  306                 if ((bcmp(bdaddr, &con->remote, sizeof(con->remote)) == 0)&&
  307                     (con->linktype == type))
  308                         break;
  309 
  310         return (con);
  311 } /* ng_l2cap_con_by_addr */
  312 
  313 /*
  314  * Get connection by "handle" 
  315  */
  316 
  317 ng_l2cap_con_p
  318 ng_l2cap_con_by_handle(ng_l2cap_p l2cap, u_int16_t con_handle)
  319 {
  320         ng_l2cap_con_p  con = NULL;
  321 
  322         LIST_FOREACH(con, &l2cap->con_list, next)
  323                 if (con->con_handle == con_handle)
  324                         break;
  325 
  326         return (con);
  327 } /* ng_l2cap_con_by_handle */
  328 
  329 /*
  330  * Allocate new L2CAP channel descriptor on "con" connection with "psm".
  331  * Will link the channel to the l2cap node
  332  */
  333 
  334 ng_l2cap_chan_p
  335 ng_l2cap_new_chan(ng_l2cap_p l2cap, ng_l2cap_con_p con, u_int16_t psm, int idtype)
  336 {
  337         ng_l2cap_chan_p ch = NULL;
  338 
  339         ch = malloc(sizeof(*ch), M_NETGRAPH_L2CAP,
  340                 M_NOWAIT|M_ZERO);
  341         if (ch == NULL)
  342                 return (NULL);
  343         if(idtype == NG_L2CAP_L2CA_IDTYPE_ATT){
  344                 ch->scid = ch->dcid = NG_L2CAP_ATT_CID;
  345         }else if(idtype == NG_L2CAP_L2CA_IDTYPE_SMP){
  346                 ch->scid = ch->dcid = NG_L2CAP_SMP_CID;
  347         }else{
  348                 ch->scid = ng_l2cap_get_cid(l2cap,
  349                                             (con->linktype!= NG_HCI_LINK_ACL));
  350         }
  351 
  352         ch->idtype = idtype;
  353         if (ch->scid != NG_L2CAP_NULL_CID) {
  354                 /* Initialize channel */
  355                 ch->psm = psm;
  356                 ch->con = con;
  357                 ch->state = NG_L2CAP_CLOSED;
  358 
  359                 /* Set MTU and flow control settings to defaults */
  360                 ch->imtu = NG_L2CAP_MTU_DEFAULT;
  361                 bcopy(ng_l2cap_default_flow(), &ch->iflow, sizeof(ch->iflow));
  362 
  363                 ch->omtu = NG_L2CAP_MTU_DEFAULT;
  364                 bcopy(ng_l2cap_default_flow(), &ch->oflow, sizeof(ch->oflow));
  365 
  366                 ch->flush_timo = NG_L2CAP_FLUSH_TIMO_DEFAULT;
  367                 ch->link_timo = NG_L2CAP_LINK_TIMO_DEFAULT;
  368 
  369                 LIST_INSERT_HEAD(&l2cap->chan_list, ch, next);
  370 
  371                 ng_l2cap_con_ref(con);
  372         } else {
  373                 bzero(ch, sizeof(*ch));
  374                 free(ch, M_NETGRAPH_L2CAP);
  375                 ch = NULL;
  376         }
  377 
  378         return (ch);
  379 } /* ng_l2cap_new_chan */
  380 
  381 ng_l2cap_chan_p
  382 ng_l2cap_chan_by_scid(ng_l2cap_p l2cap, u_int16_t scid, int idtype)
  383 {
  384         ng_l2cap_chan_p ch = NULL;
  385 
  386         if((idtype == NG_L2CAP_L2CA_IDTYPE_ATT)||
  387            (idtype == NG_L2CAP_L2CA_IDTYPE_SMP)){
  388                 return NULL;
  389         }
  390 
  391         LIST_FOREACH(ch, &l2cap->chan_list, next){
  392                 if((idtype != NG_L2CAP_L2CA_IDTYPE_BREDR)&&
  393                    (ch->con->linktype == NG_HCI_LINK_ACL ))
  394                         continue;
  395                 if((idtype != NG_L2CAP_L2CA_IDTYPE_LE)&&
  396                    (ch->con->linktype != NG_HCI_LINK_ACL ))
  397                         continue;
  398                 if (ch->scid == scid)
  399                         break;
  400         }
  401         return (ch);
  402 } /* ng_l2cap_chan_by_scid */
  403 
  404 ng_l2cap_chan_p
  405 ng_l2cap_chan_by_conhandle(ng_l2cap_p l2cap, uint16_t scid,
  406                            u_int16_t con_handle)
  407 {
  408         ng_l2cap_chan_p ch = NULL;
  409 
  410         LIST_FOREACH(ch, &l2cap->chan_list, next){
  411                 if ((ch->scid == scid) &&
  412                     (ch->con->con_handle == con_handle))
  413                         break;
  414         }
  415         return (ch);
  416 } /* ng_l2cap_chan_by_scid */
  417 
  418 /*
  419  * Free channel descriptor.
  420  */
  421 
  422 void
  423 ng_l2cap_free_chan(ng_l2cap_chan_p ch)
  424 {
  425         ng_l2cap_cmd_p  f = NULL, n = NULL;
  426 
  427         f = TAILQ_FIRST(&ch->con->cmd_list);
  428 
  429         while (f != NULL) {
  430                 n = TAILQ_NEXT(f, next);
  431 
  432                 if (f->ch == ch) {
  433                         ng_l2cap_unlink_cmd(f);
  434                         if (f->flags & NG_L2CAP_CMD_PENDING)
  435                                 ng_l2cap_command_untimeout(f);
  436                         ng_l2cap_free_cmd(f);
  437                 }
  438 
  439                 f = n;
  440         }
  441 
  442         LIST_REMOVE(ch, next);
  443 
  444         ng_l2cap_con_unref(ch->con);
  445 
  446         bzero(ch, sizeof(*ch));
  447         free(ch, M_NETGRAPH_L2CAP);
  448 } /* ng_l2cap_free_chan */
  449 
  450 /*
  451  * Create new L2CAP command descriptor. WILL NOT add command to the queue.
  452  */
  453 
  454 ng_l2cap_cmd_p
  455 ng_l2cap_new_cmd(ng_l2cap_con_p con, ng_l2cap_chan_p ch, u_int8_t ident,
  456                 u_int8_t code, u_int32_t token)
  457 {
  458         ng_l2cap_cmd_p  cmd = NULL;
  459 
  460         KASSERT((ch == NULL || ch->con == con),
  461 ("%s: %s - invalid channel pointer!\n",
  462                 __func__, NG_NODE_NAME(con->l2cap->node)));
  463 
  464         cmd = malloc(sizeof(*cmd), M_NETGRAPH_L2CAP,
  465                 M_NOWAIT|M_ZERO);
  466         if (cmd == NULL)
  467                 return (NULL);
  468 
  469         cmd->con = con;
  470         cmd->ch = ch;
  471         cmd->ident = ident;
  472         cmd->code = code;
  473         cmd->token = token;
  474         ng_callout_init(&cmd->timo);
  475 
  476         return (cmd);
  477 } /* ng_l2cap_new_cmd */
  478 
  479 /*
  480  * Get pending (i.e. initiated by local side) L2CAP command descriptor by ident
  481  */
  482 
  483 ng_l2cap_cmd_p
  484 ng_l2cap_cmd_by_ident(ng_l2cap_con_p con, u_int8_t ident)
  485 {
  486         ng_l2cap_cmd_p  cmd = NULL;
  487 
  488         TAILQ_FOREACH(cmd, &con->cmd_list, next) {
  489                 if ((cmd->flags & NG_L2CAP_CMD_PENDING) && cmd->ident == ident) {
  490                         KASSERT((cmd->con == con),
  491 ("%s: %s - invalid connection pointer!\n",
  492                                 __func__, NG_NODE_NAME(con->l2cap->node)));
  493 
  494                         break;
  495                 }
  496         }
  497 
  498         return (cmd);
  499 } /* ng_l2cap_cmd_by_ident */
  500 
  501 /*
  502  * Set LP timeout
  503  * XXX FIXME: check return code from ng_callout
  504  */
  505 
  506 int
  507 ng_l2cap_lp_timeout(ng_l2cap_con_p con)
  508 {
  509         if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
  510                 panic(
  511 "%s: %s - invalid timeout, state=%d, flags=%#x\n",
  512                         __func__, NG_NODE_NAME(con->l2cap->node),
  513                         con->state, con->flags);
  514 
  515         con->flags |= NG_L2CAP_CON_LP_TIMO;
  516         ng_callout(&con->con_timo, con->l2cap->node, NULL,
  517                                 bluetooth_hci_connect_timeout(),
  518                                 ng_l2cap_process_lp_timeout, NULL,
  519                                 con->con_handle);
  520 
  521         return (0);
  522 } /* ng_l2cap_lp_timeout */
  523 
  524 /*
  525  * Unset LP timeout
  526  */
  527 
  528 int
  529 ng_l2cap_lp_untimeout(ng_l2cap_con_p con)
  530 {
  531         if (!(con->flags & NG_L2CAP_CON_LP_TIMO))
  532                 panic(
  533 "%s: %s - no LP connection timeout, state=%d, flags=%#x\n",
  534                         __func__,  NG_NODE_NAME(con->l2cap->node),
  535                         con->state, con->flags);
  536 
  537         if (ng_uncallout(&con->con_timo, con->l2cap->node) < 1)
  538                 return (ETIMEDOUT);
  539 
  540         con->flags &= ~NG_L2CAP_CON_LP_TIMO;
  541 
  542         return (0);
  543 } /* ng_l2cap_lp_untimeout */
  544 
  545 /*
  546  * Set L2CAP command timeout
  547  * XXX FIXME: check return code from ng_callout
  548  */
  549 
  550 int
  551 ng_l2cap_command_timeout(ng_l2cap_cmd_p cmd, int timo)
  552 {
  553         int     arg;
  554 
  555         if (cmd->flags & NG_L2CAP_CMD_PENDING)
  556                 panic(
  557 "%s: %s - duplicated command timeout, code=%#x, flags=%#x\n",
  558                         __func__, NG_NODE_NAME(cmd->con->l2cap->node),
  559                         cmd->code, cmd->flags);
  560 
  561         arg = ((cmd->ident << 16) | cmd->con->con_handle);
  562         cmd->flags |= NG_L2CAP_CMD_PENDING;
  563         ng_callout(&cmd->timo, cmd->con->l2cap->node, NULL, timo,
  564                                 ng_l2cap_process_command_timeout, NULL, arg);
  565 
  566         return (0);
  567 } /* ng_l2cap_command_timeout */
  568 
  569 /*
  570  * Unset L2CAP command timeout
  571  */
  572 
  573 int
  574 ng_l2cap_command_untimeout(ng_l2cap_cmd_p cmd)
  575 {
  576         if (!(cmd->flags & NG_L2CAP_CMD_PENDING))
  577                 panic(
  578 "%s: %s - no command timeout, code=%#x, flags=%#x\n",
  579                         __func__, NG_NODE_NAME(cmd->con->l2cap->node),
  580                         cmd->code, cmd->flags);
  581 
  582         if (ng_uncallout(&cmd->timo, cmd->con->l2cap->node) < 1)
  583                 return (ETIMEDOUT);
  584 
  585         cmd->flags &= ~NG_L2CAP_CMD_PENDING;
  586 
  587         return (0);
  588 } /* ng_l2cap_command_untimeout */
  589 
  590 /*
  591  * Prepend "m"buf with "size" bytes
  592  */
  593 
  594 struct mbuf *
  595 ng_l2cap_prepend(struct mbuf *m, int size)
  596 {
  597         M_PREPEND(m, size, M_NOWAIT);
  598         if (m == NULL || (m->m_len < size && (m = m_pullup(m, size)) == NULL))
  599                 return (NULL);
  600 
  601         return (m);
  602 } /* ng_l2cap_prepend */
  603 
  604 /*
  605  * Default flow settings
  606  */
  607 
  608 ng_l2cap_flow_p
  609 ng_l2cap_default_flow(void)
  610 {
  611         static ng_l2cap_flow_t  default_flow = {
  612                 /* flags */             0x0,
  613                 /* service_type */      NG_HCI_SERVICE_TYPE_BEST_EFFORT,
  614                 /* token_rate */        0xffffffff, /* maximum */
  615                 /* token_bucket_size */ 0xffffffff, /* maximum */
  616                 /* peak_bandwidth */    0x00000000, /* maximum */
  617                 /* latency */           0xffffffff, /* don't care */
  618                 /* delay_variation */   0xffffffff  /* don't care */
  619         };
  620 
  621         return (&default_flow);
  622 } /* ng_l2cap_default_flow */
  623 
  624 /*
  625  * Get next available channel ID
  626  * XXX FIXME this is *UGLY* but will do for now
  627  */
  628 
  629 static u_int16_t
  630 ng_l2cap_get_cid(ng_l2cap_p l2cap,int isle)
  631 {
  632         u_int16_t       cid ;
  633         u_int16_t       endcid;
  634         uint16_t         mask;
  635         int idtype;
  636         if(isle){
  637                 endcid = l2cap->lecid;
  638                 /*Assume Last CID is 2^n-1 */
  639                 mask = NG_L2CAP_LELAST_CID;
  640                 idtype = NG_L2CAP_L2CA_IDTYPE_LE;
  641         }else{
  642                 endcid = l2cap->cid;
  643                 /*Assume Last CID is 2^n-1 */           
  644                 mask = NG_L2CAP_LAST_CID;
  645                 idtype = NG_L2CAP_L2CA_IDTYPE_BREDR;
  646         }
  647         cid = (endcid+1) & mask;
  648              
  649         if (cid < NG_L2CAP_FIRST_CID)
  650                 cid = NG_L2CAP_FIRST_CID;
  651 
  652         while (cid != endcid) {
  653                 if (ng_l2cap_chan_by_scid(l2cap, cid, idtype) == NULL) {
  654                         if(!isle){
  655                                 l2cap->cid = cid;
  656                         }else{
  657                                 l2cap->lecid = cid;
  658                         }
  659                         return (cid);
  660                 }
  661 
  662                 cid ++;
  663                 cid &= mask;
  664                 if (cid < NG_L2CAP_FIRST_CID)
  665                         cid = NG_L2CAP_FIRST_CID;
  666         }
  667                 
  668         return (NG_L2CAP_NULL_CID);
  669 } /* ng_l2cap_get_cid */
  670 
  671 /*
  672  * Get next available command ident
  673  * XXX FIXME this is *UGLY* but will do for now
  674  */
  675 
  676 u_int8_t
  677 ng_l2cap_get_ident(ng_l2cap_con_p con)
  678 {
  679         u_int8_t        ident = con->ident + 1;
  680 
  681         if (ident < NG_L2CAP_FIRST_IDENT)
  682                 ident = NG_L2CAP_FIRST_IDENT;
  683 
  684         while (ident != con->ident) {
  685                 if (ng_l2cap_cmd_by_ident(con, ident) == NULL) {
  686                         con->ident = ident;
  687 
  688                         return (ident);
  689                 }
  690 
  691                 ident ++;
  692                 if (ident < NG_L2CAP_FIRST_IDENT)
  693                         ident = NG_L2CAP_FIRST_IDENT;
  694         }
  695 
  696         return (NG_L2CAP_NULL_IDENT);
  697 } /* ng_l2cap_get_ident */

Cache object: 0dd582ba2e46df88729f43110cefc477


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