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_evnt.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_evnt.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_evnt.c,v 1.6 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 event processing module
   56  ******************************************************************************
   57  ******************************************************************************/
   58 
   59 /* 
   60  * Event processing routines 
   61  */
   62 
   63 static int inquiry_result             (ng_hci_unit_p, struct mbuf *);
   64 static int con_compl                  (ng_hci_unit_p, struct mbuf *);
   65 static int con_req                    (ng_hci_unit_p, struct mbuf *);
   66 static int discon_compl               (ng_hci_unit_p, struct mbuf *);
   67 static int encryption_change          (ng_hci_unit_p, struct mbuf *);
   68 static int read_remote_features_compl (ng_hci_unit_p, struct mbuf *);
   69 static int qos_setup_compl            (ng_hci_unit_p, struct mbuf *);
   70 static int hardware_error             (ng_hci_unit_p, struct mbuf *);
   71 static int role_change                (ng_hci_unit_p, struct mbuf *);
   72 static int num_compl_pkts             (ng_hci_unit_p, struct mbuf *);
   73 static int mode_change                (ng_hci_unit_p, struct mbuf *);
   74 static int data_buffer_overflow       (ng_hci_unit_p, struct mbuf *);
   75 static int read_clock_offset_compl    (ng_hci_unit_p, struct mbuf *);
   76 static int qos_violation              (ng_hci_unit_p, struct mbuf *);
   77 static int page_scan_mode_change      (ng_hci_unit_p, struct mbuf *);
   78 static int page_scan_rep_mode_change  (ng_hci_unit_p, struct mbuf *);
   79 static int sync_con_queue             (ng_hci_unit_p, ng_hci_unit_con_p, int);
   80 static int send_data_packets          (ng_hci_unit_p, int, int);
   81 static int le_event                   (ng_hci_unit_p, struct mbuf *);
   82 
   83 /*
   84  * Process HCI event packet
   85  */
   86 
   87 int
   88 ng_hci_process_event(ng_hci_unit_p unit, struct mbuf *event)
   89 {
   90         ng_hci_event_pkt_t      *hdr = NULL;
   91         int                      error = 0;
   92 
   93         /* Get event packet header */
   94         NG_HCI_M_PULLUP(event, sizeof(*hdr));
   95         if (event == NULL)
   96                 return (ENOBUFS);
   97 
   98         hdr = mtod(event, ng_hci_event_pkt_t *);
   99 
  100         NG_HCI_INFO(
  101 "%s: %s - got HCI event=%#x, length=%d\n",
  102                 __func__, NG_NODE_NAME(unit->node), hdr->event, hdr->length);
  103 
  104         /* Get rid of event header and process event */
  105         m_adj(event, sizeof(*hdr));
  106 
  107         switch (hdr->event) {
  108         case NG_HCI_EVENT_INQUIRY_COMPL:
  109         case NG_HCI_EVENT_RETURN_LINK_KEYS:
  110         case NG_HCI_EVENT_PIN_CODE_REQ:
  111         case NG_HCI_EVENT_LINK_KEY_REQ:
  112         case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
  113         case NG_HCI_EVENT_LOOPBACK_COMMAND:
  114         case NG_HCI_EVENT_AUTH_COMPL:
  115         case NG_HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL:
  116         case NG_HCI_EVENT_MASTER_LINK_KEY_COMPL:
  117         case NG_HCI_EVENT_FLUSH_OCCUR:  /* XXX Do we have to handle it? */
  118         case NG_HCI_EVENT_MAX_SLOT_CHANGE:
  119         case NG_HCI_EVENT_CON_PKT_TYPE_CHANGED:
  120         case NG_HCI_EVENT_BT_LOGO:
  121         case NG_HCI_EVENT_VENDOR:
  122         case NG_HCI_EVENT_REMOTE_NAME_REQ_COMPL:
  123         case NG_HCI_EVENT_READ_REMOTE_VER_INFO_COMPL:
  124                 /* These do not need post processing */
  125                 NG_FREE_M(event);
  126                 break;
  127         case NG_HCI_EVENT_LE:
  128                 error = le_event(unit, event);
  129                 break;
  130 
  131         case NG_HCI_EVENT_INQUIRY_RESULT:
  132                 error = inquiry_result(unit, event);
  133                 break;
  134 
  135         case NG_HCI_EVENT_CON_COMPL:
  136                 error = con_compl(unit, event);
  137                 break;
  138 
  139         case NG_HCI_EVENT_CON_REQ:
  140                 error = con_req(unit, event);
  141                 break;
  142 
  143         case NG_HCI_EVENT_DISCON_COMPL:
  144                 error = discon_compl(unit, event);
  145                 break;
  146 
  147         case NG_HCI_EVENT_ENCRYPTION_CHANGE:
  148                 error = encryption_change(unit, event);
  149                 break;
  150 
  151         case NG_HCI_EVENT_READ_REMOTE_FEATURES_COMPL:
  152                 error = read_remote_features_compl(unit, event);
  153                 break;
  154 
  155         case NG_HCI_EVENT_QOS_SETUP_COMPL:
  156                 error = qos_setup_compl(unit, event);
  157                 break;
  158 
  159         case NG_HCI_EVENT_COMMAND_COMPL:
  160                 error = ng_hci_process_command_complete(unit, event);
  161                 break;
  162 
  163         case NG_HCI_EVENT_COMMAND_STATUS:
  164                 error = ng_hci_process_command_status(unit, event);
  165                 break;
  166 
  167         case NG_HCI_EVENT_HARDWARE_ERROR:
  168                 error = hardware_error(unit, event);
  169                 break;
  170 
  171         case NG_HCI_EVENT_ROLE_CHANGE:
  172                 error = role_change(unit, event);
  173                 break;
  174 
  175         case NG_HCI_EVENT_NUM_COMPL_PKTS:
  176                 error = num_compl_pkts(unit, event);
  177                 break;
  178 
  179         case NG_HCI_EVENT_MODE_CHANGE:
  180                 error = mode_change(unit, event);
  181                 break;
  182 
  183         case NG_HCI_EVENT_DATA_BUFFER_OVERFLOW:
  184                 error = data_buffer_overflow(unit, event);
  185                 break;
  186 
  187         case NG_HCI_EVENT_READ_CLOCK_OFFSET_COMPL:
  188                 error = read_clock_offset_compl(unit, event);
  189                 break;
  190 
  191         case NG_HCI_EVENT_QOS_VIOLATION:
  192                 error = qos_violation(unit, event);
  193                 break;
  194 
  195         case NG_HCI_EVENT_PAGE_SCAN_MODE_CHANGE:
  196                 error = page_scan_mode_change(unit, event);
  197                 break;
  198 
  199         case NG_HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE:
  200                 error = page_scan_rep_mode_change(unit, event);
  201                 break;
  202 
  203         default:
  204                 NG_FREE_M(event);
  205                 error = EINVAL;
  206                 break;
  207         }
  208 
  209         return (error);
  210 } /* ng_hci_process_event */
  211 
  212 /*
  213  * Send ACL and/or SCO data to the unit driver
  214  */
  215 
  216 void
  217 ng_hci_send_data(ng_hci_unit_p unit)
  218 {
  219         int     count;
  220 
  221         /* Send ACL data */
  222         NG_HCI_BUFF_ACL_AVAIL(unit->buffer, count);
  223 
  224         NG_HCI_INFO(
  225 "%s: %s - sending ACL data packets, count=%d\n",
  226                 __func__, NG_NODE_NAME(unit->node), count);
  227 
  228         if (count > 0) {
  229                 count = send_data_packets(unit, NG_HCI_LINK_ACL, count);
  230                 NG_HCI_STAT_ACL_SENT(unit->stat, count);
  231                 NG_HCI_BUFF_ACL_USE(unit->buffer, count);
  232         }
  233 
  234         /* Send SCO data */
  235         NG_HCI_BUFF_SCO_AVAIL(unit->buffer, count);
  236 
  237         NG_HCI_INFO(
  238 "%s: %s - sending SCO data packets, count=%d\n",
  239                 __func__, NG_NODE_NAME(unit->node), count);
  240 
  241         if (count > 0) {
  242                 count = send_data_packets(unit, NG_HCI_LINK_SCO, count);
  243                 NG_HCI_STAT_SCO_SENT(unit->stat, count);
  244                 NG_HCI_BUFF_SCO_USE(unit->buffer, count);
  245         }
  246 } /* ng_hci_send_data */
  247 
  248 /*
  249  * Send data packets to the lower layer.
  250  */
  251 
  252 static int
  253 send_data_packets(ng_hci_unit_p unit, int link_type, int limit)
  254 {
  255         ng_hci_unit_con_p       con = NULL, winner = NULL;
  256         int                     reallink_type;
  257         item_p                  item = NULL;
  258         int                     min_pending, total_sent, sent, error, v;
  259 
  260         for (total_sent = 0; limit > 0; ) {
  261                 min_pending = 0x0fffffff;
  262                 winner = NULL;
  263 
  264                 /*
  265                  * Find the connection that has has data to send 
  266                  * and the smallest number of pending packets
  267                  */
  268 
  269                 LIST_FOREACH(con, &unit->con_list, next) {
  270                         reallink_type = (con->link_type == NG_HCI_LINK_SCO)?
  271                                 NG_HCI_LINK_SCO: NG_HCI_LINK_ACL;
  272                         if (reallink_type != link_type){
  273                                 continue;
  274                         }
  275                         if (NG_BT_ITEMQ_LEN(&con->conq) == 0)
  276                                 continue;
  277         
  278                         if (con->pending < min_pending) {
  279                                 winner = con;
  280                                 min_pending = con->pending;
  281                         }
  282                 }
  283 
  284                 if (winner == NULL)
  285                         break;
  286 
  287                 /* 
  288                  * OK, we have a winner now send as much packets as we can
  289                  * Count the number of packets we have sent and then sync
  290                  * winner connection queue.
  291                  */
  292 
  293                 for (sent = 0; limit > 0; limit --, total_sent ++, sent ++) {
  294                         NG_BT_ITEMQ_DEQUEUE(&winner->conq, item);
  295                         if (item == NULL)
  296                                 break;
  297                 
  298                         NG_HCI_INFO(
  299 "%s: %s - sending data packet, handle=%d, len=%d\n",
  300                                 __func__, NG_NODE_NAME(unit->node), 
  301                                 winner->con_handle, NGI_M(item)->m_pkthdr.len);
  302 
  303                         /* Check if driver hook still there */
  304                         v = (unit->drv != NULL && NG_HOOK_IS_VALID(unit->drv));
  305                         if (!v || (unit->state & NG_HCI_UNIT_READY) != 
  306                                         NG_HCI_UNIT_READY) {
  307                                 NG_HCI_ERR(
  308 "%s: %s - could not send data. Hook \"%s\" is %svalid, state=%#x\n",
  309                                         __func__, NG_NODE_NAME(unit->node),
  310                                         NG_HCI_HOOK_DRV, ((v)? "" : "not "),
  311                                         unit->state);
  312 
  313                                 NG_FREE_ITEM(item);
  314                                 error = ENOTCONN;
  315                         } else {
  316                                 v = NGI_M(item)->m_pkthdr.len;
  317 
  318                                 /* Give packet to raw hook */
  319                                 ng_hci_mtap(unit, NGI_M(item));
  320 
  321                                 /* ... and forward item to the driver */
  322                                 NG_FWD_ITEM_HOOK(error, item, unit->drv);
  323                         }
  324 
  325                         if (error != 0) {
  326                                 NG_HCI_ERR(
  327 "%s: %s - could not send data packet, handle=%d, error=%d\n",
  328                                         __func__, NG_NODE_NAME(unit->node),
  329                                         winner->con_handle, error);
  330                                 break;
  331                         }
  332 
  333                         winner->pending ++;
  334                         NG_HCI_STAT_BYTES_SENT(unit->stat, v);
  335                 }
  336 
  337                 /*
  338                  * Sync connection queue for the winner
  339                  */
  340                 sync_con_queue(unit, winner, sent);
  341         }
  342 
  343         return (total_sent);
  344 } /* send_data_packets */
  345 
  346 /*
  347  * Send flow control messages to the upper layer
  348  */
  349 
  350 static int
  351 sync_con_queue(ng_hci_unit_p unit, ng_hci_unit_con_p con, int completed)
  352 {
  353         hook_p                           hook = NULL;
  354         struct ng_mesg                  *msg = NULL;
  355         ng_hci_sync_con_queue_ep        *state = NULL;
  356         int                              error;
  357 
  358         hook = (con->link_type != NG_HCI_LINK_SCO)? unit->acl : unit->sco;
  359         if (hook == NULL || NG_HOOK_NOT_VALID(hook))
  360                 return (ENOTCONN);
  361 
  362         NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_SYNC_CON_QUEUE,
  363                 sizeof(*state), M_NOWAIT);
  364         if (msg == NULL)
  365                 return (ENOMEM);
  366 
  367         state = (ng_hci_sync_con_queue_ep *)(msg->data);
  368         state->con_handle = con->con_handle;
  369         state->completed = completed;
  370 
  371         NG_SEND_MSG_HOOK(error, unit->node, msg, hook, 0);
  372 
  373         return (error);
  374 } /* sync_con_queue */
  375 /* le meta event */
  376 /* Inquiry result event */
  377 static int
  378 le_advertizing_report(ng_hci_unit_p unit, struct mbuf *event)
  379 {
  380         ng_hci_le_advertising_report_ep *ep = NULL;
  381         ng_hci_neighbor_p                n = NULL;
  382         bdaddr_t                         bdaddr;
  383         int                              error = 0;
  384         int                              num_reports = 0;
  385         u_int8_t addr_type;
  386 
  387         NG_HCI_M_PULLUP(event, sizeof(*ep));
  388         if (event == NULL)
  389                 return (ENOBUFS);
  390 
  391         ep = mtod(event, ng_hci_le_advertising_report_ep *);
  392         num_reports = ep->num_reports;
  393         m_adj(event, sizeof(*ep));
  394         ep = NULL;
  395 
  396         for (; num_reports > 0; num_reports --) {
  397                 /* event_type */
  398                 m_adj(event, sizeof(u_int8_t));
  399 
  400                 /* Get remote unit address */
  401                 NG_HCI_M_PULLUP(event, sizeof(u_int8_t));
  402                 if (event == NULL) {
  403                         error = ENOBUFS;
  404                         goto out;
  405                 }
  406                 addr_type = *mtod(event, u_int8_t *);
  407                 m_adj(event, sizeof(u_int8_t));
  408 
  409                 m_copydata(event, 0, sizeof(bdaddr), (caddr_t) &bdaddr);
  410                 m_adj(event, sizeof(bdaddr));
  411                 
  412                 /* Lookup entry in the cache */
  413                 n = ng_hci_get_neighbor(unit, &bdaddr, (addr_type) ? NG_HCI_LINK_LE_RANDOM:NG_HCI_LINK_LE_PUBLIC);
  414                 if (n == NULL) {
  415                         /* Create new entry */
  416                         n = ng_hci_new_neighbor(unit);
  417                         if (n == NULL) {
  418                                 error = ENOMEM;
  419                                 break;
  420                         }
  421                         bcopy(&bdaddr, &n->bdaddr, sizeof(n->bdaddr));
  422                         n->addrtype = (addr_type)? NG_HCI_LINK_LE_RANDOM :
  423                           NG_HCI_LINK_LE_PUBLIC;
  424                         
  425                 } else
  426                         getmicrotime(&n->updated);
  427                 
  428                 {
  429                         /* 
  430                          * TODO: Make these information 
  431                          * Available from userland.
  432                          */
  433                         u_int8_t length_data;
  434                         
  435                         event = m_pullup(event, sizeof(u_int8_t));
  436                         if(event == NULL){
  437                                 NG_HCI_WARN("%s: Event datasize Pullup Failed\n", __func__);
  438                                 goto out;
  439                         }
  440                         length_data = *mtod(event, u_int8_t *);
  441                         m_adj(event, sizeof(u_int8_t));
  442                         n->extinq_size = (length_data < NG_HCI_EXTINQ_MAX)?
  443                                 length_data : NG_HCI_EXTINQ_MAX;
  444                         
  445                         /*Advertizement data*/
  446                         event = m_pullup(event, n->extinq_size);
  447                         if(event == NULL){
  448                                 NG_HCI_WARN("%s: Event data pullup Failed\n", __func__);
  449                                 goto out;
  450                         }
  451                         m_copydata(event, 0, n->extinq_size, n->extinq_data);
  452                         m_adj(event, n->extinq_size);
  453                         event = m_pullup(event, sizeof(char ));
  454                         /*Get RSSI*/
  455                         if(event == NULL){
  456                                 NG_HCI_WARN("%s: Event rssi pull up Failed\n", __func__);
  457                                 
  458                                 goto out;
  459                         }                               
  460                         n->page_scan_mode = *mtod(event, char *);
  461                         m_adj(event, sizeof(u_int8_t));
  462                 }
  463         }
  464  out:
  465         NG_FREE_M(event);
  466 
  467         return (error);
  468 } /* inquiry_result */
  469 
  470 static int le_connection_complete(ng_hci_unit_p unit, struct mbuf *event)
  471 {
  472         int                      error = 0;
  473 
  474         ng_hci_le_connection_complete_ep        *ep = NULL;
  475         ng_hci_unit_con_p        con = NULL;
  476         int link_type;
  477         uint8_t uclass[3] = {0,0,0};//dummy uclass
  478 
  479         NG_HCI_M_PULLUP(event, sizeof(*ep));
  480         if (event == NULL)
  481                 return (ENOBUFS);
  482 
  483         ep = mtod(event, ng_hci_le_connection_complete_ep *);
  484         link_type = (ep->address_type)? NG_HCI_LINK_LE_RANDOM :
  485           NG_HCI_LINK_LE_PUBLIC;
  486         /*
  487          * Find the first connection descriptor that matches the following:
  488          *
  489          * 1) con->link_type == link_type
  490          * 2) con->state == NG_HCI_CON_W4_CONN_COMPLETE
  491          * 3) con->bdaddr == ep->address
  492          */
  493         LIST_FOREACH(con, &unit->con_list, next)
  494                 if (con->link_type == link_type &&
  495                     con->state == NG_HCI_CON_W4_CONN_COMPLETE &&
  496                     bcmp(&con->bdaddr, &ep->address, sizeof(bdaddr_t)) == 0)
  497                         break;
  498 
  499         /*
  500          * Two possible cases:
  501          *
  502          * 1) We have found connection descriptor. That means upper layer has
  503          *    requested this connection via LP_CON_REQ message. In this case
  504          *    connection must have timeout set. If ng_hci_con_untimeout() fails
  505          *    then timeout message already went into node's queue. In this case
  506          *    ignore Connection_Complete event and let timeout deal with it.
  507          *
  508          * 2) We do not have connection descriptor. That means upper layer
  509          *    nas not requested this connection , (less likely) we gave up
  510          *    on this connection (timeout) or as node act as slave role.
  511          *    The most likely scenario is that
  512          *    we have received LE_Create_Connection command 
  513          *    from the RAW hook
  514          */
  515 
  516         if (con == NULL) {
  517                 if (ep->status != 0)
  518                         goto out;
  519 
  520                 con = ng_hci_new_con(unit, link_type);
  521                 if (con == NULL) {
  522                         error = ENOMEM;
  523                         goto out;
  524                 }
  525 
  526                 con->state = NG_HCI_CON_W4_LP_CON_RSP;
  527                 ng_hci_con_timeout(con);
  528 
  529                 bcopy(&ep->address, &con->bdaddr, sizeof(con->bdaddr));
  530                 error = ng_hci_lp_con_ind(con, uclass);
  531                 if (error != 0) {
  532                         ng_hci_con_untimeout(con);
  533                         ng_hci_free_con(con);
  534                         goto out;
  535                 }
  536 
  537         } else if ((error = ng_hci_con_untimeout(con)) != 0)
  538                         goto out;
  539 
  540         /*
  541          * Update connection descriptor and send notification 
  542          * to the upper layers.
  543          */
  544 
  545         con->con_handle = NG_HCI_CON_HANDLE(le16toh(ep->handle));
  546         con->encryption_mode = NG_HCI_ENCRYPTION_MODE_NONE;
  547 
  548         ng_hci_lp_con_cfm(con, ep->status);
  549 
  550         /* Adjust connection state */
  551         if (ep->status != 0)
  552                 ng_hci_free_con(con);
  553         else {
  554                 con->state = NG_HCI_CON_OPEN;
  555 
  556                 /*      
  557                  * Change link policy for the ACL connections. Enable all 
  558                  * supported link modes. Enable Role switch as well if
  559                  * device supports it.
  560                  */
  561         }
  562 
  563 out:
  564         NG_FREE_M(event);
  565 
  566         return (error);
  567 
  568 }
  569 
  570 static int le_connection_update(ng_hci_unit_p unit, struct mbuf *event)
  571 {
  572         int error = 0;
  573         /*TBD*/
  574 
  575         NG_FREE_M(event);
  576         return error;
  577 
  578 }
  579 static int
  580 le_event(ng_hci_unit_p unit, struct mbuf *event)
  581 {
  582         int error = 0;
  583         ng_hci_le_ep *lep;
  584 
  585         NG_HCI_M_PULLUP(event, sizeof(*lep));
  586         if(event ==NULL){
  587                 return ENOBUFS;
  588         }
  589         lep = mtod(event, ng_hci_le_ep *);
  590         m_adj(event, sizeof(*lep));
  591         switch(lep->subevent_code){
  592         case NG_HCI_LEEV_CON_COMPL:
  593                 le_connection_complete(unit, event);
  594                 break;
  595         case NG_HCI_LEEV_ADVREP:
  596                 le_advertizing_report(unit, event);
  597                 break;
  598         case NG_HCI_LEEV_CON_UPDATE_COMPL:
  599                 le_connection_update(unit, event);
  600                 break;
  601         case NG_HCI_LEEV_READ_REMOTE_FEATURES_COMPL:
  602                 //TBD
  603           /*FALLTHROUGH*/
  604         case NG_HCI_LEEV_LONG_TERM_KEY_REQUEST:
  605                 //TBD
  606           /*FALLTHROUGH*/
  607         default:
  608                 NG_FREE_M(event);
  609         }
  610         return error;
  611 }
  612 
  613 /* Inquiry result event */
  614 static int
  615 inquiry_result(ng_hci_unit_p unit, struct mbuf *event)
  616 {
  617         ng_hci_inquiry_result_ep        *ep = NULL;
  618         ng_hci_neighbor_p                n = NULL;
  619         bdaddr_t                         bdaddr;
  620         int                              error = 0;
  621 
  622         NG_HCI_M_PULLUP(event, sizeof(*ep));
  623         if (event == NULL)
  624                 return (ENOBUFS);
  625 
  626         ep = mtod(event, ng_hci_inquiry_result_ep *);
  627         m_adj(event, sizeof(*ep));
  628 
  629         for (; ep->num_responses > 0; ep->num_responses --) {
  630                 /* Get remote unit address */
  631                 m_copydata(event, 0, sizeof(bdaddr), (caddr_t) &bdaddr);
  632                 m_adj(event, sizeof(bdaddr));
  633 
  634                 /* Lookup entry in the cache */
  635                 n = ng_hci_get_neighbor(unit, &bdaddr, NG_HCI_LINK_ACL);
  636                 if (n == NULL) {
  637                         /* Create new entry */
  638                         n = ng_hci_new_neighbor(unit);
  639                         if (n == NULL) {
  640                                 error = ENOMEM;
  641                                 break;
  642                         }
  643                 } else
  644                         getmicrotime(&n->updated);
  645 
  646                 bcopy(&bdaddr, &n->bdaddr, sizeof(n->bdaddr));
  647                 n->addrtype = NG_HCI_LINK_ACL;
  648 
  649                 /* XXX call m_pullup here? */
  650 
  651                 n->page_scan_rep_mode = *mtod(event, u_int8_t *);
  652                 m_adj(event, sizeof(u_int8_t));
  653 
  654                 /* page_scan_period_mode */
  655                 m_adj(event, sizeof(u_int8_t));
  656 
  657                 n->page_scan_mode = *mtod(event, u_int8_t *);
  658                 m_adj(event, sizeof(u_int8_t));
  659 
  660                 /* class */
  661                 m_adj(event, NG_HCI_CLASS_SIZE);
  662 
  663                 /* clock offset */
  664                 m_copydata(event, 0, sizeof(n->clock_offset), 
  665                         (caddr_t) &n->clock_offset);
  666                 n->clock_offset = le16toh(n->clock_offset);
  667         }
  668 
  669         NG_FREE_M(event);
  670 
  671         return (error);
  672 } /* inquiry_result */
  673 
  674 /* Connection complete event */
  675 static int
  676 con_compl(ng_hci_unit_p unit, struct mbuf *event)
  677 {
  678         ng_hci_con_compl_ep     *ep = NULL;
  679         ng_hci_unit_con_p        con = NULL;
  680         int                      error = 0;
  681 
  682         NG_HCI_M_PULLUP(event, sizeof(*ep));
  683         if (event == NULL)
  684                 return (ENOBUFS);
  685 
  686         ep = mtod(event, ng_hci_con_compl_ep *);
  687 
  688         /*
  689          * Find the first connection descriptor that matches the following:
  690          *
  691          * 1) con->link_type == ep->link_type
  692          * 2) con->state == NG_HCI_CON_W4_CONN_COMPLETE
  693          * 3) con->bdaddr == ep->bdaddr
  694          */
  695 
  696         LIST_FOREACH(con, &unit->con_list, next)
  697                 if (con->link_type == ep->link_type &&
  698                     con->state == NG_HCI_CON_W4_CONN_COMPLETE &&
  699                     bcmp(&con->bdaddr, &ep->bdaddr, sizeof(bdaddr_t)) == 0)
  700                         break;
  701 
  702         /*
  703          * Two possible cases:
  704          *
  705          * 1) We have found connection descriptor. That means upper layer has
  706          *    requested this connection via LP_CON_REQ message. In this case
  707          *    connection must have timeout set. If ng_hci_con_untimeout() fails
  708          *    then timeout message already went into node's queue. In this case
  709          *    ignore Connection_Complete event and let timeout deal with it.
  710          *
  711          * 2) We do not have connection descriptor. That means upper layer
  712          *    nas not requested this connection or (less likely) we gave up
  713          *    on this connection (timeout). The most likely scenario is that
  714          *    we have received Create_Connection/Add_SCO_Connection command 
  715          *    from the RAW hook
  716          */
  717 
  718         if (con == NULL) {
  719                 if (ep->status != 0)
  720                         goto out;
  721 
  722                 con = ng_hci_new_con(unit, ep->link_type);
  723                 if (con == NULL) {
  724                         error = ENOMEM;
  725                         goto out;
  726                 }
  727 
  728                 bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr));
  729         } else if ((error = ng_hci_con_untimeout(con)) != 0)
  730                         goto out;
  731 
  732         /*
  733          * Update connection descriptor and send notification 
  734          * to the upper layers.
  735          */
  736 
  737         con->con_handle = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
  738         con->encryption_mode = ep->encryption_mode;
  739 
  740         ng_hci_lp_con_cfm(con, ep->status);
  741 
  742         /* Adjust connection state */
  743         if (ep->status != 0)
  744                 ng_hci_free_con(con);
  745         else {
  746                 con->state = NG_HCI_CON_OPEN;
  747 
  748                 /*      
  749                  * Change link policy for the ACL connections. Enable all 
  750                  * supported link modes. Enable Role switch as well if
  751                  * device supports it.
  752                  */
  753 
  754                 if (ep->link_type == NG_HCI_LINK_ACL) {
  755                         struct __link_policy {
  756                                 ng_hci_cmd_pkt_t                         hdr;
  757                                 ng_hci_write_link_policy_settings_cp     cp;
  758                         } __attribute__ ((packed))                      *lp;
  759                         struct mbuf                                     *m;
  760 
  761                         MGETHDR(m, M_NOWAIT, MT_DATA);
  762                         if (m != NULL) {
  763                                 m->m_pkthdr.len = m->m_len = sizeof(*lp);
  764                                 lp = mtod(m, struct __link_policy *);
  765 
  766                                 lp->hdr.type = NG_HCI_CMD_PKT;
  767                                 lp->hdr.opcode = htole16(NG_HCI_OPCODE(
  768                                         NG_HCI_OGF_LINK_POLICY,
  769                                         NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS));
  770                                 lp->hdr.length = sizeof(lp->cp);
  771 
  772                                 lp->cp.con_handle = ep->con_handle;
  773 
  774                                 lp->cp.settings = 0;
  775                                 if ((unit->features[0] & NG_HCI_LMP_SWITCH) &&
  776                                     unit->role_switch)
  777                                         lp->cp.settings |= 0x1;
  778                                 if (unit->features[0] & NG_HCI_LMP_HOLD_MODE)
  779                                         lp->cp.settings |= 0x2;
  780                                 if (unit->features[0] & NG_HCI_LMP_SNIFF_MODE)
  781                                         lp->cp.settings |= 0x4;
  782                                 if (unit->features[1] & NG_HCI_LMP_PARK_MODE)
  783                                         lp->cp.settings |= 0x8;
  784 
  785                                 lp->cp.settings &= unit->link_policy_mask;
  786                                 lp->cp.settings = htole16(lp->cp.settings);
  787 
  788                                 NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
  789                                 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
  790                                         ng_hci_send_command(unit);
  791                         }
  792                 }
  793         }
  794 out:
  795         NG_FREE_M(event);
  796 
  797         return (error);
  798 } /* con_compl */
  799 
  800 /* Connection request event */
  801 static int
  802 con_req(ng_hci_unit_p unit, struct mbuf *event)
  803 {
  804         ng_hci_con_req_ep       *ep = NULL;
  805         ng_hci_unit_con_p        con = NULL;
  806         int                      error = 0;
  807 
  808         NG_HCI_M_PULLUP(event, sizeof(*ep));
  809         if (event == NULL)
  810                 return (ENOBUFS);
  811 
  812         ep = mtod(event, ng_hci_con_req_ep *);
  813 
  814         /*
  815          * Find the first connection descriptor that matches the following:
  816          *
  817          * 1) con->link_type == ep->link_type
  818          *
  819          * 2) con->state == NG_HCI_CON_W4_LP_CON_RSP ||
  820          *    con->state == NG_HCI_CON_W4_CONN_COMPL
  821          * 
  822          * 3) con->bdaddr == ep->bdaddr
  823          *
  824          * Possible cases:
  825          *
  826          * 1) We do not have connection descriptor. This is simple. Create
  827          *    new fresh connection descriptor and send notification to the
  828          *    appropriate upstream hook (based on link_type).
  829          *
  830          * 2) We found connection handle. This is more complicated.
  831          * 
  832          * 2.1) ACL links
  833          *
  834          *      Since only one ACL link can exist between each pair of
  835          *      units then we have a race. Our upper layer has requested 
  836          *      an ACL connection to the remote unit, but we did not send 
  837          *      command yet. At the same time the remote unit has requested
  838          *      an ACL connection from us. In this case we will ignore 
  839          *      Connection_Request event. This probably will cause connect
  840          *      failure on both units.
  841          *
  842          * 2.2) SCO links
  843          *
  844          *      The spec on page 45 says :
  845          *
  846          *      "The master can support up to three SCO links to the same 
  847          *       slave or to different slaves. A slave can support up to 
  848          *       three SCO links from the same master, or two SCO links if 
  849          *       the links originate from different masters."
  850          *
  851          *      The only problem is how to handle multiple SCO links between
  852          *      matster and slave. For now we will assume that multiple SCO
  853          *      links MUST be opened one after another. 
  854          */
  855 
  856         LIST_FOREACH(con, &unit->con_list, next)
  857                 if (con->link_type == ep->link_type &&
  858                     (con->state == NG_HCI_CON_W4_LP_CON_RSP ||
  859                      con->state == NG_HCI_CON_W4_CONN_COMPLETE) &&
  860                     bcmp(&con->bdaddr, &ep->bdaddr, sizeof(bdaddr_t)) == 0)
  861                         break;
  862 
  863         if (con == NULL) {
  864                 con = ng_hci_new_con(unit, ep->link_type);
  865                 if (con != NULL) {
  866                         bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr));
  867 
  868                         con->state = NG_HCI_CON_W4_LP_CON_RSP;
  869                         ng_hci_con_timeout(con);
  870 
  871                         error = ng_hci_lp_con_ind(con, ep->uclass);
  872                         if (error != 0) {
  873                                 ng_hci_con_untimeout(con);
  874                                 ng_hci_free_con(con);
  875                         }
  876                 } else
  877                         error = ENOMEM;
  878         }
  879 
  880         NG_FREE_M(event);
  881 
  882         return (error);
  883 } /* con_req */
  884 
  885 /* Disconnect complete event */
  886 static int
  887 discon_compl(ng_hci_unit_p unit, struct mbuf *event)
  888 {
  889         ng_hci_discon_compl_ep  *ep = NULL;
  890         ng_hci_unit_con_p        con = NULL;
  891         int                      error = 0;
  892         u_int16_t                h;
  893 
  894         NG_HCI_M_PULLUP(event, sizeof(*ep));
  895         if (event == NULL)
  896                 return (ENOBUFS);
  897 
  898         ep = mtod(event, ng_hci_discon_compl_ep *);
  899 
  900         /* 
  901          * XXX 
  902          * Do we have to send notification if ep->status != 0? 
  903          * For now we will send notification for both ACL and SCO connections
  904          * ONLY if ep->status == 0.
  905          */
  906 
  907         if (ep->status == 0) {
  908                 h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
  909                 con = ng_hci_con_by_handle(unit, h);
  910                 if (con != NULL) {
  911                         error = ng_hci_lp_discon_ind(con, ep->reason);
  912 
  913                         /* Remove all timeouts (if any) */
  914                         if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
  915                                 ng_hci_con_untimeout(con);
  916 
  917                         ng_hci_free_con(con);
  918                 } else {
  919                         NG_HCI_ALERT(
  920 "%s: %s - invalid connection handle=%d\n",
  921                                 __func__, NG_NODE_NAME(unit->node), h);
  922                         error = ENOENT;
  923                 }
  924         }
  925 
  926         NG_FREE_M(event);
  927 
  928         return (error);
  929 } /* discon_compl */
  930 
  931 /* Encryption change event */
  932 static int
  933 encryption_change(ng_hci_unit_p unit, struct mbuf *event)
  934 {
  935         ng_hci_encryption_change_ep     *ep = NULL;
  936         ng_hci_unit_con_p                con = NULL;
  937         int                              error = 0;
  938         u_int16_t       h;
  939 
  940         NG_HCI_M_PULLUP(event, sizeof(*ep));
  941         if (event == NULL)
  942                 return (ENOBUFS);
  943 
  944         ep = mtod(event, ng_hci_encryption_change_ep *);
  945         h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
  946         con = ng_hci_con_by_handle(unit, h);
  947 
  948         if (ep->status == 0) {
  949                 if (con == NULL) {
  950                         NG_HCI_ALERT(
  951 "%s: %s - invalid connection handle=%d\n",
  952                                 __func__, NG_NODE_NAME(unit->node), h);
  953                         error = ENOENT;
  954                 } else if (con->link_type == NG_HCI_LINK_SCO) {
  955                         NG_HCI_ALERT(
  956 "%s: %s - invalid link type=%d\n",
  957                                 __func__, NG_NODE_NAME(unit->node), 
  958                                 con->link_type);
  959                         error = EINVAL;
  960                 } else if (ep->encryption_enable)
  961                         /* XXX is that true? */
  962                         con->encryption_mode = NG_HCI_ENCRYPTION_MODE_P2P;
  963                 else
  964                         con->encryption_mode = NG_HCI_ENCRYPTION_MODE_NONE;
  965         } else
  966                 NG_HCI_ERR(
  967 "%s: %s - failed to change encryption mode, status=%d\n",
  968                         __func__, NG_NODE_NAME(unit->node), ep->status);
  969 
  970         /*Anyway, propagete encryption status to upper layer*/
  971         ng_hci_lp_enc_change(con, con->encryption_mode);
  972 
  973         NG_FREE_M(event);
  974 
  975         return (error);
  976 } /* encryption_change */
  977 
  978 /* Read remote feature complete event */
  979 static int
  980 read_remote_features_compl(ng_hci_unit_p unit, struct mbuf *event)
  981 {
  982         ng_hci_read_remote_features_compl_ep    *ep = NULL;
  983         ng_hci_unit_con_p                        con = NULL;
  984         ng_hci_neighbor_p                        n = NULL;
  985         u_int16_t                                h;
  986         int                                      error = 0;
  987 
  988         NG_HCI_M_PULLUP(event, sizeof(*ep));
  989         if (event == NULL)
  990                 return (ENOBUFS);
  991 
  992         ep = mtod(event, ng_hci_read_remote_features_compl_ep *);
  993 
  994         if (ep->status == 0) {
  995                 /* Check if we have this connection handle */
  996                 h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
  997                 con = ng_hci_con_by_handle(unit, h);
  998                 if (con == NULL) {
  999                         NG_HCI_ALERT(
 1000 "%s: %s - invalid connection handle=%d\n",
 1001                                 __func__, NG_NODE_NAME(unit->node), h);
 1002                         error = ENOENT;
 1003                         goto out;
 1004                 }
 1005 
 1006                 /* Update cache entry */
 1007                 n = ng_hci_get_neighbor(unit, &con->bdaddr, NG_HCI_LINK_ACL);
 1008                 if (n == NULL) {
 1009                         n = ng_hci_new_neighbor(unit);
 1010                         if (n == NULL) {
 1011                                 error = ENOMEM;
 1012                                 goto out;
 1013                         }
 1014 
 1015                         bcopy(&con->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
 1016                         n->addrtype = NG_HCI_LINK_ACL;
 1017                 } else
 1018                         getmicrotime(&n->updated);
 1019 
 1020                 bcopy(ep->features, n->features, sizeof(n->features));
 1021         } else
 1022                 NG_HCI_ERR(
 1023 "%s: %s - failed to read remote unit features, status=%d\n",
 1024                         __func__, NG_NODE_NAME(unit->node), ep->status);
 1025 out:
 1026         NG_FREE_M(event);
 1027 
 1028         return (error);
 1029 } /* read_remote_features_compl */
 1030 
 1031 /* QoS setup complete event */
 1032 static int
 1033 qos_setup_compl(ng_hci_unit_p unit, struct mbuf *event)
 1034 {
 1035         ng_hci_qos_setup_compl_ep       *ep = NULL;
 1036         ng_hci_unit_con_p                con = NULL;
 1037         u_int16_t                        h;
 1038         int                              error = 0;
 1039 
 1040         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1041         if (event == NULL)
 1042                 return (ENOBUFS);
 1043 
 1044         ep = mtod(event, ng_hci_qos_setup_compl_ep *);
 1045 
 1046         /* Check if we have this connection handle */
 1047         h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
 1048         con = ng_hci_con_by_handle(unit, h);
 1049         if (con == NULL) {
 1050                 NG_HCI_ALERT(
 1051 "%s: %s - invalid connection handle=%d\n",
 1052                         __func__, NG_NODE_NAME(unit->node), h);
 1053                 error = ENOENT;
 1054         } else if (con->link_type != NG_HCI_LINK_ACL) {
 1055                 NG_HCI_ALERT(
 1056 "%s: %s - invalid link type=%d, handle=%d\n",
 1057                         __func__, NG_NODE_NAME(unit->node), con->link_type, h);
 1058                 error = EINVAL;
 1059         } else if (con->state != NG_HCI_CON_OPEN) {
 1060                 NG_HCI_ALERT(
 1061 "%s: %s - invalid connection state=%d, handle=%d\n",
 1062                         __func__, NG_NODE_NAME(unit->node), 
 1063                         con->state, h);
 1064                 error = EINVAL;
 1065         } else /* Notify upper layer */
 1066                 error = ng_hci_lp_qos_cfm(con, ep->status);
 1067 
 1068         NG_FREE_M(event);
 1069 
 1070         return (error);
 1071 } /* qos_setup_compl */
 1072 
 1073 /* Hardware error event */
 1074 static int
 1075 hardware_error(ng_hci_unit_p unit, struct mbuf *event)
 1076 {
 1077         NG_HCI_ALERT(
 1078 "%s: %s - hardware error %#x\n",
 1079                 __func__, NG_NODE_NAME(unit->node), *mtod(event, u_int8_t *));
 1080 
 1081         NG_FREE_M(event);
 1082 
 1083         return (0);
 1084 } /* hardware_error */
 1085 
 1086 /* Role change event */
 1087 static int
 1088 role_change(ng_hci_unit_p unit, struct mbuf *event)
 1089 {
 1090         ng_hci_role_change_ep   *ep = NULL;
 1091         ng_hci_unit_con_p        con = NULL;
 1092 
 1093         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1094         if (event == NULL)
 1095                 return (ENOBUFS);
 1096 
 1097         ep = mtod(event, ng_hci_role_change_ep *);
 1098 
 1099         if (ep->status == 0) {
 1100                 /* XXX shoud we also change "role" for SCO connections? */
 1101                 con = ng_hci_con_by_bdaddr(unit, &ep->bdaddr, NG_HCI_LINK_ACL);
 1102                 if (con != NULL)
 1103                         con->role = ep->role;
 1104                 else
 1105                         NG_HCI_ALERT(
 1106 "%s: %s - ACL connection does not exist, bdaddr=%x:%x:%x:%x:%x:%x\n",
 1107                                 __func__, NG_NODE_NAME(unit->node),
 1108                                 ep->bdaddr.b[5], ep->bdaddr.b[4], 
 1109                                 ep->bdaddr.b[3], ep->bdaddr.b[2], 
 1110                                 ep->bdaddr.b[1], ep->bdaddr.b[0]);
 1111         } else
 1112                 NG_HCI_ERR(
 1113 "%s: %s - failed to change role, status=%d, bdaddr=%x:%x:%x:%x:%x:%x\n",
 1114                         __func__, NG_NODE_NAME(unit->node), ep->status,
 1115                         ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3],
 1116                         ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]);
 1117 
 1118         NG_FREE_M(event);
 1119 
 1120         return (0);
 1121 } /* role_change */
 1122 
 1123 /* Number of completed packets event */
 1124 static int
 1125 num_compl_pkts(ng_hci_unit_p unit, struct mbuf *event)
 1126 {
 1127         ng_hci_num_compl_pkts_ep        *ep = NULL;
 1128         ng_hci_unit_con_p                con = NULL;
 1129         u_int16_t                        h, p;
 1130 
 1131         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1132         if (event == NULL)
 1133                 return (ENOBUFS);
 1134 
 1135         ep = mtod(event, ng_hci_num_compl_pkts_ep *);
 1136         m_adj(event, sizeof(*ep));
 1137 
 1138         for (; ep->num_con_handles > 0; ep->num_con_handles --) {
 1139                 /* Get connection handle */
 1140                 m_copydata(event, 0, sizeof(h), (caddr_t) &h);
 1141                 m_adj(event, sizeof(h));
 1142                 h = NG_HCI_CON_HANDLE(le16toh(h));
 1143 
 1144                 /* Get number of completed packets */
 1145                 m_copydata(event, 0, sizeof(p), (caddr_t) &p);
 1146                 m_adj(event, sizeof(p));
 1147                 p = le16toh(p);
 1148 
 1149                 /* Check if we have this connection handle */
 1150                 con = ng_hci_con_by_handle(unit, h);
 1151                 if (con != NULL) {
 1152                         con->pending -= p;
 1153                         if (con->pending < 0) {
 1154                                 NG_HCI_WARN(
 1155 "%s: %s - pending packet counter is out of sync! " \
 1156 "handle=%d, pending=%d, ncp=%d\n",      __func__, NG_NODE_NAME(unit->node), 
 1157                                         con->con_handle, con->pending, p);
 1158 
 1159                                 con->pending = 0;
 1160                         }
 1161 
 1162                         /* Update buffer descriptor */
 1163                         if (con->link_type != NG_HCI_LINK_SCO)
 1164                                 NG_HCI_BUFF_ACL_FREE(unit->buffer, p);
 1165                         else 
 1166                                 NG_HCI_BUFF_SCO_FREE(unit->buffer, p);
 1167                 } else
 1168                         NG_HCI_ALERT(
 1169 "%s: %s - invalid connection handle=%d\n",
 1170                                 __func__, NG_NODE_NAME(unit->node), h);
 1171         }
 1172 
 1173         NG_FREE_M(event);
 1174 
 1175         /* Send more data */
 1176         ng_hci_send_data(unit);
 1177 
 1178         return (0);
 1179 } /* num_compl_pkts */
 1180 
 1181 /* Mode change event */
 1182 static int
 1183 mode_change(ng_hci_unit_p unit, struct mbuf *event)
 1184 {
 1185         ng_hci_mode_change_ep   *ep = NULL;
 1186         ng_hci_unit_con_p        con = NULL;
 1187         int                      error = 0;
 1188 
 1189         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1190         if (event == NULL)
 1191                 return (ENOBUFS);
 1192 
 1193         ep = mtod(event, ng_hci_mode_change_ep *);
 1194 
 1195         if (ep->status == 0) {
 1196                 u_int16_t       h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
 1197 
 1198                 con = ng_hci_con_by_handle(unit, h);
 1199                 if (con == NULL) {
 1200                         NG_HCI_ALERT(
 1201 "%s: %s - invalid connection handle=%d\n",
 1202                                 __func__, NG_NODE_NAME(unit->node), h);
 1203                         error = ENOENT;
 1204                 } else if (con->link_type != NG_HCI_LINK_ACL) {
 1205                         NG_HCI_ALERT(
 1206 "%s: %s - invalid link type=%d\n",
 1207                                 __func__, NG_NODE_NAME(unit->node), 
 1208                                 con->link_type);
 1209                         error = EINVAL;
 1210                 } else
 1211                         con->mode = ep->unit_mode;
 1212         } else
 1213                 NG_HCI_ERR(
 1214 "%s: %s - failed to change mode, status=%d\n",
 1215                         __func__, NG_NODE_NAME(unit->node), ep->status);
 1216 
 1217         NG_FREE_M(event);
 1218 
 1219         return (error);
 1220 } /* mode_change */
 1221 
 1222 /* Data buffer overflow event */
 1223 static int
 1224 data_buffer_overflow(ng_hci_unit_p unit, struct mbuf *event)
 1225 {
 1226         NG_HCI_ALERT(
 1227 "%s: %s - %s data buffer overflow\n",
 1228                 __func__, NG_NODE_NAME(unit->node),
 1229                 (*mtod(event, u_int8_t *) == NG_HCI_LINK_ACL)? "ACL" : "SCO");
 1230 
 1231         NG_FREE_M(event);
 1232 
 1233         return (0);
 1234 } /* data_buffer_overflow */
 1235 
 1236 /* Read clock offset complete event */
 1237 static int
 1238 read_clock_offset_compl(ng_hci_unit_p unit, struct mbuf *event)
 1239 {
 1240         ng_hci_read_clock_offset_compl_ep       *ep = NULL;
 1241         ng_hci_unit_con_p                        con = NULL;
 1242         ng_hci_neighbor_p                        n = NULL;
 1243         int                                      error = 0;
 1244 
 1245         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1246         if (event == NULL)
 1247                 return (ENOBUFS);
 1248 
 1249         ep = mtod(event, ng_hci_read_clock_offset_compl_ep *);
 1250 
 1251         if (ep->status == 0) {
 1252                 u_int16_t       h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
 1253 
 1254                 con = ng_hci_con_by_handle(unit, h);
 1255                 if (con == NULL) {
 1256                         NG_HCI_ALERT(
 1257 "%s: %s - invalid connection handle=%d\n",
 1258                                 __func__, NG_NODE_NAME(unit->node), h);
 1259                         error = ENOENT;
 1260                         goto out;
 1261                 }
 1262 
 1263                 /* Update cache entry */
 1264                 n = ng_hci_get_neighbor(unit, &con->bdaddr, NG_HCI_LINK_ACL);
 1265                 if (n == NULL) {
 1266                         n = ng_hci_new_neighbor(unit);
 1267                         if (n == NULL) {
 1268                                 error = ENOMEM;
 1269                                 goto out;
 1270                         }
 1271 
 1272                         bcopy(&con->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
 1273                         n->addrtype = NG_HCI_LINK_ACL;
 1274                 } else
 1275                         getmicrotime(&n->updated);
 1276 
 1277                 n->clock_offset = le16toh(ep->clock_offset);
 1278         } else
 1279                 NG_HCI_ERR(
 1280 "%s: %s - failed to Read Remote Clock Offset, status=%d\n",
 1281                         __func__, NG_NODE_NAME(unit->node), ep->status);
 1282 out:
 1283         NG_FREE_M(event);
 1284 
 1285         return (error);
 1286 } /* read_clock_offset_compl */
 1287 
 1288 /* QoS violation event */
 1289 static int
 1290 qos_violation(ng_hci_unit_p unit, struct mbuf *event)
 1291 {
 1292         ng_hci_qos_violation_ep *ep = NULL;
 1293         ng_hci_unit_con_p        con = NULL;
 1294         u_int16_t                h;
 1295         int                      error = 0;
 1296 
 1297         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1298         if (event == NULL)
 1299                 return (ENOBUFS);
 1300 
 1301         ep = mtod(event, ng_hci_qos_violation_ep *);
 1302 
 1303         /* Check if we have this connection handle */
 1304         h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
 1305         con = ng_hci_con_by_handle(unit, h);
 1306         if (con == NULL) {
 1307                 NG_HCI_ALERT(
 1308 "%s: %s - invalid connection handle=%d\n",
 1309                         __func__, NG_NODE_NAME(unit->node), h);
 1310                 error = ENOENT;
 1311         } else if (con->link_type != NG_HCI_LINK_ACL) {
 1312                 NG_HCI_ALERT(
 1313 "%s: %s - invalid link type=%d\n",
 1314                         __func__, NG_NODE_NAME(unit->node), con->link_type);
 1315                 error = EINVAL;
 1316         } else if (con->state != NG_HCI_CON_OPEN) {
 1317                 NG_HCI_ALERT(
 1318 "%s: %s - invalid connection state=%d, handle=%d\n",
 1319                         __func__, NG_NODE_NAME(unit->node), con->state, h);
 1320                 error = EINVAL;
 1321         } else /* Notify upper layer */
 1322                 error = ng_hci_lp_qos_ind(con); 
 1323 
 1324         NG_FREE_M(event);
 1325 
 1326         return (error);
 1327 } /* qos_violation */
 1328 
 1329 /* Page scan mode change event */
 1330 static int
 1331 page_scan_mode_change(ng_hci_unit_p unit, struct mbuf *event)
 1332 {
 1333         ng_hci_page_scan_mode_change_ep *ep = NULL;
 1334         ng_hci_neighbor_p                n = NULL;
 1335         int                              error = 0;
 1336 
 1337         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1338         if (event == NULL)
 1339                 return (ENOBUFS);
 1340 
 1341         ep = mtod(event, ng_hci_page_scan_mode_change_ep *);
 1342 
 1343         /* Update cache entry */
 1344         n = ng_hci_get_neighbor(unit, &ep->bdaddr, NG_HCI_LINK_ACL);
 1345         if (n == NULL) {
 1346                 n = ng_hci_new_neighbor(unit);
 1347                 if (n == NULL) {
 1348                         error = ENOMEM;
 1349                         goto out;
 1350                 }
 1351 
 1352                 bcopy(&ep->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
 1353                 n->addrtype = NG_HCI_LINK_ACL;
 1354         } else
 1355                 getmicrotime(&n->updated);
 1356 
 1357         n->page_scan_mode = ep->page_scan_mode;
 1358 out:
 1359         NG_FREE_M(event);
 1360 
 1361         return (error);
 1362 } /* page_scan_mode_change */
 1363 
 1364 /* Page scan repetition mode change event */
 1365 static int
 1366 page_scan_rep_mode_change(ng_hci_unit_p unit, struct mbuf *event)
 1367 {
 1368         ng_hci_page_scan_rep_mode_change_ep     *ep = NULL;
 1369         ng_hci_neighbor_p                        n = NULL;
 1370         int                                      error = 0;
 1371 
 1372         NG_HCI_M_PULLUP(event, sizeof(*ep));
 1373         if (event == NULL)
 1374                 return (ENOBUFS);
 1375 
 1376         ep = mtod(event, ng_hci_page_scan_rep_mode_change_ep *);
 1377 
 1378         /* Update cache entry */
 1379         n = ng_hci_get_neighbor(unit, &ep->bdaddr, NG_HCI_LINK_ACL);
 1380         if (n == NULL) {
 1381                 n = ng_hci_new_neighbor(unit);
 1382                 if (n == NULL) {
 1383                         error = ENOMEM;
 1384                         goto out;
 1385                 }
 1386 
 1387                 bcopy(&ep->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
 1388                 n->addrtype = NG_HCI_LINK_ACL;
 1389         } else
 1390                 getmicrotime(&n->updated);
 1391 
 1392         n->page_scan_rep_mode = ep->page_scan_rep_mode;
 1393 out:
 1394         NG_FREE_M(event);
 1395 
 1396         return (error);
 1397 } /* page_scan_rep_mode_change */

Cache object: e5798afc9820ebf413a7704c17433592


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