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_cmds.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_cmds.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_cmds.c,v 1.2 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/endian.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/queue.h>
   43 #include <netgraph/ng_message.h>
   44 #include <netgraph/netgraph.h>
   45 #include <netgraph/bluetooth/include/ng_bluetooth.h>
   46 #include <netgraph/bluetooth/include/ng_hci.h>
   47 #include <netgraph/bluetooth/include/ng_l2cap.h>
   48 #include <netgraph/bluetooth/l2cap/ng_l2cap_var.h>
   49 #include <netgraph/bluetooth/l2cap/ng_l2cap_cmds.h>
   50 #include <netgraph/bluetooth/l2cap/ng_l2cap_evnt.h>
   51 #include <netgraph/bluetooth/l2cap/ng_l2cap_llpi.h>
   52 #include <netgraph/bluetooth/l2cap/ng_l2cap_ulpi.h>
   53 #include <netgraph/bluetooth/l2cap/ng_l2cap_misc.h>
   54 
   55 /******************************************************************************
   56  ******************************************************************************
   57  **                    L2CAP commands processing module
   58  ******************************************************************************
   59  ******************************************************************************/
   60 
   61 /*
   62  * Process L2CAP command queue on connection
   63  */
   64 
   65 void
   66 ng_l2cap_con_wakeup(ng_l2cap_con_p con)
   67 {
   68         ng_l2cap_cmd_p   cmd = NULL;
   69         struct mbuf     *m = NULL;
   70         int              error = 0;
   71 
   72         /* Find first non-pending command in the queue */
   73         TAILQ_FOREACH(cmd, &con->cmd_list, next) {
   74                 KASSERT((cmd->con == con),
   75 ("%s: %s - invalid connection pointer!\n",
   76                         __func__, NG_NODE_NAME(con->l2cap->node)));
   77 
   78                 if (!(cmd->flags & NG_L2CAP_CMD_PENDING))
   79                         break;
   80         }
   81 
   82         if (cmd == NULL)
   83                 return;
   84 
   85         /* Detach command packet */
   86         m = cmd->aux;
   87         cmd->aux = NULL;
   88 
   89         /* Process command */
   90         switch (cmd->code) {
   91         case NG_L2CAP_DISCON_RSP:
   92         case NG_L2CAP_ECHO_RSP:
   93         case NG_L2CAP_INFO_RSP:
   94                 /*
   95                  * Do not check return ng_l2cap_lp_send() value, because
   96                  * in these cases we do not really have a graceful way out.
   97                  * ECHO and INFO responses are internal to the stack and not
   98                  * visible to user. REJect is just being nice to remote end
   99                  * (otherwise remote end will timeout anyway). DISCON is
  100                  * probably most interesting here, however, if it fails
  101                  * there is nothing we can do anyway.
  102                  */
  103 
  104                 (void) ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  105                 ng_l2cap_unlink_cmd(cmd);
  106                 ng_l2cap_free_cmd(cmd);
  107                 break;
  108         case NG_L2CAP_CMD_REJ:
  109                 (void) ng_l2cap_lp_send(con,
  110                                         (con->linktype == NG_HCI_LINK_ACL)?
  111                                         NG_L2CAP_SIGNAL_CID:
  112                                         NG_L2CAP_LESIGNAL_CID
  113                                         , m);
  114                 ng_l2cap_unlink_cmd(cmd);
  115                 ng_l2cap_free_cmd(cmd);
  116                 break;
  117                 
  118         case NG_L2CAP_CON_REQ:
  119                 error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  120                 if (error != 0) {
  121                         ng_l2cap_l2ca_con_rsp(cmd->ch, cmd->token,
  122                                 NG_L2CAP_NO_RESOURCES, 0);
  123                         ng_l2cap_free_chan(cmd->ch); /* will free commands */
  124                 } else
  125                         ng_l2cap_command_timeout(cmd,
  126                                 bluetooth_l2cap_rtx_timeout());
  127                 break;
  128         case NG_L2CAP_CON_RSP:
  129                 error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  130                 ng_l2cap_unlink_cmd(cmd);
  131                 if (cmd->ch != NULL) {
  132                         ng_l2cap_l2ca_con_rsp_rsp(cmd->ch, cmd->token,
  133                                 (error == 0)? NG_L2CAP_SUCCESS : 
  134                                         NG_L2CAP_NO_RESOURCES);
  135                         if (error != 0)
  136                                 ng_l2cap_free_chan(cmd->ch);
  137                 }
  138                 ng_l2cap_free_cmd(cmd);
  139                 break;
  140 
  141         case NG_L2CAP_CFG_REQ:
  142                 error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  143                 if (error != 0) {
  144                         ng_l2cap_l2ca_cfg_rsp(cmd->ch, cmd->token,
  145                                 NG_L2CAP_NO_RESOURCES);
  146                         ng_l2cap_unlink_cmd(cmd);
  147                         ng_l2cap_free_cmd(cmd);
  148                 } else
  149                         ng_l2cap_command_timeout(cmd,
  150                                 bluetooth_l2cap_rtx_timeout());
  151                 break;
  152 
  153         case NG_L2CAP_CFG_RSP:
  154                 error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  155                 ng_l2cap_unlink_cmd(cmd);
  156                 if (cmd->ch != NULL)
  157                         ng_l2cap_l2ca_cfg_rsp_rsp(cmd->ch, cmd->token,
  158                                 (error == 0)? NG_L2CAP_SUCCESS :
  159                                         NG_L2CAP_NO_RESOURCES);
  160                 ng_l2cap_free_cmd(cmd);
  161                 break;
  162 
  163         case NG_L2CAP_DISCON_REQ:
  164                 error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  165                 ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token,
  166                         (error == 0)? NG_L2CAP_SUCCESS : NG_L2CAP_NO_RESOURCES);
  167                 if (error != 0)
  168                         ng_l2cap_free_chan(cmd->ch); /* XXX free channel */
  169                 else
  170                         ng_l2cap_command_timeout(cmd,
  171                                 bluetooth_l2cap_rtx_timeout());
  172                 break;
  173 
  174         case NG_L2CAP_ECHO_REQ:
  175                 error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  176                 if (error != 0) {
  177                         ng_l2cap_l2ca_ping_rsp(con, cmd->token,
  178                                         NG_L2CAP_NO_RESOURCES, NULL);
  179                         ng_l2cap_unlink_cmd(cmd);
  180                         ng_l2cap_free_cmd(cmd);
  181                 } else
  182                         ng_l2cap_command_timeout(cmd, 
  183                                 bluetooth_l2cap_rtx_timeout());
  184                 break;
  185 
  186         case NG_L2CAP_INFO_REQ:
  187                 error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
  188                 if (error != 0) {
  189                         ng_l2cap_l2ca_get_info_rsp(con, cmd->token, 
  190                                 NG_L2CAP_NO_RESOURCES, NULL);
  191                         ng_l2cap_unlink_cmd(cmd);
  192                         ng_l2cap_free_cmd(cmd);
  193                 } else
  194                         ng_l2cap_command_timeout(cmd, 
  195                                 bluetooth_l2cap_rtx_timeout());
  196                 break;
  197 
  198         case NGM_L2CAP_L2CA_WRITE: {
  199                 int     length = m->m_pkthdr.len;
  200 
  201                 if (cmd->ch->dcid == NG_L2CAP_CLT_CID) {
  202                         m = ng_l2cap_prepend(m, sizeof(ng_l2cap_clt_hdr_t));
  203                         if (m == NULL)
  204                                 error = ENOBUFS;
  205                         else
  206                                 mtod(m, ng_l2cap_clt_hdr_t *)->psm =
  207                                                         htole16(cmd->ch->psm);
  208                 }
  209 
  210                 if (error == 0)
  211                         error = ng_l2cap_lp_send(con, cmd->ch->dcid, m);
  212 
  213                 ng_l2cap_l2ca_write_rsp(cmd->ch, cmd->token,
  214                         (error == 0)? NG_L2CAP_SUCCESS : NG_L2CAP_NO_RESOURCES,
  215                         length);
  216 
  217                 ng_l2cap_unlink_cmd(cmd);
  218                 ng_l2cap_free_cmd(cmd);
  219                 } break;
  220         case NG_L2CAP_CMD_PARAM_UPDATE_RESPONSE:
  221                 error = ng_l2cap_lp_send(con, NG_L2CAP_LESIGNAL_CID, m);
  222                 ng_l2cap_unlink_cmd(cmd);
  223                 ng_l2cap_free_cmd(cmd);
  224                 break;
  225         case NG_L2CAP_CMD_PARAM_UPDATE_REQUEST:
  226                   /*TBD.*/
  227         /* XXX FIXME add other commands */
  228         default:
  229                 panic(
  230 "%s: %s - unknown command code=%d\n",
  231                         __func__, NG_NODE_NAME(con->l2cap->node), cmd->code);
  232                 break;
  233         }
  234 } /* ng_l2cap_con_wakeup */
  235 
  236 /*
  237  * We have failed to open ACL connection to the remote unit. Could be negative
  238  * confirmation or timeout. So fail any "delayed" commands, notify upper layer,
  239  * remove all channels and remove connection descriptor.
  240  */
  241 
  242 void
  243 ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result)
  244 {
  245         ng_l2cap_p      l2cap = con->l2cap;
  246         ng_l2cap_cmd_p  cmd = NULL;
  247         ng_l2cap_chan_p ch = NULL;
  248 
  249         NG_L2CAP_INFO(
  250 "%s: %s - ACL connection failed, result=%d\n",
  251                 __func__, NG_NODE_NAME(l2cap->node), result);
  252 
  253         /* Connection is dying */
  254         con->flags |= NG_L2CAP_CON_DYING;
  255 
  256         /* Clean command queue */
  257         while (!TAILQ_EMPTY(&con->cmd_list)) {
  258                 cmd = TAILQ_FIRST(&con->cmd_list);
  259 
  260                 ng_l2cap_unlink_cmd(cmd);
  261                 if(cmd->flags & NG_L2CAP_CMD_PENDING)
  262                         ng_l2cap_command_untimeout(cmd);
  263 
  264                 KASSERT((cmd->con == con),
  265 ("%s: %s - invalid connection pointer!\n",
  266                         __func__, NG_NODE_NAME(l2cap->node)));
  267 
  268                 switch (cmd->code) {
  269                 case NG_L2CAP_CMD_REJ:
  270                 case NG_L2CAP_DISCON_RSP:
  271                 case NG_L2CAP_ECHO_RSP:
  272                 case NG_L2CAP_INFO_RSP:
  273                 case NG_L2CAP_CMD_PARAM_UPDATE_RESPONSE:
  274                         break;
  275 
  276                 case NG_L2CAP_CON_REQ:
  277                         ng_l2cap_l2ca_con_rsp(cmd->ch, cmd->token, result, 0);
  278                         break;
  279 
  280                 case NG_L2CAP_CON_RSP:
  281                         if (cmd->ch != NULL)
  282                                 ng_l2cap_l2ca_con_rsp_rsp(cmd->ch, cmd->token,
  283                                         result);
  284                         break;
  285 
  286                 case NG_L2CAP_CFG_REQ:
  287                 case NG_L2CAP_CFG_RSP:
  288                 case NGM_L2CAP_L2CA_WRITE:
  289                         ng_l2cap_l2ca_discon_ind(cmd->ch);
  290                         break;
  291 
  292                 case NG_L2CAP_DISCON_REQ:
  293                         ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token,
  294                                 NG_L2CAP_SUCCESS);
  295                         break;
  296 
  297                 case NG_L2CAP_ECHO_REQ:
  298                         ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token,
  299                                 result, NULL);
  300                         break;
  301 
  302                 case NG_L2CAP_INFO_REQ:
  303                         ng_l2cap_l2ca_get_info_rsp(cmd->con, cmd->token,
  304                                 result, NULL);
  305                         break;
  306 
  307                 /* XXX FIXME add other commands */
  308 
  309                 default:
  310                         panic(
  311 "%s: %s - unexpected command code=%d\n",
  312                                 __func__, NG_NODE_NAME(l2cap->node), cmd->code);
  313                         break;
  314                 }
  315 
  316                 if (cmd->ch != NULL)
  317                         ng_l2cap_free_chan(cmd->ch);
  318 
  319                 ng_l2cap_free_cmd(cmd);
  320         }
  321 
  322         /*
  323          * There still might be channels (in OPEN state?) that
  324          * did not submit any commands, so disconnect them
  325          */
  326 
  327         LIST_FOREACH(ch, &l2cap->chan_list, next)
  328                 if (ch->con == con)
  329                         ng_l2cap_l2ca_discon_ind(ch);
  330 
  331         /* Free connection descriptor */
  332         ng_l2cap_free_con(con);
  333 } /* ng_l2cap_con_fail */
  334 
  335 /*
  336  * Process L2CAP command timeout. In general - notify upper layer and destroy
  337  * channel. Do not pay much attention to return code, just do our best.
  338  */
  339 
  340 void
  341 ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
  342 {
  343         ng_l2cap_p      l2cap = NULL;
  344         ng_l2cap_con_p  con = NULL;
  345         ng_l2cap_cmd_p  cmd = NULL;
  346         u_int16_t       con_handle = (arg2 & 0x0ffff);
  347         u_int8_t        ident = ((arg2 >> 16) & 0xff);
  348 
  349         if (NG_NODE_NOT_VALID(node)) {
  350                 printf("%s: Netgraph node is not valid\n", __func__);
  351                 return;
  352         }
  353 
  354         l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node);
  355 
  356         con = ng_l2cap_con_by_handle(l2cap, con_handle);
  357         if (con == NULL) {
  358                 NG_L2CAP_ALERT(
  359 "%s: %s - could not find connection, con_handle=%d\n",
  360                         __func__, NG_NODE_NAME(node), con_handle);
  361                 return;
  362         }
  363 
  364         cmd = ng_l2cap_cmd_by_ident(con, ident);
  365         if (cmd == NULL) {
  366                 NG_L2CAP_ALERT(
  367 "%s: %s - could not find command, con_handle=%d, ident=%d\n",
  368                         __func__, NG_NODE_NAME(node), con_handle, ident);
  369                 return;
  370         }
  371 
  372         cmd->flags &= ~NG_L2CAP_CMD_PENDING;
  373         ng_l2cap_unlink_cmd(cmd);
  374 
  375         switch (cmd->code) {
  376         case NG_L2CAP_CON_REQ:
  377                 ng_l2cap_l2ca_con_rsp(cmd->ch, cmd->token, NG_L2CAP_TIMEOUT, 0);
  378                 ng_l2cap_free_chan(cmd->ch); 
  379                 break;
  380 
  381         case NG_L2CAP_CFG_REQ:
  382                 ng_l2cap_l2ca_cfg_rsp(cmd->ch, cmd->token, NG_L2CAP_TIMEOUT);
  383                 break;
  384 
  385         case NG_L2CAP_DISCON_REQ:
  386                 ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token, NG_L2CAP_TIMEOUT);
  387                 ng_l2cap_free_chan(cmd->ch); /* XXX free channel */
  388                 break;
  389 
  390         case NG_L2CAP_ECHO_REQ:
  391                 /* Echo request timed out. Let the upper layer know */
  392                 ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token,
  393                         NG_L2CAP_TIMEOUT, NULL);
  394                 break;
  395 
  396         case NG_L2CAP_INFO_REQ:
  397                 /* Info request timed out. Let the upper layer know */
  398                 ng_l2cap_l2ca_get_info_rsp(cmd->con, cmd->token,
  399                         NG_L2CAP_TIMEOUT, NULL);
  400                 break;
  401 
  402         /* XXX FIXME add other commands */
  403 
  404         default:
  405                 panic(
  406 "%s: %s - unexpected command code=%d\n",
  407                         __func__, NG_NODE_NAME(l2cap->node), cmd->code);
  408                 break;
  409         }
  410 
  411         ng_l2cap_free_cmd(cmd);
  412 } /* ng_l2cap_process_command_timeout */

Cache object: 949352488b2f504c4c0bb1ca867a1b5d


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