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_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_hci_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_hci_misc.c,v 1.5 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/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/hci/ng_hci_var.h>
   47 #include <netgraph/bluetooth/hci/ng_hci_cmds.h>
   48 #include <netgraph/bluetooth/hci/ng_hci_evnt.h>
   49 #include <netgraph/bluetooth/hci/ng_hci_ulpi.h>
   50 #include <netgraph/bluetooth/hci/ng_hci_misc.h>
   51 
   52 /******************************************************************************
   53  ******************************************************************************
   54  **                              Utility routines
   55  ******************************************************************************
   56  ******************************************************************************/
   57 
   58 /*
   59  * Give packet to RAW hook
   60  * Assumes input mbuf is read only.
   61  */
   62 
   63 void
   64 ng_hci_mtap(ng_hci_unit_p unit, struct mbuf *m0)
   65 {
   66         struct mbuf     *m = NULL;
   67         int              error = 0;
   68 
   69         if (unit->raw != NULL && NG_HOOK_IS_VALID(unit->raw)) {
   70                 m = m_dup(m0, M_NOWAIT);
   71                 if (m != NULL)
   72                         NG_SEND_DATA_ONLY(error, unit->raw, m);
   73 
   74                 if (error != 0)
   75                         NG_HCI_INFO(
   76 "%s: %s - Could not forward packet, error=%d\n",
   77                                 __func__, NG_NODE_NAME(unit->node), error);
   78         }
   79 } /* ng_hci_mtap */
   80 
   81 /*
   82  * Send notification to the upper layer's
   83  */
   84 
   85 void
   86 ng_hci_node_is_up(node_p node, hook_p hook, void *arg1, int arg2)
   87 {
   88         ng_hci_unit_p            unit = NULL;
   89         struct ng_mesg          *msg = NULL;
   90         ng_hci_node_up_ep       *ep = NULL;
   91         int                      error;
   92 
   93         if (node == NULL || NG_NODE_NOT_VALID(node) ||
   94             hook == NULL || NG_HOOK_NOT_VALID(hook))
   95                 return;
   96 
   97         unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
   98         if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY)
   99                 return;
  100 
  101         if (hook != unit->acl && hook != unit->sco)
  102                 return;
  103 
  104         NG_MKMESSAGE(msg,NGM_HCI_COOKIE,NGM_HCI_NODE_UP,sizeof(*ep),M_NOWAIT);
  105         if (msg != NULL) {
  106                 ep = (ng_hci_node_up_ep *)(msg->data);
  107 
  108                 if (hook == unit->acl) {
  109                         NG_HCI_BUFF_ACL_SIZE(unit->buffer, ep->pkt_size);
  110                         NG_HCI_BUFF_ACL_TOTAL(unit->buffer, ep->num_pkts);
  111                 } else {
  112                         NG_HCI_BUFF_SCO_SIZE(unit->buffer, ep->pkt_size);
  113                         NG_HCI_BUFF_SCO_TOTAL(unit->buffer, ep->num_pkts);
  114                 } 
  115 
  116                 bcopy(&unit->bdaddr, &ep->bdaddr, sizeof(ep->bdaddr));
  117 
  118                 NG_SEND_MSG_HOOK(error, node, msg, hook, 0);
  119         } else
  120                 error = ENOMEM;
  121 
  122         if (error != 0)
  123                 NG_HCI_INFO(
  124 "%s: %s - failed to send NODE_UP message to hook \"%s\", error=%d\n",
  125                         __func__, NG_NODE_NAME(unit->node), 
  126                         NG_HOOK_NAME(hook), error);
  127 } /* ng_hci_node_is_up */
  128 
  129 /*
  130  * Clean unit (helper)
  131  */
  132 
  133 void
  134 ng_hci_unit_clean(ng_hci_unit_p unit, int reason)
  135 {
  136         int     size;
  137 
  138         /* Drain command queue */
  139         if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
  140                 ng_hci_command_untimeout(unit);
  141 
  142         NG_BT_MBUFQ_DRAIN(&unit->cmdq);
  143         NG_HCI_BUFF_CMD_SET(unit->buffer, 1);
  144 
  145         /* Clean up connection list */
  146         while (!LIST_EMPTY(&unit->con_list)) {
  147                 ng_hci_unit_con_p       con = LIST_FIRST(&unit->con_list);
  148 
  149                 /* Remove all timeouts (if any) */
  150                 if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
  151                         ng_hci_con_untimeout(con);
  152 
  153                 /*
  154                  * Notify upper layer protocol and destroy connection 
  155                  * descriptor. Do not really care about the result.
  156                  */
  157 
  158                 ng_hci_lp_discon_ind(con, reason);
  159                 ng_hci_free_con(con);
  160         }
  161 
  162         NG_HCI_BUFF_ACL_TOTAL(unit->buffer, size);
  163         NG_HCI_BUFF_ACL_FREE(unit->buffer, size);
  164 
  165         NG_HCI_BUFF_SCO_TOTAL(unit->buffer, size);
  166         NG_HCI_BUFF_SCO_FREE(unit->buffer, size);
  167 
  168         /* Clean up neighbors list */
  169         ng_hci_flush_neighbor_cache(unit);
  170 } /* ng_hci_unit_clean */
  171 
  172 /*
  173  * Allocate and link new unit neighbor cache entry
  174  */
  175 
  176 ng_hci_neighbor_p
  177 ng_hci_new_neighbor(ng_hci_unit_p unit)
  178 {
  179         ng_hci_neighbor_p       n = NULL;
  180 
  181         n = malloc(sizeof(*n), M_NETGRAPH_HCI,
  182                 M_NOWAIT | M_ZERO); 
  183         if (n != NULL) {
  184                 getmicrotime(&n->updated);
  185                 LIST_INSERT_HEAD(&unit->neighbors, n, next);
  186         }
  187 
  188         return (n);
  189 } /* ng_hci_new_neighbor */
  190 
  191 /*
  192  * Free unit neighbor cache entry
  193  */
  194 
  195 void
  196 ng_hci_free_neighbor(ng_hci_neighbor_p n)
  197 {
  198         LIST_REMOVE(n, next);
  199         bzero(n, sizeof(*n));
  200         free(n, M_NETGRAPH_HCI);
  201 } /* ng_hci_free_neighbor */
  202 
  203 /*
  204  * Flush neighbor cache 
  205  */
  206 
  207 void
  208 ng_hci_flush_neighbor_cache(ng_hci_unit_p unit)
  209 {
  210         while (!LIST_EMPTY(&unit->neighbors))
  211                 ng_hci_free_neighbor(LIST_FIRST(&unit->neighbors));
  212 } /* ng_hci_flush_neighbor_cache */
  213 
  214 /*
  215  * Lookup unit in neighbor cache
  216  */
  217 
  218 ng_hci_neighbor_p
  219 ng_hci_get_neighbor(ng_hci_unit_p unit, bdaddr_p bdaddr,int link_type)
  220 {
  221         ng_hci_neighbor_p       n = NULL;
  222 
  223         for (n = LIST_FIRST(&unit->neighbors); n != NULL; ) {
  224                 ng_hci_neighbor_p       nn = LIST_NEXT(n, next);
  225 
  226                 if (!ng_hci_neighbor_stale(n)) {
  227                         if (n->addrtype == link_type && 
  228                             bcmp(&n->bdaddr, bdaddr, sizeof(*bdaddr)) == 0)
  229                                 break;
  230                 } else 
  231                         ng_hci_free_neighbor(n); /* remove old entry */
  232 
  233                 n = nn;
  234         }
  235 
  236         return (n);
  237 } /* ng_hci_get_neighbor */
  238 
  239 /*
  240  * Check if neighbor entry is stale
  241  */
  242 
  243 int
  244 ng_hci_neighbor_stale(ng_hci_neighbor_p n)
  245 {
  246         struct timeval  now;
  247 
  248         getmicrotime(&now);
  249 
  250         return (now.tv_sec - n->updated.tv_sec > bluetooth_hci_max_neighbor_age());
  251 } /* ng_hci_neighbor_stale */
  252 
  253 /*
  254  * Allocate and link new connection descriptor
  255  */
  256 
  257 ng_hci_unit_con_p
  258 ng_hci_new_con(ng_hci_unit_p unit, int link_type)
  259 {
  260         ng_hci_unit_con_p       con = NULL;
  261         int                     num_pkts;
  262         static int              fake_con_handle = 0x0f00;
  263 
  264         con = malloc(sizeof(*con), M_NETGRAPH_HCI,
  265                 M_NOWAIT | M_ZERO);
  266         if (con != NULL) {
  267                 con->unit = unit;
  268                 con->state = NG_HCI_CON_CLOSED;
  269 
  270                 /*
  271                  * XXX
  272                  *
  273                  * Assign fake connection handle to the connection descriptor.
  274                  * Bluetooth specification marks 0x0f00 - 0x0fff connection
  275                  * handles as reserved. We need this fake connection handles
  276                  * for timeouts. Connection handle will be passed as argument
  277                  * to timeout so when timeout happens we can find the right
  278                  * connection descriptor. We can not pass pointers, because
  279                  * timeouts are external (to Netgraph) events and there might
  280                  * be a race when node/hook goes down and timeout event already
  281                  * went into node's queue
  282                  */
  283 
  284                 con->con_handle = fake_con_handle ++;
  285                 if (fake_con_handle > 0x0fff)
  286                         fake_con_handle = 0x0f00;
  287 
  288                 con->link_type = link_type;
  289 
  290                 if (con->link_type != NG_HCI_LINK_SCO)
  291                         NG_HCI_BUFF_ACL_TOTAL(unit->buffer, num_pkts);
  292                 else
  293                         NG_HCI_BUFF_SCO_TOTAL(unit->buffer, num_pkts);
  294 
  295                 NG_BT_ITEMQ_INIT(&con->conq, num_pkts);
  296 
  297                 ng_callout_init(&con->con_timo);
  298 
  299                 LIST_INSERT_HEAD(&unit->con_list, con, next);
  300         }
  301 
  302         return (con);
  303 } /* ng_hci_new_con */
  304 
  305 /*
  306  * Free connection descriptor
  307  */
  308 
  309 void
  310 ng_hci_free_con(ng_hci_unit_con_p con)
  311 { 
  312         LIST_REMOVE(con, next);
  313 
  314         /*
  315          * If we have pending packets then assume that Host Controller has 
  316          * flushed these packets and we can free them too
  317          */
  318 
  319         if (con->link_type != NG_HCI_LINK_SCO)
  320                 NG_HCI_BUFF_ACL_FREE(con->unit->buffer, con->pending);
  321         else
  322                 NG_HCI_BUFF_SCO_FREE(con->unit->buffer, con->pending);
  323 
  324         NG_BT_ITEMQ_DESTROY(&con->conq);
  325 
  326         bzero(con, sizeof(*con));
  327         free(con, M_NETGRAPH_HCI);
  328 } /* ng_hci_free_con */
  329 
  330 /*
  331  * Lookup connection for given unit and connection handle.
  332  */
  333 
  334 ng_hci_unit_con_p
  335 ng_hci_con_by_handle(ng_hci_unit_p unit, int con_handle)
  336 {
  337         ng_hci_unit_con_p       con = NULL;
  338 
  339         LIST_FOREACH(con, &unit->con_list, next)
  340                 if (con->con_handle == con_handle)
  341                         break;
  342 
  343         return (con);
  344 } /* ng_hci_con_by_handle */
  345 
  346 /*
  347  * Lookup connection for given unit, link type and remove unit address
  348  */
  349 
  350 ng_hci_unit_con_p
  351 ng_hci_con_by_bdaddr(ng_hci_unit_p unit, bdaddr_p bdaddr, int link_type)
  352 {
  353         ng_hci_unit_con_p       con = NULL;
  354 
  355         LIST_FOREACH(con, &unit->con_list, next)
  356                 if (con->link_type == link_type &&
  357                     bcmp(&con->bdaddr, bdaddr, sizeof(bdaddr_t)) == 0)
  358                         break;
  359 
  360         return (con);
  361 } /* ng_hci_con_by_bdaddr */
  362 
  363 /*
  364  * Set HCI command timeout
  365  * XXX FIXME: check return code from ng_callout
  366  */
  367 
  368 int
  369 ng_hci_command_timeout(ng_hci_unit_p unit)
  370 {
  371         if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
  372                 panic(
  373 "%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node));
  374 
  375         unit->state |= NG_HCI_UNIT_COMMAND_PENDING;
  376         ng_callout(&unit->cmd_timo, unit->node, NULL,
  377                                 bluetooth_hci_command_timeout(),
  378                                 ng_hci_process_command_timeout, NULL, 0);
  379 
  380         return (0);
  381 } /* ng_hci_command_timeout */
  382 
  383 /*
  384  * Unset HCI command timeout
  385  */
  386 
  387 int
  388 ng_hci_command_untimeout(ng_hci_unit_p unit)
  389 {
  390         if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
  391                 panic(
  392 "%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node));
  393 
  394         if (ng_uncallout(&unit->cmd_timo, unit->node) < 1)
  395                 return (ETIMEDOUT);
  396 
  397         unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
  398 
  399         return (0);
  400 } /* ng_hci_command_untimeout */
  401 
  402 /*
  403  * Set HCI connection timeout
  404  * XXX FIXME: check return code from ng_callout
  405  */
  406 
  407 int
  408 ng_hci_con_timeout(ng_hci_unit_con_p con)
  409 {
  410         if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
  411                 panic(
  412 "%s: %s - Duplicated connection timeout!\n",
  413                         __func__, NG_NODE_NAME(con->unit->node));
  414 
  415         con->flags |= NG_HCI_CON_TIMEOUT_PENDING;
  416         ng_callout(&con->con_timo, con->unit->node, NULL,
  417                                 bluetooth_hci_connect_timeout(),
  418                                 ng_hci_process_con_timeout, NULL,
  419                                 con->con_handle);
  420 
  421         return (0);
  422 } /* ng_hci_con_timeout */
  423 
  424 /*
  425  * Unset HCI connection timeout
  426  */
  427 
  428 int
  429 ng_hci_con_untimeout(ng_hci_unit_con_p con)
  430 {
  431         if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING))
  432                 panic(
  433 "%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node));
  434 
  435         if (ng_uncallout(&con->con_timo, con->unit->node) < 1)
  436                 return (ETIMEDOUT);
  437 
  438         con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
  439 
  440         return (0);
  441 } /* ng_hci_con_untimeout */
  442 
  443 #if 0
  444 /*
  445  * Convert numeric error code/reason to a string
  446  */
  447 
  448 char const * const
  449 ng_hci_str_error(u_int16_t code)
  450 {
  451 #define LAST_ERROR_CODE                 ((sizeof(s)/sizeof(s[0]))-1)
  452         static char const * const       s[] = {
  453         /* 0x00 */ "No error",
  454         /* 0x01 */ "Unknown HCI command",
  455         /* 0x02 */ "No connection",
  456         /* 0x03 */ "Hardware failure",
  457         /* 0x04 */ "Page timeout",
  458         /* 0x05 */ "Authentication failure",
  459         /* 0x06 */ "Key missing",
  460         /* 0x07 */ "Memory full",
  461         /* 0x08 */ "Connection timeout",
  462         /* 0x09 */ "Max number of connections",
  463         /* 0x0a */ "Max number of SCO connections to a unit",
  464         /* 0x0b */ "ACL connection already exists",
  465         /* 0x0c */ "Command disallowed",
  466         /* 0x0d */ "Host rejected due to limited resources",
  467         /* 0x0e */ "Host rejected due to securiity reasons",
  468         /* 0x0f */ "Host rejected due to remote unit is a personal unit",
  469         /* 0x10 */ "Host timeout",
  470         /* 0x11 */ "Unsupported feature or parameter value",
  471         /* 0x12 */ "Invalid HCI command parameter",
  472         /* 0x13 */ "Other end terminated connection: User ended connection",
  473         /* 0x14 */ "Other end terminated connection: Low resources",
  474         /* 0x15 */ "Other end terminated connection: About to power off",
  475         /* 0x16 */ "Connection terminated by local host",
  476         /* 0x17 */ "Repeated attempts",
  477         /* 0x18 */ "Pairing not allowed",
  478         /* 0x19 */ "Unknown LMP PDU",
  479         /* 0x1a */ "Unsupported remote feature",
  480         /* 0x1b */ "SCO offset rejected",
  481         /* 0x1c */ "SCO interval rejected",
  482         /* 0x1d */ "SCO air mode rejected",
  483         /* 0x1e */ "Invalid LMP parameters",
  484         /* 0x1f */ "Unspecified error",
  485         /* 0x20 */ "Unsupported LMP parameter value",
  486         /* 0x21 */ "Role change not allowed",
  487         /* 0x22 */ "LMP response timeout",
  488         /* 0x23 */ "LMP error transaction collision",
  489         /* 0x24 */ "LMP PSU not allowed",
  490         /* 0x25 */ "Encryption mode not acceptable",
  491         /* 0x26 */ "Unit key used",
  492         /* 0x27 */ "QoS is not supported",
  493         /* 0x28 */ "Instant passed",
  494         /* 0x29 */ "Pairing with unit key not supported",
  495         /* 0x2a */ "Different Transaction Collision",
  496         /* 0x2b */ "Unknown error (Reserved for future use)",
  497         /* 0x2c */ "QoS Unacceptable Parameter",
  498         /* 0x2d */ "QoS Rejected",
  499         /* 0x2e */ "Channel Classification Not Supported",
  500         /* 0x2f */ "Insufficient Security",
  501         /* 0x30 */ "Parameter Out Of Mandatory Range",
  502         /* 0x31 */ "Unknown error (Reserved for future use)",
  503         /* 0x32 */ "Role Switch Pending",
  504         /* 0x33 */ "Unknown error (Reserved for future use)",
  505         /* 0x34 */ "Reserved Slot Violation",
  506         /* 0x35 */ "Role Switch Failed",
  507         /* 0x36 */ "Extended Inquiry Response Too Large",
  508         /* 0x37 */ "Secure Simple Pairing Not Supported By Host",
  509         /* 0x38 */ "Host Busy - Pairing",
  510         /* 0x39 */ "Connection Rejected due to No Suitable Channel Found",
  511         /* 0x3a */ "Controller Busy",
  512         /* 0x3b */ "Unacceptable Connection Parameters",
  513         /* 0x3c */ "Advertising Timeout",
  514         /* 0x3d */ "Connection Terminated due to MIC Failure",
  515         /* 0x3e */ "Connection Failed to be Established / Synchronization Timeout",
  516         /* 0x3f */ "MAC Connection Failed",
  517         /* 0x40 */ "Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging",
  518         /* 0x41 */ "Type0 Submap Not Defined",
  519         /* 0x42 */ "Unknown Advertising Identifier",
  520         /* 0x43 */ "Limit Reached",
  521         /* 0x44 */ "Operation Cancelled by Host",
  522         /* 0x45 */ "Packet Too Long",
  523         /* SHOULD ALWAYS BE LAST */ "Unknown error"
  524         };
  525 
  526         return ((code >= LAST_ERROR_CODE)? s[LAST_ERROR_CODE] : s[code]);
  527 } /* ng_hci_str_error */
  528 #endif

Cache object: 9223f282e8f145083c2e1a16fb487c53


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