Home | History | Annotate | Download | only in pan
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 1999-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This file contains main functions to support PAN profile
     22  *  commands and events.
     23  *
     24  ******************************************************************************/
     25 
     26 #include <string.h>
     27 #include "gki.h"
     28 #include "bt_types.h"
     29 #include "bt_utils.h"
     30 #include "bnep_api.h"
     31 #include "pan_api.h"
     32 #include "pan_int.h"
     33 #include "sdp_api.h"
     34 #include "sdpdefs.h"
     35 #include "l2c_api.h"
     36 #include "hcidefs.h"
     37 
     38 
     39 #if PAN_DYNAMIC_MEMORY == FALSE
     40 tPAN_CB  pan_cb;
     41 #endif
     42 
     43 #define UUID_CONSTANT_PART  12
     44 UINT8 constant_pan_uuid[UUID_CONSTANT_PART] = {0, 0, 0x10, 0, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
     45 
     46 
     47 /*******************************************************************************
     48 **
     49 ** Function         pan_register_with_bnep
     50 **
     51 ** Description      This function registers PAN profile with BNEP
     52 **
     53 ** Parameters:      none
     54 **
     55 ** Returns          none
     56 **
     57 *******************************************************************************/
     58 void pan_register_with_bnep (void)
     59 {
     60     tBNEP_REGISTER      reg_info;
     61 
     62     memset (&reg_info, 0, sizeof (tBNEP_REGISTER));
     63 
     64     reg_info.p_conn_ind_cb      = pan_conn_ind_cb;
     65     reg_info.p_conn_state_cb    = pan_connect_state_cb;
     66     reg_info.p_data_buf_cb      = pan_data_buf_ind_cb;
     67     reg_info.p_data_ind_cb      = NULL;
     68     reg_info.p_tx_data_flow_cb  = pan_tx_data_flow_cb;
     69     reg_info.p_filter_ind_cb    = pan_proto_filt_ind_cb;
     70     reg_info.p_mfilter_ind_cb   = pan_mcast_filt_ind_cb;
     71 
     72     BNEP_Register (&reg_info);
     73 }
     74 
     75 
     76 /*******************************************************************************
     77 **
     78 ** Function         pan_conn_ind_cb
     79 **
     80 ** Description      This function is registered with BNEP as connection indication
     81 **                  callback. BNEP will call this when there is connection
     82 **                  request from the peer. PAN should call BNEP_ConnectResp to
     83 **                  indicate whether to accept the connection or reject
     84 **
     85 ** Parameters:      handle          - handle for the connection
     86 **                  p_bda           - BD Addr of the peer requesting the connection
     87 **                  remote_uuid     - UUID of the source role (peer device role)
     88 **                  local_uuid      - UUID of the destination role (local device role)
     89 **                  is_role_change  - Flag to indicate that it is a role change
     90 **
     91 ** Returns          none
     92 **
     93 *******************************************************************************/
     94 void pan_conn_ind_cb (UINT16 handle,
     95                       BD_ADDR p_bda,
     96                       tBT_UUID *remote_uuid,
     97                       tBT_UUID *local_uuid,
     98                       BOOLEAN is_role_change)
     99 {
    100     tPAN_CONN       *pcb;
    101     UINT8           req_role;
    102     BOOLEAN         wrong_uuid;
    103 
    104     /*
    105     ** If we are in GN or NAP role and have one or more
    106     ** active connections and the received connection is
    107     ** for user role reject it.
    108     ** If we are in user role with one connection active
    109     ** reject the connection.
    110     ** Allocate PCB and store the parameters
    111     ** Make bridge request to the host system if connection
    112     ** is for NAP
    113     */
    114     wrong_uuid = FALSE;
    115 #if (defined (BNEP_SUPPORTS_ALL_UUID_LENGTHS) && BNEP_SUPPORTS_ALL_UUID_LENGTHS == TRUE)
    116     if (remote_uuid->len == 16)
    117     {
    118         /*
    119         ** If the UUID is 16 bytes forst two bytes should be zeros
    120         ** and last 12 bytes should match the spec defined constant value
    121         */
    122         if (memcmp (constant_pan_uuid, remote_uuid->uu.uuid128 + 4, UUID_CONSTANT_PART))
    123             wrong_uuid = TRUE;
    124 
    125         if (remote_uuid->uu.uuid128[0] || remote_uuid->uu.uuid128[1])
    126             wrong_uuid = TRUE;
    127 
    128         /* Extract the 16 bit equivalent of the UUID */
    129         remote_uuid->uu.uuid16 = (UINT16)((remote_uuid->uu.uuid128[2] << 8) | remote_uuid->uu.uuid128[3]);
    130         remote_uuid->len = 2;
    131     }
    132     if (remote_uuid->len == 4)
    133     {
    134         /* First two bytes should be zeros */
    135         if (remote_uuid->uu.uuid32 & 0xFFFF0000)
    136             wrong_uuid = TRUE;
    137 
    138         remote_uuid->uu.uuid16 = (UINT16)remote_uuid->uu.uuid32;
    139         remote_uuid->len = 2;
    140     }
    141 
    142     if (wrong_uuid)
    143     {
    144         PAN_TRACE_ERROR ("PAN Connection failed because of wrong remote UUID ");
    145         BNEP_ConnectResp (handle, BNEP_CONN_FAILED_SRC_UUID);
    146         return;
    147     }
    148 
    149     wrong_uuid = FALSE;
    150     if (local_uuid->len == 16)
    151     {
    152         /*
    153         ** If the UUID is 16 bytes forst two bytes should be zeros
    154         ** and last 12 bytes should match the spec defined constant value
    155         */
    156         if (memcmp (constant_pan_uuid, local_uuid->uu.uuid128 + 4, UUID_CONSTANT_PART))
    157             wrong_uuid = TRUE;
    158 
    159         if (local_uuid->uu.uuid128[0] || local_uuid->uu.uuid128[1])
    160             wrong_uuid = TRUE;
    161 
    162         /* Extract the 16 bit equivalent of the UUID */
    163         local_uuid->uu.uuid16 = (UINT16)((local_uuid->uu.uuid128[2] << 8) | local_uuid->uu.uuid128[3]);
    164         local_uuid->len = 2;
    165     }
    166     if (local_uuid->len == 4)
    167     {
    168         /* First two bytes should be zeros */
    169         if (local_uuid->uu.uuid32 & 0xFFFF0000)
    170             wrong_uuid = TRUE;
    171 
    172         local_uuid->uu.uuid16 = (UINT16)local_uuid->uu.uuid32;
    173         local_uuid->len = 2;
    174     }
    175 
    176     if (wrong_uuid)
    177     {
    178         PAN_TRACE_ERROR ("PAN Connection failed because of wrong local UUID ");
    179         BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
    180         return;
    181     }
    182 
    183     PAN_TRACE_EVENT ("pan_conn_ind_cb - for handle %d, current role %d, dst uuid 0x%x, src uuid 0x%x, role change %s",
    184         handle, pan_cb.role, local_uuid->uu.uuid16, remote_uuid->uu.uuid16, is_role_change?"YES":"NO");
    185     /* The acceptable UUID size is only 2 */
    186     if (remote_uuid->len != 2)
    187     {
    188         PAN_TRACE_ERROR ("PAN Connection failed because of wrong UUID size %d", remote_uuid->len);
    189         BNEP_ConnectResp (handle, BNEP_CONN_FAILED_UUID_SIZE);
    190         return;
    191     }
    192 #endif
    193 
    194     /* Check if the source UUID is a valid one */
    195     if (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
    196         remote_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
    197         remote_uuid->uu.uuid16 != UUID_SERVCLASS_GN)
    198     {
    199         PAN_TRACE_ERROR ("Src UUID 0x%x is not valid", remote_uuid->uu.uuid16);
    200         BNEP_ConnectResp (handle, BNEP_CONN_FAILED_SRC_UUID);
    201         return;
    202     }
    203 
    204     /* Check if the destination UUID is a valid one */
    205     if (local_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
    206         local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
    207         local_uuid->uu.uuid16 != UUID_SERVCLASS_GN)
    208     {
    209         PAN_TRACE_ERROR ("Dst UUID 0x%x is not valid", remote_uuid->uu.uuid16);
    210         BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
    211         return;
    212     }
    213 
    214     /* Check if currently we support the destination role requested */
    215     if (((!(pan_cb.role & UUID_SERVCLASS_PANU))
    216         && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) ||
    217         ((!(pan_cb.role & UUID_SERVCLASS_GN))
    218         && local_uuid->uu.uuid16 == UUID_SERVCLASS_GN) ||
    219         ((!(pan_cb.role & UUID_SERVCLASS_NAP))
    220         && local_uuid->uu.uuid16 == UUID_SERVCLASS_NAP))
    221     {
    222         PAN_TRACE_ERROR ("PAN Connection failed because of unsupported destination UUID 0x%x", local_uuid->uu.uuid16);
    223         BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
    224         return;
    225     }
    226 
    227     /* Requested destination role is */
    228     if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
    229         req_role = PAN_ROLE_CLIENT;
    230     else if (local_uuid->uu.uuid16 == UUID_SERVCLASS_GN)
    231         req_role = PAN_ROLE_GN_SERVER;
    232     else
    233         req_role = PAN_ROLE_NAP_SERVER;
    234 
    235     /* If the connection indication is for the existing connection
    236     ** Check if the new destination role is acceptable
    237     */
    238     pcb = pan_get_pcb_by_handle (handle);
    239     if (pcb)
    240     {
    241         if (pan_cb.num_conns > 1 && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
    242         {
    243             /* There are connections other than this one
    244             ** so we cann't accept PANU role. Reject
    245             */
    246             PAN_TRACE_ERROR ("Dst UUID should be either GN or NAP only because there are other connections");
    247             BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
    248             return;
    249         }
    250 
    251         /* If it is already in connected state check for bridging status */
    252         if (pcb->con_state == PAN_STATE_CONNECTED)
    253         {
    254             PAN_TRACE_EVENT ("PAN Role changing New Src 0x%x Dst 0x%x",
    255                 remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
    256 
    257             pcb->prv_src_uuid = pcb->src_uuid;
    258             pcb->prv_dst_uuid = pcb->dst_uuid;
    259 
    260             if (pcb->src_uuid == UUID_SERVCLASS_NAP &&
    261                 local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP)
    262             {
    263                 /* Remove bridging */
    264                 if (pan_cb.pan_bridge_req_cb)
    265                     (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
    266             }
    267         }
    268         /* Set the latest active PAN role */
    269         pan_cb.active_role = req_role;
    270         pcb->src_uuid = local_uuid->uu.uuid16;
    271         pcb->dst_uuid = remote_uuid->uu.uuid16;
    272         BNEP_ConnectResp (handle, BNEP_SUCCESS);
    273         return;
    274     }
    275     else
    276     {
    277         /* If this a new connection and destination is PANU role and
    278         ** we already have a connection then reject the request.
    279         ** If we have a connection in PANU role then reject it
    280         */
    281         if (pan_cb.num_conns &&
    282             (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU ||
    283             pan_cb.active_role == PAN_ROLE_CLIENT))
    284         {
    285             PAN_TRACE_ERROR ("PAN already have a connection and can't be user");
    286             BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
    287             return;
    288         }
    289     }
    290 
    291     /* This is a new connection */
    292     PAN_TRACE_DEBUG ("New connection indication for handle %d", handle);
    293     pcb = pan_allocate_pcb (p_bda, handle);
    294     if (!pcb)
    295     {
    296         PAN_TRACE_ERROR ("PAN no control block for new connection");
    297         BNEP_ConnectResp (handle, BNEP_CONN_FAILED);
    298         return;
    299     }
    300 
    301     PAN_TRACE_EVENT ("PAN connection destination UUID is 0x%x", local_uuid->uu.uuid16);
    302     /* Set the latest active PAN role */
    303     pan_cb.active_role = req_role;
    304     pcb->src_uuid = local_uuid->uu.uuid16;
    305     pcb->dst_uuid = remote_uuid->uu.uuid16;
    306     pcb->con_state = PAN_STATE_CONN_START;
    307     pan_cb.num_conns++;
    308 
    309     BNEP_ConnectResp (handle, BNEP_SUCCESS);
    310     return;
    311 }
    312 
    313 
    314 /*******************************************************************************
    315 **
    316 ** Function         pan_connect_state_cb
    317 **
    318 ** Description      This function is registered with BNEP as connection state
    319 **                  change callback. BNEP will call this when the connection
    320 **                  is established successfully or terminated
    321 **
    322 ** Parameters:      handle      - handle for the connection given in the connection
    323 **                                      indication callback
    324 **                  rem_bda     - remote device bd addr
    325 **                  result      - indicates whether the connection is up or down
    326 **                                      BNEP_SUCCESS if the connection is up
    327 **                                      all other values indicates appropriate errors
    328 **                  is_role_change - flag to indicate that it is a role change
    329 **
    330 ** Returns          none
    331 **
    332 *******************************************************************************/
    333 void pan_connect_state_cb (UINT16 handle, BD_ADDR rem_bda, tBNEP_RESULT result, BOOLEAN is_role_change)
    334 {
    335     tPAN_CONN       *pcb;
    336     UINT8            peer_role;
    337     UNUSED(rem_bda);
    338 
    339     PAN_TRACE_EVENT ("pan_connect_state_cb - for handle %d, result %d", handle, result);
    340     pcb = pan_get_pcb_by_handle (handle);
    341     if (!pcb)
    342     {
    343         PAN_TRACE_ERROR ("PAN State change indication for wrong handle %d", handle);
    344         return;
    345     }
    346 
    347     /* If the connection is getting terminated remove bridging */
    348     if (result != BNEP_SUCCESS)
    349     {
    350         /* Inform the application that connection is down */
    351         if (pan_cb.pan_conn_state_cb)
    352             (*pan_cb.pan_conn_state_cb) (pcb->handle, pcb->rem_bda, result, is_role_change, PAN_ROLE_INACTIVE, PAN_ROLE_INACTIVE);
    353 
    354         /* Check if this failure is for role change only */
    355         if (pcb->con_state != PAN_STATE_CONNECTED &&
    356             (pcb->con_flags & PAN_FLAGS_CONN_COMPLETED))
    357         {
    358             /* restore the original values */
    359             PAN_TRACE_EVENT ("restoring the connection state to active");
    360             pcb->con_state = PAN_STATE_CONNECTED;
    361             pcb->con_flags &= (~PAN_FLAGS_CONN_COMPLETED);
    362 
    363             pcb->src_uuid = pcb->prv_src_uuid;
    364             pcb->dst_uuid = pcb->prv_dst_uuid;
    365             pan_cb.active_role = pan_cb.prv_active_role;
    366 
    367             if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb)
    368                 (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, TRUE);
    369 
    370             return;
    371         }
    372 
    373         if (pcb->con_state == PAN_STATE_CONNECTED)
    374         {
    375             /* If the connections destination role is NAP remove bridging */
    376             if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb)
    377                 (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
    378         }
    379 
    380         pan_cb.num_conns--;
    381         pan_release_pcb (pcb);
    382         return;
    383     }
    384 
    385     /* Requested destination role is */
    386     if (pcb->src_uuid == UUID_SERVCLASS_PANU)
    387         pan_cb.active_role = PAN_ROLE_CLIENT;
    388     else if (pcb->src_uuid == UUID_SERVCLASS_GN)
    389         pan_cb.active_role = PAN_ROLE_GN_SERVER;
    390     else
    391         pan_cb.active_role = PAN_ROLE_NAP_SERVER;
    392 
    393     if (pcb->dst_uuid == UUID_SERVCLASS_PANU)
    394         peer_role = PAN_ROLE_CLIENT;
    395     else if (pcb->dst_uuid == UUID_SERVCLASS_GN)
    396         peer_role = PAN_ROLE_GN_SERVER;
    397     else
    398         peer_role = PAN_ROLE_NAP_SERVER;
    399 
    400     pcb->con_state = PAN_STATE_CONNECTED;
    401 
    402     /* Inform the application that connection is down */
    403     if (pan_cb.pan_conn_state_cb)
    404         (*pan_cb.pan_conn_state_cb) (pcb->handle, pcb->rem_bda, PAN_SUCCESS, is_role_change, pan_cb.active_role, peer_role);
    405 
    406     /* Create bridge if the destination role is NAP */
    407     if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP)
    408     {
    409         PAN_TRACE_EVENT ("PAN requesting for bridge");
    410         (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, TRUE);
    411     }
    412 }
    413 
    414 
    415 /*******************************************************************************
    416 **
    417 ** Function         pan_data_ind_cb
    418 **
    419 ** Description      This function is registered with BNEP as data indication
    420 **                  callback. BNEP will call this when the peer sends any data
    421 **                  on this connection
    422 **
    423 ** Parameters:      handle      - handle for the connection
    424 **                  src         - source BD Addr
    425 **                  dst         - destination BD Addr
    426 **                  protocol    - Network protocol of the Eth packet
    427 **                  p_data      - pointer to the data
    428 **                  len         - length of the data
    429 **                  fw_ext_present - to indicate whether the data contains any
    430 **                                         extension headers before the payload
    431 **
    432 ** Returns          none
    433 **
    434 *******************************************************************************/
    435 void pan_data_ind_cb (UINT16 handle,
    436                       UINT8 *src,
    437                       UINT8 *dst,
    438                       UINT16 protocol,
    439                       UINT8 *p_data,
    440                       UINT16 len,
    441                       BOOLEAN ext)
    442 {
    443     tPAN_CONN       *pcb;
    444     UINT16          i;
    445     BOOLEAN         forward;
    446 
    447     /*
    448     ** Check the connection status
    449     ** If the destination address is MAC broadcast send on all links
    450     ** except on the one received
    451     ** If the destination uuid is for NAP send to host system also
    452     ** If the destination address is one of the devices connected
    453     ** send the packet to over that link
    454     ** If the destination address is unknown and destination uuid is NAP
    455     ** send it to the host system
    456     */
    457 
    458     PAN_TRACE_EVENT ("pan_data_ind_cb - for handle %d", handle);
    459     pcb = pan_get_pcb_by_handle (handle);
    460     if (!pcb)
    461     {
    462         PAN_TRACE_ERROR ("PAN Data indication for wrong handle %d", handle);
    463         return;
    464     }
    465 
    466     if (pcb->con_state != PAN_STATE_CONNECTED)
    467     {
    468         PAN_TRACE_ERROR ("PAN Data indication in wrong state %d for handle %d",
    469             pcb->con_state, handle);
    470         return;
    471     }
    472 
    473     /* Check if it is broadcast packet */
    474     if (dst[0] & 0x01)
    475     {
    476         PAN_TRACE_DEBUG ("PAN received broadcast packet on handle %d, src uuid 0x%x",
    477             handle, pcb->src_uuid);
    478         for (i=0; i<MAX_PAN_CONNS; i++)
    479         {
    480             if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
    481                 pan_cb.pcb[i].handle != handle &&
    482                 pcb->src_uuid == pan_cb.pcb[i].src_uuid)
    483             {
    484                 BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
    485             }
    486         }
    487 
    488         if (pan_cb.pan_data_ind_cb)
    489             (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, TRUE);
    490 
    491         return;
    492     }
    493 
    494     /* Check if it is for any other PAN connection */
    495     for (i=0; i<MAX_PAN_CONNS; i++)
    496     {
    497         if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
    498             pcb->src_uuid == pan_cb.pcb[i].src_uuid)
    499         {
    500             if (memcmp (pan_cb.pcb[i].rem_bda, dst, BD_ADDR_LEN) == 0)
    501             {
    502                 BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
    503                 return;
    504             }
    505         }
    506     }
    507 
    508    if (pcb->src_uuid == UUID_SERVCLASS_NAP)
    509        forward = TRUE;
    510    else
    511        forward = FALSE;
    512 
    513     /* Send it over the LAN or give it to host software */
    514     if (pan_cb.pan_data_ind_cb)
    515         (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward);
    516 
    517     return;
    518 }
    519 
    520 
    521 /*******************************************************************************
    522 **
    523 ** Function         pan_data_buf_ind_cb
    524 **
    525 ** Description      This function is registered with BNEP as data buffer indication
    526 **                  callback. BNEP will call this when the peer sends any data
    527 **                  on this connection. PAN is responsible to release the buffer
    528 **
    529 ** Parameters:      handle      - handle for the connection
    530 **                  src         - source BD Addr
    531 **                  dst         - destination BD Addr
    532 **                  protocol    - Network protocol of the Eth packet
    533 **                  p_buf       - pointer to the data buffer
    534 **                  ext         - to indicate whether the data contains any
    535 **                                         extension headers before the payload
    536 **
    537 ** Returns          none
    538 **
    539 *******************************************************************************/
    540 void pan_data_buf_ind_cb (UINT16 handle,
    541                           UINT8 *src,
    542                           UINT8 *dst,
    543                           UINT16 protocol,
    544                           BT_HDR *p_buf,
    545                           BOOLEAN ext)
    546 {
    547     tPAN_CONN       *pcb, *dst_pcb;
    548     tBNEP_RESULT    result;
    549     UINT16          i, len;
    550     UINT8           *p_data;
    551     BOOLEAN         forward = FALSE;
    552 
    553     /* Check if the connection is in right state */
    554     pcb = pan_get_pcb_by_handle (handle);
    555     if (!pcb)
    556     {
    557         PAN_TRACE_ERROR ("PAN Data buffer indication for wrong handle %d", handle);
    558         GKI_freebuf (p_buf);
    559         return;
    560     }
    561 
    562     if (pcb->con_state != PAN_STATE_CONNECTED)
    563     {
    564         PAN_TRACE_ERROR ("PAN Data indication in wrong state %d for handle %d",
    565             pcb->con_state, handle);
    566         GKI_freebuf (p_buf);
    567         return;
    568     }
    569 
    570     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
    571     len    = p_buf->len;
    572 
    573     PAN_TRACE_EVENT ("pan_data_buf_ind_cb - for handle %d, protocol 0x%x, length %d, ext %d",
    574         handle, protocol, len, ext);
    575 
    576    if (pcb->src_uuid == UUID_SERVCLASS_NAP)
    577        forward = TRUE;
    578    else
    579        forward = FALSE;
    580 
    581     /* Check if it is broadcast or multicast packet */
    582     if (pcb->src_uuid != UUID_SERVCLASS_PANU)
    583     {
    584         if (dst[0] & 0x01)
    585         {
    586             PAN_TRACE_DEBUG ("PAN received broadcast packet on handle %d, src uuid 0x%x",
    587                 handle, pcb->src_uuid);
    588             for (i=0; i<MAX_PAN_CONNS; i++)
    589             {
    590                 if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
    591                     pan_cb.pcb[i].handle != handle &&
    592                     pcb->src_uuid == pan_cb.pcb[i].src_uuid)
    593                 {
    594                     BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
    595                 }
    596             }
    597 
    598             if (pan_cb.pan_data_buf_ind_cb)
    599                 (*pan_cb.pan_data_buf_ind_cb) (pcb->handle, src, dst, protocol, p_buf, ext, forward);
    600             else if (pan_cb.pan_data_ind_cb)
    601             {
    602                 (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward);
    603                 GKI_freebuf (p_buf);
    604             }
    605 
    606             return;
    607         }
    608 
    609         /* Check if it is for any other PAN connection */
    610         dst_pcb = pan_get_pcb_by_addr (dst);
    611         if (dst_pcb)
    612         {
    613             PAN_TRACE_EVENT ("pan_data_buf_ind_cb - destination PANU found and sending the data");
    614             result = BNEP_WriteBuf (dst_pcb->handle, dst, p_buf, protocol, src, ext);
    615             if (result != BNEP_SUCCESS && result != BNEP_IGNORE_CMD)
    616                 PAN_TRACE_ERROR ("Failed to write data for PAN connection handle %d", dst_pcb->handle);
    617             return;
    618         }
    619     }
    620 
    621     /* Send it over the LAN or give it to host software */
    622     if (pan_cb.pan_data_buf_ind_cb)
    623         (*pan_cb.pan_data_buf_ind_cb) (pcb->handle, src, dst, protocol, p_buf, ext, forward);
    624     else if (pan_cb.pan_data_ind_cb)
    625     {
    626         (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward);
    627         GKI_freebuf (p_buf);
    628     }
    629     else
    630         GKI_freebuf (p_buf);
    631 
    632     return;
    633 }
    634 
    635 /*******************************************************************************
    636 **
    637 ** Function         pan_proto_filt_ind_cb
    638 **
    639 ** Description      This function is registered with BNEP to receive tx data
    640 **					flow status
    641 **
    642 ** Parameters:      handle      - handle for the connection
    643 **					event       - flow status
    644 **
    645 ** Returns          none
    646 **
    647 *******************************************************************************/
    648 void pan_tx_data_flow_cb (UINT16 handle,
    649                             tBNEP_RESULT  event)
    650 {
    651 
    652     if (pan_cb.pan_tx_data_flow_cb)
    653         (*pan_cb.pan_tx_data_flow_cb) (handle, event);
    654 
    655     return;
    656 }
    657 
    658 /*******************************************************************************
    659 **
    660 ** Function         pan_proto_filt_ind_cb
    661 **
    662 ** Description      This function is registered with BNEP as proto filter indication
    663 **                  callback. BNEP will call this when the peer sends any protocol
    664 **                  filter set for the connection or to indicate the result of the
    665 **                  protocol filter set by the local device
    666 **
    667 ** Parameters:      handle      - handle for the connection
    668 **                  indication  - TRUE if this is indication
    669 **                                FALSE if it is called to give the result of local
    670 **                                      device protocol filter set
    671 **                  result      - This gives the result of the filter set operation
    672 **                  num_filters - number of filters set by the peer device
    673 **                  p_filters   - pointer to the filters set by the peer device
    674 **
    675 ** Returns          none
    676 **
    677 *******************************************************************************/
    678 void pan_proto_filt_ind_cb (UINT16 handle,
    679                             BOOLEAN indication,
    680                             tBNEP_RESULT result,
    681                             UINT16 num_filters,
    682                             UINT8 *p_filters)
    683 {
    684 #if (defined (BNEP_SUPPORTS_PROT_FILTERS) && BNEP_SUPPORTS_PROT_FILTERS == TRUE)
    685     PAN_TRACE_EVENT ("pan_proto_filt_ind_cb - called for handle %d with ind %d, result %d, num %d",
    686                             handle, indication, result, num_filters);
    687 
    688     if (pan_cb.pan_pfilt_ind_cb)
    689         (*pan_cb.pan_pfilt_ind_cb) (handle, indication, result, num_filters, p_filters);
    690 #endif
    691 
    692     return;
    693 }
    694 
    695 
    696 /*******************************************************************************
    697 **
    698 ** Function         pan_mcast_filt_ind_cb
    699 **
    700 ** Description      This function is registered with BNEP as mcast filter indication
    701 **                  callback. BNEP will call this when the peer sends any multicast
    702 **                  filter set for the connection or to indicate the result of the
    703 **                  multicast filter set by the local device
    704 **
    705 ** Parameters:      handle      - handle for the connection
    706 **                  indication  - TRUE if this is indication
    707 **                                FALSE if it is called to give the result of local
    708 **                                      device multicast filter set
    709 **                  result      - This gives the result of the filter set operation
    710 **                  num_filters - number of filters set by the peer device
    711 **                  p_filters   - pointer to the filters set by the peer device
    712 **
    713 ** Returns          none
    714 **
    715 *******************************************************************************/
    716 void pan_mcast_filt_ind_cb (UINT16 handle,
    717                             BOOLEAN indication,
    718                             tBNEP_RESULT result,
    719                             UINT16 num_filters,
    720                             UINT8 *p_filters)
    721 {
    722 #if (defined (BNEP_SUPPORTS_MULTI_FILTERS) && BNEP_SUPPORTS_MULTI_FILTERS == TRUE)
    723     PAN_TRACE_EVENT ("pan_mcast_filt_ind_cb - called for handle %d with ind %d, result %d, num %d",
    724                             handle, indication, result, num_filters);
    725 
    726     if (pan_cb.pan_mfilt_ind_cb)
    727         (*pan_cb.pan_mfilt_ind_cb) (handle, indication, result, num_filters, p_filters);
    728 #endif
    729 
    730     return;
    731 }
    732 
    733