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/hci/ng_hci_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_hci_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_hci_cmds.c,v 1.4 2003/09/08 18:57:51 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/hci/ng_hci_var.h>
   48 #include <netgraph/bluetooth/hci/ng_hci_cmds.h>
   49 #include <netgraph/bluetooth/hci/ng_hci_evnt.h>
   50 #include <netgraph/bluetooth/hci/ng_hci_ulpi.h>
   51 #include <netgraph/bluetooth/hci/ng_hci_misc.h>
   52 
   53 /******************************************************************************
   54  ******************************************************************************
   55  **                     HCI commands processing module
   56  ******************************************************************************
   57  ******************************************************************************/
   58 
   59 #undef  min
   60 #define min(a, b)       ((a) < (b))? (a) : (b)
   61 
   62 static int  complete_command (ng_hci_unit_p, int, struct mbuf **);
   63 
   64 static int process_link_control_params
   65         (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
   66 static int process_link_policy_params
   67         (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
   68 static int process_hc_baseband_params
   69         (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
   70 static int process_info_params
   71         (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
   72 static int process_status_params
   73         (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
   74 static int process_testing_params
   75         (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
   76 static int process_le_params
   77         (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
   78 
   79 static int process_link_control_status
   80         (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
   81 static int process_link_policy_status
   82         (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
   83 static int process_le_status
   84         (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
   85 
   86 /*
   87  * Send HCI command to the driver.
   88  */
   89 
   90 int
   91 ng_hci_send_command(ng_hci_unit_p unit)
   92 {
   93         struct mbuf     *m0 = NULL, *m = NULL;
   94         int              free, error = 0;
   95 
   96         /* Check if other command is pending */
   97         if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
   98                 return (0);
   99 
  100         /* Check if unit can accept our command */
  101         NG_HCI_BUFF_CMD_GET(unit->buffer, free);
  102         if (free == 0)
  103                 return (0);
  104 
  105         /* Check if driver hook is still ok */
  106         if (unit->drv == NULL || NG_HOOK_NOT_VALID(unit->drv)) {
  107                 NG_HCI_WARN(
  108 "%s: %s - hook \"%s\" is not connected or valid\n",
  109                         __func__, NG_NODE_NAME(unit->node), NG_HCI_HOOK_DRV);
  110 
  111                 NG_BT_MBUFQ_DRAIN(&unit->cmdq);
  112 
  113                 return (ENOTCONN);
  114         }
  115 
  116         /* 
  117          * Get first command from queue, give it to RAW hook then 
  118          * make copy of it and send it to the driver
  119          */
  120 
  121         m0 = NG_BT_MBUFQ_FIRST(&unit->cmdq);
  122         if (m0 == NULL)
  123                 return (0);
  124 
  125         ng_hci_mtap(unit, m0);
  126 
  127         m = m_dup(m0, M_NOWAIT);
  128         if (m != NULL)
  129                 NG_SEND_DATA_ONLY(error, unit->drv, m);
  130         else
  131                 error = ENOBUFS;
  132 
  133         if (error != 0)
  134                 NG_HCI_ERR(
  135 "%s: %s - could not send HCI command, error=%d\n",
  136                         __func__, NG_NODE_NAME(unit->node), error);
  137 
  138         /*
  139          * Even if we were not able to send command we still pretend
  140          * that everything is OK and let timeout handle that.
  141          */
  142 
  143         NG_HCI_BUFF_CMD_USE(unit->buffer, 1);
  144         NG_HCI_STAT_CMD_SENT(unit->stat);
  145         NG_HCI_STAT_BYTES_SENT(unit->stat, m0->m_pkthdr.len);
  146 
  147         /*
  148          * Note: ng_hci_command_timeout() will set 
  149          * NG_HCI_UNIT_COMMAND_PENDING flag
  150          */
  151 
  152         ng_hci_command_timeout(unit);
  153 
  154         return (0);
  155 } /* ng_hci_send_command */
  156 
  157 /*
  158  * Process HCI Command_Compete event. Complete HCI command, and do post 
  159  * processing on the command parameters (cp) and command return parameters
  160  * (e) if required (for example adjust state).
  161  */
  162 
  163 int
  164 ng_hci_process_command_complete(ng_hci_unit_p unit, struct mbuf *e)
  165 {
  166         ng_hci_command_compl_ep         *ep = NULL;
  167         struct mbuf                     *cp = NULL;
  168         int                              error = 0;
  169 
  170         /* Get event packet and update command buffer info */
  171         NG_HCI_M_PULLUP(e, sizeof(*ep));
  172         if (e == NULL)
  173                 return (ENOBUFS); /* XXX this is bad */
  174 
  175         ep = mtod(e, ng_hci_command_compl_ep *);
  176         NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts);
  177 
  178         /* Check for special NOOP command */
  179         if (ep->opcode == 0x0000) {
  180                 NG_FREE_M(e);
  181                 goto out;
  182         }
  183 
  184         /* Try to match first command item in the queue */
  185         error = complete_command(unit, ep->opcode, &cp);
  186         if (error != 0) {
  187                 NG_FREE_M(e);
  188                 goto out;
  189         }
  190 
  191         /* 
  192          * Perform post processing on command parameters and return parameters
  193          * do it only if status is OK (status == 0). Status is the first byte
  194          * of any command return parameters.
  195          */
  196 
  197         ep->opcode = le16toh(ep->opcode);
  198         m_adj(e, sizeof(*ep));
  199 
  200         if (*mtod(e, u_int8_t *) == 0) { /* XXX m_pullup here? */
  201                 switch (NG_HCI_OGF(ep->opcode)) {
  202                 case NG_HCI_OGF_LINK_CONTROL:
  203                         error = process_link_control_params(unit,
  204                                         NG_HCI_OCF(ep->opcode), cp, e);
  205                         break;
  206 
  207                 case NG_HCI_OGF_LINK_POLICY:
  208                         error = process_link_policy_params(unit,
  209                                         NG_HCI_OCF(ep->opcode), cp, e);
  210                         break;
  211 
  212                 case NG_HCI_OGF_HC_BASEBAND:
  213                         error = process_hc_baseband_params(unit,
  214                                         NG_HCI_OCF(ep->opcode), cp, e);
  215                         break;
  216 
  217                 case NG_HCI_OGF_INFO:
  218                         error = process_info_params(unit,
  219                                         NG_HCI_OCF(ep->opcode), cp, e);
  220                         break;
  221 
  222                 case NG_HCI_OGF_STATUS:
  223                         error = process_status_params(unit,
  224                                         NG_HCI_OCF(ep->opcode), cp, e);
  225                         break;
  226 
  227                 case NG_HCI_OGF_TESTING:
  228                         error = process_testing_params(unit,
  229                                         NG_HCI_OCF(ep->opcode), cp, e);
  230                         break;
  231                 case NG_HCI_OGF_LE:
  232                         error = process_le_params(unit,
  233                                           NG_HCI_OCF(ep->opcode), cp, e);
  234                         break;
  235                 case NG_HCI_OGF_BT_LOGO:
  236                 case NG_HCI_OGF_VENDOR:
  237                         NG_FREE_M(cp);
  238                         NG_FREE_M(e);
  239                         break;
  240 
  241                 default:
  242                         NG_FREE_M(cp);
  243                         NG_FREE_M(e);
  244                         error = EINVAL;
  245                         break;
  246                 }
  247         } else {
  248                 NG_HCI_ERR(
  249 "%s: %s - HCI command failed, OGF=%#x, OCF=%#x, status=%#x\n",
  250                         __func__, NG_NODE_NAME(unit->node),
  251                         NG_HCI_OGF(ep->opcode), NG_HCI_OCF(ep->opcode), 
  252                         *mtod(e, u_int8_t *));
  253 
  254                 NG_FREE_M(cp);
  255                 NG_FREE_M(e);
  256         }
  257 out:
  258         ng_hci_send_command(unit);
  259 
  260         return (error);
  261 } /* ng_hci_process_command_complete */
  262 
  263 /*
  264  * Process HCI Command_Status event. Check the status (mst) and do post 
  265  * processing (if required).
  266  */
  267 
  268 int
  269 ng_hci_process_command_status(ng_hci_unit_p unit, struct mbuf *e)
  270 {
  271         ng_hci_command_status_ep        *ep = NULL;
  272         struct mbuf                     *cp = NULL;
  273         int                              error = 0;
  274 
  275         /* Update command buffer info */
  276         NG_HCI_M_PULLUP(e, sizeof(*ep));
  277         if (e == NULL)
  278                 return (ENOBUFS); /* XXX this is bad */
  279 
  280         ep = mtod(e, ng_hci_command_status_ep *);
  281         NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts);
  282 
  283         /* Check for special NOOP command */
  284         if (ep->opcode == 0x0000)
  285                 goto out;
  286 
  287         /* Try to match first command item in the queue */
  288         error = complete_command(unit, ep->opcode, &cp);
  289         if (error != 0)
  290                 goto out;
  291 
  292         /* 
  293          * Perform post processing on HCI Command_Status event
  294          */
  295 
  296         ep->opcode = le16toh(ep->opcode);
  297 
  298         switch (NG_HCI_OGF(ep->opcode)) {
  299         case NG_HCI_OGF_LINK_CONTROL:
  300                 error = process_link_control_status(unit, ep, cp);
  301                 break;
  302 
  303         case NG_HCI_OGF_LINK_POLICY:
  304                 error = process_link_policy_status(unit, ep, cp);
  305                 break;
  306         case NG_HCI_OGF_LE:
  307                 error = process_le_status(unit, ep, cp);
  308                 break;
  309         case NG_HCI_OGF_BT_LOGO:
  310         case NG_HCI_OGF_VENDOR:
  311                 NG_FREE_M(cp);
  312                 break;
  313 
  314         case NG_HCI_OGF_HC_BASEBAND:
  315         case NG_HCI_OGF_INFO:
  316         case NG_HCI_OGF_STATUS:
  317         case NG_HCI_OGF_TESTING:
  318         default:
  319                 NG_FREE_M(cp);
  320                 error = EINVAL;
  321                 break;
  322         }
  323 out:
  324         NG_FREE_M(e);
  325         ng_hci_send_command(unit);
  326 
  327         return (error);
  328 } /* ng_hci_process_command_status */
  329 
  330 /*
  331  * Complete queued HCI command. 
  332  */
  333 
  334 static int
  335 complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp)
  336 {
  337         struct mbuf     *m = NULL;
  338 
  339         /* Check unit state */
  340         if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) {
  341                 NG_HCI_ALERT(
  342 "%s: %s - no pending command, state=%#x\n",
  343                         __func__, NG_NODE_NAME(unit->node), unit->state);
  344 
  345                 return (EINVAL);
  346         }
  347 
  348         /* Get first command in the queue */
  349         m = NG_BT_MBUFQ_FIRST(&unit->cmdq);
  350         if (m == NULL) {
  351                 NG_HCI_ALERT(
  352 "%s: %s - empty command queue?!\n", __func__, NG_NODE_NAME(unit->node));
  353 
  354                 return (EINVAL);
  355         }
  356 
  357         /*
  358          * Match command opcode, if does not match - do nothing and 
  359          * let timeout handle that.
  360          */
  361 
  362         if (mtod(m, ng_hci_cmd_pkt_t *)->opcode != opcode) {
  363                 NG_HCI_ALERT(
  364 "%s: %s - command queue is out of sync\n", __func__, NG_NODE_NAME(unit->node));
  365 
  366                 return (EINVAL);
  367         }
  368 
  369         /* 
  370          * Now we can remove command timeout, dequeue completed command
  371          * and return command parameters. ng_hci_command_untimeout will
  372          * drop NG_HCI_UNIT_COMMAND_PENDING flag.
  373          * Note: if ng_hci_command_untimeout() fails (returns non-zero)
  374          * then timeout already happened and timeout message went info node
  375          * queue. In this case we ignore command completion and pretend
  376          * there is a timeout.
  377          */
  378 
  379         if (ng_hci_command_untimeout(unit) != 0)
  380                 return (ETIMEDOUT);
  381 
  382         NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, *cp);
  383         m_adj(*cp, sizeof(ng_hci_cmd_pkt_t));
  384 
  385         return (0);
  386 } /* complete_command */
  387 
  388 /*
  389  * Process HCI command timeout
  390  */
  391 
  392 void
  393 ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
  394 {
  395         ng_hci_unit_p    unit = NULL;
  396         struct mbuf     *m = NULL;
  397         u_int16_t        opcode;
  398 
  399         if (NG_NODE_NOT_VALID(node)) {
  400                 printf("%s: Netgraph node is not valid\n", __func__);
  401                 return;
  402         }
  403 
  404         unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
  405 
  406         if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
  407                 unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
  408 
  409                 NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m);
  410                 if (m == NULL) {
  411                         NG_HCI_ALERT(
  412 "%s: %s - command queue is out of sync!\n", __func__, NG_NODE_NAME(unit->node));
  413 
  414                         return;
  415                 }
  416 
  417                 opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode);
  418                 NG_FREE_M(m);
  419 
  420                 NG_HCI_ERR(
  421 "%s: %s - unable to complete HCI command OGF=%#x, OCF=%#x. Timeout\n",
  422                         __func__, NG_NODE_NAME(unit->node), NG_HCI_OGF(opcode),
  423                         NG_HCI_OCF(opcode));
  424 
  425                 /* Try to send more commands */
  426                 NG_HCI_BUFF_CMD_SET(unit->buffer, 1);
  427                 ng_hci_send_command(unit);
  428         } else
  429                 NG_HCI_ALERT(
  430 "%s: %s - no pending command\n", __func__, NG_NODE_NAME(unit->node));
  431 } /* ng_hci_process_command_timeout */
  432 
  433 /* 
  434  * Process link command return parameters
  435  */
  436 
  437 static int
  438 process_link_control_params(ng_hci_unit_p unit, u_int16_t ocf, 
  439                 struct mbuf *mcp, struct mbuf *mrp)
  440 {
  441         int     error  = 0;
  442 
  443         switch (ocf) {
  444         case NG_HCI_OCF_INQUIRY_CANCEL:
  445         case NG_HCI_OCF_PERIODIC_INQUIRY:
  446         case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY:
  447         case NG_HCI_OCF_LINK_KEY_REP:
  448         case NG_HCI_OCF_LINK_KEY_NEG_REP: 
  449         case NG_HCI_OCF_PIN_CODE_REP:
  450         case NG_HCI_OCF_PIN_CODE_NEG_REP:
  451                 /* These do not need post processing */
  452                 break;
  453 
  454         case NG_HCI_OCF_INQUIRY:
  455         case NG_HCI_OCF_CREATE_CON:
  456         case NG_HCI_OCF_DISCON:
  457         case NG_HCI_OCF_ADD_SCO_CON:
  458         case NG_HCI_OCF_ACCEPT_CON:
  459         case NG_HCI_OCF_REJECT_CON:
  460         case NG_HCI_OCF_CHANGE_CON_PKT_TYPE:
  461         case NG_HCI_OCF_AUTH_REQ:
  462         case NG_HCI_OCF_SET_CON_ENCRYPTION:
  463         case NG_HCI_OCF_CHANGE_CON_LINK_KEY:
  464         case NG_HCI_OCF_MASTER_LINK_KEY:
  465         case NG_HCI_OCF_REMOTE_NAME_REQ:
  466         case NG_HCI_OCF_READ_REMOTE_FEATURES:
  467         case NG_HCI_OCF_READ_REMOTE_VER_INFO:
  468         case NG_HCI_OCF_READ_CLOCK_OFFSET:
  469         default:
  470 
  471                 /*
  472                  * None of these command was supposed to generate 
  473                  * Command_Complete event. Instead Command_Status event 
  474                  * should have been generated and then appropriate event 
  475                  * should have been sent to indicate the final result.
  476                  */
  477 
  478                 error = EINVAL;
  479                 break;
  480         }
  481 
  482         NG_FREE_M(mcp);
  483         NG_FREE_M(mrp);
  484 
  485         return (error);
  486 } /* process_link_control_params */
  487 
  488 /* 
  489  * Process link policy command return parameters
  490  */
  491 
  492 static int
  493 process_link_policy_params(ng_hci_unit_p unit, u_int16_t ocf,
  494                 struct mbuf *mcp, struct mbuf *mrp)
  495 {
  496         int     error = 0;
  497 
  498         switch (ocf){
  499         case NG_HCI_OCF_ROLE_DISCOVERY: {
  500                 ng_hci_role_discovery_rp        *rp = NULL;
  501                 ng_hci_unit_con_t               *con = NULL;
  502                 u_int16_t                        h;
  503 
  504                 NG_HCI_M_PULLUP(mrp, sizeof(*rp));
  505                 if (mrp != NULL) {
  506                         rp = mtod(mrp, ng_hci_role_discovery_rp *);
  507 
  508                         h = NG_HCI_CON_HANDLE(le16toh(rp->con_handle));
  509                         con = ng_hci_con_by_handle(unit, h);
  510                         if (con == NULL) {
  511                                 NG_HCI_ALERT(
  512 "%s: %s - invalid connection handle=%d\n",
  513                                         __func__, NG_NODE_NAME(unit->node), h); 
  514                                 error = ENOENT;
  515                         } else if (con->link_type != NG_HCI_LINK_ACL) {
  516                                 NG_HCI_ALERT(
  517 "%s: %s - invalid link type=%d\n", __func__, NG_NODE_NAME(unit->node),
  518                                         con->link_type);
  519                                 error = EINVAL;
  520                         } else
  521                                 con->role = rp->role;
  522                 } else
  523                         error = ENOBUFS;
  524                 } break;
  525 
  526         case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS:
  527         case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS:
  528                 /* These do not need post processing */
  529                 break;
  530 
  531         case NG_HCI_OCF_HOLD_MODE:
  532         case NG_HCI_OCF_SNIFF_MODE:
  533         case NG_HCI_OCF_EXIT_SNIFF_MODE:
  534         case NG_HCI_OCF_PARK_MODE:
  535         case NG_HCI_OCF_EXIT_PARK_MODE:
  536         case NG_HCI_OCF_QOS_SETUP:
  537         case NG_HCI_OCF_SWITCH_ROLE:
  538         default:
  539 
  540                 /*
  541                  * None of these command was supposed to generate 
  542                  * Command_Complete event. Instead Command_Status event 
  543                  * should have been generated and then appropriate event
  544                  * should have been sent to indicate the final result.
  545                  */
  546 
  547                 error = EINVAL;
  548                 break;
  549         } 
  550 
  551         NG_FREE_M(mcp);
  552         NG_FREE_M(mrp);
  553 
  554         return (error);
  555 } /* process_link_policy_params */
  556 
  557 /* 
  558  * Process HC and baseband command return parameters
  559  */
  560 
  561 int
  562 process_hc_baseband_params(ng_hci_unit_p unit, u_int16_t ocf, 
  563                 struct mbuf *mcp, struct mbuf *mrp)
  564 {
  565         int     error = 0;
  566 
  567         switch (ocf) {
  568         case NG_HCI_OCF_SET_EVENT_MASK:
  569         case NG_HCI_OCF_SET_EVENT_FILTER:
  570         case NG_HCI_OCF_FLUSH:  /* XXX Do we need to handle that? */
  571         case NG_HCI_OCF_READ_PIN_TYPE:
  572         case NG_HCI_OCF_WRITE_PIN_TYPE:
  573         case NG_HCI_OCF_CREATE_NEW_UNIT_KEY:
  574         case NG_HCI_OCF_WRITE_STORED_LINK_KEY:
  575         case NG_HCI_OCF_WRITE_CON_ACCEPT_TIMO:
  576         case NG_HCI_OCF_WRITE_PAGE_TIMO:
  577         case NG_HCI_OCF_READ_SCAN_ENABLE:
  578         case NG_HCI_OCF_WRITE_SCAN_ENABLE:
  579         case NG_HCI_OCF_WRITE_PAGE_SCAN_ACTIVITY:
  580         case NG_HCI_OCF_WRITE_INQUIRY_SCAN_ACTIVITY:
  581         case NG_HCI_OCF_READ_AUTH_ENABLE:
  582         case NG_HCI_OCF_WRITE_AUTH_ENABLE:
  583         case NG_HCI_OCF_READ_ENCRYPTION_MODE:
  584         case NG_HCI_OCF_WRITE_ENCRYPTION_MODE:
  585         case NG_HCI_OCF_WRITE_VOICE_SETTINGS:
  586         case NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS:
  587         case NG_HCI_OCF_WRITE_NUM_BROADCAST_RETRANS:
  588         case NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY:
  589         case NG_HCI_OCF_WRITE_HOLD_MODE_ACTIVITY:
  590         case NG_HCI_OCF_READ_SCO_FLOW_CONTROL:
  591         case NG_HCI_OCF_WRITE_SCO_FLOW_CONTROL:
  592         case NG_HCI_OCF_H2HC_FLOW_CONTROL: /* XXX Not supported this time */
  593         case NG_HCI_OCF_HOST_BUFFER_SIZE:
  594         case NG_HCI_OCF_READ_IAC_LAP:
  595         case NG_HCI_OCF_WRITE_IAC_LAP:
  596         case NG_HCI_OCF_READ_PAGE_SCAN_PERIOD:
  597         case NG_HCI_OCF_WRITE_PAGE_SCAN_PERIOD:
  598         case NG_HCI_OCF_READ_PAGE_SCAN:
  599         case NG_HCI_OCF_WRITE_PAGE_SCAN:
  600         case NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO:
  601         case NG_HCI_OCF_WRITE_LINK_SUPERVISION_TIMO:
  602         case NG_HCI_OCF_READ_SUPPORTED_IAC_NUM:
  603         case NG_HCI_OCF_READ_STORED_LINK_KEY:
  604         case NG_HCI_OCF_DELETE_STORED_LINK_KEY:
  605         case NG_HCI_OCF_READ_CON_ACCEPT_TIMO:
  606         case NG_HCI_OCF_READ_PAGE_TIMO:
  607         case NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY:
  608         case NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY:
  609         case NG_HCI_OCF_READ_VOICE_SETTINGS:
  610         case NG_HCI_OCF_READ_AUTO_FLUSH_TIMO:
  611         case NG_HCI_OCF_WRITE_AUTO_FLUSH_TIMO:
  612         case NG_HCI_OCF_READ_XMIT_LEVEL:
  613         case NG_HCI_OCF_HOST_NUM_COMPL_PKTS:    /* XXX Can get here? */
  614         case NG_HCI_OCF_CHANGE_LOCAL_NAME:
  615         case NG_HCI_OCF_READ_LOCAL_NAME:
  616         case NG_HCI_OCF_READ_UNIT_CLASS:
  617         case NG_HCI_OCF_WRITE_UNIT_CLASS:
  618         case NG_HCI_OCF_READ_LE_HOST_SUPPORTED:
  619         case NG_HCI_OCF_WRITE_LE_HOST_SUPPORTED:
  620                 /* These do not need post processing */
  621                 break;
  622 
  623         case NG_HCI_OCF_RESET: {
  624                 ng_hci_unit_con_p       con = NULL;
  625                 int                     size;
  626 
  627                 /*
  628                  * XXX 
  629                  *
  630                  * After RESET command unit goes into standby mode
  631                  * and all operational state is lost. Host controller
  632                  * will revert to default values for all parameters.
  633                  * 
  634                  * For now we shall terminate all connections and drop
  635                  * inited bit. After RESET unit must be re-initialized.
  636                  */
  637 
  638                 while (!LIST_EMPTY(&unit->con_list)) {
  639                         con = LIST_FIRST(&unit->con_list);
  640 
  641                         /* Remove all timeouts (if any) */
  642                         if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
  643                                 ng_hci_con_untimeout(con);
  644 
  645                         /* Connection terminated by local host */
  646                         ng_hci_lp_discon_ind(con, 0x16);
  647                         ng_hci_free_con(con);
  648                 }
  649 
  650                 NG_HCI_BUFF_ACL_TOTAL(unit->buffer, size);
  651                 NG_HCI_BUFF_ACL_FREE(unit->buffer, size);
  652 
  653                 NG_HCI_BUFF_SCO_TOTAL(unit->buffer, size);
  654                 NG_HCI_BUFF_SCO_FREE(unit->buffer, size);
  655 
  656                 unit->state &= ~NG_HCI_UNIT_INITED;
  657                 } break;
  658 
  659         default:
  660                 error = EINVAL;
  661                 break;
  662         }
  663 
  664         NG_FREE_M(mcp);
  665         NG_FREE_M(mrp);
  666 
  667         return (error);
  668 } /* process_hc_baseband_params */
  669 
  670 /* 
  671  * Process info command return parameters
  672  */
  673 
  674 static int
  675 process_info_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
  676                 struct mbuf *mrp)
  677 {
  678         int     error = 0, len;
  679 
  680         switch (ocf) {
  681         case NG_HCI_OCF_READ_LOCAL_VER:
  682         case NG_HCI_OCF_READ_COUNTRY_CODE:
  683                 break;
  684 
  685         case NG_HCI_OCF_READ_LOCAL_FEATURES:
  686                 m_adj(mrp, sizeof(u_int8_t));
  687                 len = min(mrp->m_pkthdr.len, sizeof(unit->features));
  688                 m_copydata(mrp, 0, len, (caddr_t) unit->features);
  689                 break;
  690 
  691         case NG_HCI_OCF_READ_BUFFER_SIZE: {
  692                 ng_hci_read_buffer_size_rp      *rp = NULL;
  693 
  694                 /* Do not update buffer descriptor if node was initialized */
  695                 if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY)
  696                         break;
  697 
  698                 NG_HCI_M_PULLUP(mrp, sizeof(*rp));
  699                 if (mrp != NULL) {
  700                         rp = mtod(mrp, ng_hci_read_buffer_size_rp *);
  701 
  702                         NG_HCI_BUFF_ACL_SET(
  703                                 unit->buffer,
  704                                 le16toh(rp->num_acl_pkt),  /* number */
  705                                 le16toh(rp->max_acl_size), /* size */
  706                                 le16toh(rp->num_acl_pkt)   /* free */
  707                         );
  708 
  709                         NG_HCI_BUFF_SCO_SET(
  710                                 unit->buffer,
  711                                 le16toh(rp->num_sco_pkt), /* number */
  712                                 rp->max_sco_size,         /* size */
  713                                 le16toh(rp->num_sco_pkt)  /* free */
  714                         );
  715 
  716                         /* Let upper layers know */
  717                         ng_hci_node_is_up(unit->node, unit->acl, NULL, 0);
  718                         ng_hci_node_is_up(unit->node, unit->sco, NULL, 0);
  719                 } else
  720                         error = ENOBUFS;
  721                 } break;
  722 
  723         case NG_HCI_OCF_READ_BDADDR:
  724                 /* Do not update BD_ADDR if node was initialized */
  725                 if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY)
  726                         break;
  727 
  728                 m_adj(mrp, sizeof(u_int8_t));
  729                 len = min(mrp->m_pkthdr.len, sizeof(unit->bdaddr));
  730                 m_copydata(mrp, 0, len, (caddr_t) &unit->bdaddr);
  731 
  732                 /* Let upper layers know */
  733                 ng_hci_node_is_up(unit->node, unit->acl, NULL, 0);
  734                 ng_hci_node_is_up(unit->node, unit->sco, NULL, 0);
  735                 break;
  736 
  737         default:
  738                 error = EINVAL;
  739                 break;
  740         }
  741 
  742         NG_FREE_M(mcp);
  743         NG_FREE_M(mrp);
  744 
  745         return (error);
  746 } /* process_info_params */
  747 
  748 /* 
  749  * Process status command return parameters
  750  */
  751 
  752 static int
  753 process_status_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
  754                 struct mbuf *mrp)
  755 {
  756         int     error = 0;
  757 
  758         switch (ocf) {
  759         case NG_HCI_OCF_READ_FAILED_CONTACT_CNTR:
  760         case NG_HCI_OCF_RESET_FAILED_CONTACT_CNTR:
  761         case NG_HCI_OCF_GET_LINK_QUALITY:
  762         case NG_HCI_OCF_READ_RSSI:
  763                 /* These do not need post processing */
  764                 break;
  765 
  766         default:
  767                 error = EINVAL;
  768                 break;
  769         }
  770 
  771         NG_FREE_M(mcp);
  772         NG_FREE_M(mrp);
  773 
  774         return (error);
  775 } /* process_status_params */
  776 
  777 /* 
  778  * Process testing command return parameters
  779  */
  780 
  781 int
  782 process_testing_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
  783                 struct mbuf *mrp)
  784 {
  785         int     error = 0;
  786 
  787         switch (ocf) {
  788         /*
  789          * XXX FIXME
  790          * We do not support these features at this time. However,
  791          * HCI node could support this and do something smart. At least
  792          * node can change unit state.
  793          */
  794 
  795         case NG_HCI_OCF_READ_LOOPBACK_MODE:
  796         case NG_HCI_OCF_WRITE_LOOPBACK_MODE:
  797         case NG_HCI_OCF_ENABLE_UNIT_UNDER_TEST:
  798                 break;
  799 
  800         default:
  801                 error = EINVAL;
  802                 break;
  803         }
  804 
  805         NG_FREE_M(mcp);
  806         NG_FREE_M(mrp);
  807 
  808         return (error);
  809 } /* process_testing_params */
  810 
  811 /* 
  812  * Process LE command return parameters
  813  */
  814 
  815 static int
  816 process_le_params(ng_hci_unit_p unit, u_int16_t ocf,
  817                 struct mbuf *mcp, struct mbuf *mrp)
  818 {
  819         int     error = 0;
  820 
  821         switch (ocf){
  822         case NG_HCI_OCF_LE_SET_EVENT_MASK:
  823         case NG_HCI_OCF_LE_READ_BUFFER_SIZE:
  824         case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES:
  825         case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS:
  826         case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS:
  827         case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER:
  828         case NG_HCI_OCF_LE_SET_ADVERTISING_DATA:
  829         case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA:
  830         case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE:
  831         case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS:
  832         case NG_HCI_OCF_LE_SET_SCAN_ENABLE:
  833         case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL:
  834         case NG_HCI_OCF_LE_CLEAR_WHITE_LIST:
  835         case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE:
  836         case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST:
  837         case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST:
  838         case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION:
  839         case NG_HCI_OCF_LE_READ_CHANNEL_MAP:
  840         case NG_HCI_OCF_LE_ENCRYPT:
  841         case NG_HCI_OCF_LE_RAND:
  842         case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY:
  843         case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY:
  844         case NG_HCI_OCF_LE_READ_SUPPORTED_STATES:
  845         case NG_HCI_OCF_LE_RECEIVER_TEST:
  846         case NG_HCI_OCF_LE_TRANSMITTER_TEST:
  847         case NG_HCI_OCF_LE_TEST_END:
  848 
  849                 /* These do not need post processing */
  850                 break;
  851         case NG_HCI_OCF_LE_CREATE_CONNECTION:
  852         case NG_HCI_OCF_LE_CONNECTION_UPDATE:
  853         case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES:
  854         case NG_HCI_OCF_LE_START_ENCRYPTION:
  855 
  856         default:
  857                 /*
  858                  * None of these command was supposed to generate 
  859                  * Command_Complete event. Instead Command_Status event 
  860                  * should have been generated and then appropriate event
  861                  * should have been sent to indicate the final result.
  862                  */
  863 
  864                 error = EINVAL;
  865                 break;
  866         } 
  867 
  868         NG_FREE_M(mcp);
  869         NG_FREE_M(mrp);
  870 
  871         return (error);
  872 
  873 }
  874 
  875 static int
  876 process_le_status(ng_hci_unit_p unit,ng_hci_command_status_ep *ep,
  877                 struct mbuf *mcp)
  878 {
  879         int     error = 0;
  880 
  881         switch (NG_HCI_OCF(ep->opcode)){
  882         case NG_HCI_OCF_LE_CREATE_CONNECTION:
  883         case NG_HCI_OCF_LE_CONNECTION_UPDATE:
  884         case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES:
  885         case NG_HCI_OCF_LE_START_ENCRYPTION:
  886 
  887                 /* These do not need post processing */
  888                 break;
  889 
  890         case NG_HCI_OCF_LE_SET_EVENT_MASK:
  891         case NG_HCI_OCF_LE_READ_BUFFER_SIZE:
  892         case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES:
  893         case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS:
  894         case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS:
  895         case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER:
  896         case NG_HCI_OCF_LE_SET_ADVERTISING_DATA:
  897         case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA:
  898         case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE:
  899         case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS:
  900         case NG_HCI_OCF_LE_SET_SCAN_ENABLE:
  901         case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL:
  902         case NG_HCI_OCF_LE_CLEAR_WHITE_LIST:
  903         case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE:
  904         case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST:
  905         case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST:
  906         case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION:
  907         case NG_HCI_OCF_LE_READ_CHANNEL_MAP:
  908         case NG_HCI_OCF_LE_ENCRYPT:
  909         case NG_HCI_OCF_LE_RAND:
  910         case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY:
  911         case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY:
  912         case NG_HCI_OCF_LE_READ_SUPPORTED_STATES:
  913         case NG_HCI_OCF_LE_RECEIVER_TEST:
  914         case NG_HCI_OCF_LE_TRANSMITTER_TEST:
  915         case NG_HCI_OCF_LE_TEST_END:
  916 
  917         default:
  918                 /*
  919                  * None of these command was supposed to generate 
  920                  * Command_Stutus event. Command Complete instead.
  921                  */
  922 
  923                 error = EINVAL;
  924                 break;
  925         } 
  926 
  927         NG_FREE_M(mcp);
  928 
  929         return (error);
  930 
  931 }
  932 
  933 /*
  934  * Process link control command status
  935  */
  936 
  937 static int
  938 process_link_control_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep,
  939                 struct mbuf *mcp)
  940 {
  941         int     error = 0;
  942 
  943         switch (NG_HCI_OCF(ep->opcode)) {
  944         case NG_HCI_OCF_INQUIRY:
  945         case NG_HCI_OCF_DISCON:         /* XXX */
  946         case NG_HCI_OCF_REJECT_CON:     /* XXX */
  947         case NG_HCI_OCF_CHANGE_CON_PKT_TYPE:
  948         case NG_HCI_OCF_AUTH_REQ:
  949         case NG_HCI_OCF_SET_CON_ENCRYPTION:
  950         case NG_HCI_OCF_CHANGE_CON_LINK_KEY:
  951         case NG_HCI_OCF_MASTER_LINK_KEY:
  952         case NG_HCI_OCF_REMOTE_NAME_REQ:
  953         case NG_HCI_OCF_READ_REMOTE_FEATURES:
  954         case NG_HCI_OCF_READ_REMOTE_VER_INFO:
  955         case NG_HCI_OCF_READ_CLOCK_OFFSET:
  956                 /* These do not need post processing */
  957                 break;
  958 
  959         case NG_HCI_OCF_CREATE_CON:
  960                 break;
  961 
  962         case NG_HCI_OCF_ADD_SCO_CON:
  963                 break;
  964 
  965         case NG_HCI_OCF_ACCEPT_CON:
  966                 break;
  967 
  968         case NG_HCI_OCF_INQUIRY_CANCEL:
  969         case NG_HCI_OCF_PERIODIC_INQUIRY:
  970         case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY:
  971         case NG_HCI_OCF_LINK_KEY_REP:
  972         case NG_HCI_OCF_LINK_KEY_NEG_REP: 
  973         case NG_HCI_OCF_PIN_CODE_REP:
  974         case NG_HCI_OCF_PIN_CODE_NEG_REP:
  975         default:
  976 
  977                 /*
  978                  * None of these command was supposed to generate 
  979                  * Command_Status event. Instead Command_Complete event 
  980                  * should have been sent.
  981                  */
  982 
  983                 error = EINVAL;
  984                 break;
  985         }
  986 
  987         NG_FREE_M(mcp);
  988 
  989         return (error);
  990 } /* process_link_control_status */
  991 
  992 /*
  993  * Process link policy command status
  994  */
  995 
  996 static int
  997 process_link_policy_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep,
  998                 struct mbuf *mcp)
  999 {
 1000         int     error = 0;
 1001 
 1002         switch (NG_HCI_OCF(ep->opcode)) {
 1003         case NG_HCI_OCF_HOLD_MODE:
 1004         case NG_HCI_OCF_SNIFF_MODE:
 1005         case NG_HCI_OCF_EXIT_SNIFF_MODE:
 1006         case NG_HCI_OCF_PARK_MODE:
 1007         case NG_HCI_OCF_EXIT_PARK_MODE:
 1008         case NG_HCI_OCF_SWITCH_ROLE:
 1009                 /* These do not need post processing */
 1010                 break;
 1011 
 1012         case NG_HCI_OCF_QOS_SETUP:
 1013                 break;
 1014 
 1015         case NG_HCI_OCF_ROLE_DISCOVERY:
 1016         case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS:
 1017         case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS:
 1018         default:
 1019 
 1020                 /*
 1021                  * None of these command was supposed to generate 
 1022                  * Command_Status event. Instead Command_Complete event 
 1023                  * should have been sent.
 1024                  */
 1025 
 1026                 error = EINVAL;
 1027                 break;
 1028         }
 1029 
 1030         NG_FREE_M(mcp);
 1031 
 1032         return (error);
 1033 } /* process_link_policy_status */

Cache object: 93abc058ebcee1b8a043a2dddcd50039


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