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