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 #include "btm_api.h"
     37 #include "bta_sys.h"
     38 
     39 
     40 /*******************************************************************************
     41 **
     42 ** Function         PAN_Register
     43 **
     44 ** Description      This function is called by the application to register
     45 **                  its callbacks with PAN profile. The application then
     46 **                  should set the PAN role explicitly.
     47 **
     48 ** Parameters:      p_register - contains all callback function pointers
     49 **
     50 **
     51 ** Returns          none
     52 **
     53 *******************************************************************************/
     54 void PAN_Register (tPAN_REGISTER *p_register)
     55 {
     56     BTM_SetDiscoverability (BTM_GENERAL_DISCOVERABLE, 0, 0);
     57     BTM_SetConnectability (BTM_CONNECTABLE, 0, 0);
     58 
     59     pan_register_with_bnep ();
     60 
     61     if (!p_register)
     62         return;
     63 
     64     pan_cb.pan_conn_state_cb    = p_register->pan_conn_state_cb;
     65     pan_cb.pan_bridge_req_cb    = p_register->pan_bridge_req_cb;
     66     pan_cb.pan_data_buf_ind_cb  = p_register->pan_data_buf_ind_cb;
     67     pan_cb.pan_data_ind_cb      = p_register->pan_data_ind_cb;
     68     pan_cb.pan_pfilt_ind_cb     = p_register->pan_pfilt_ind_cb;
     69     pan_cb.pan_mfilt_ind_cb     = p_register->pan_mfilt_ind_cb;
     70     pan_cb.pan_tx_data_flow_cb  = p_register->pan_tx_data_flow_cb;
     71 
     72     return;
     73 }
     74 
     75 
     76 
     77 /*******************************************************************************
     78 **
     79 ** Function         PAN_Deregister
     80 **
     81 ** Description      This function is called by the application to de-register
     82 **                  its callbacks with PAN profile. This will make the PAN to
     83 **                  become inactive. This will deregister PAN services from SDP
     84 **                  and close all active connections
     85 **
     86 ** Parameters:      none
     87 **
     88 **
     89 ** Returns          none
     90 **
     91 *******************************************************************************/
     92 void PAN_Deregister (void)
     93 {
     94     pan_cb.pan_bridge_req_cb    = NULL;
     95     pan_cb.pan_data_buf_ind_cb  = NULL;
     96     pan_cb.pan_data_ind_cb      = NULL;
     97     pan_cb.pan_conn_state_cb    = NULL;
     98     pan_cb.pan_pfilt_ind_cb     = NULL;
     99     pan_cb.pan_mfilt_ind_cb     = NULL;
    100 
    101     PAN_SetRole (PAN_ROLE_INACTIVE, NULL, NULL, NULL, NULL);
    102     BNEP_Deregister ();
    103 
    104     return;
    105 }
    106 
    107 
    108 
    109 
    110 /*******************************************************************************
    111 **
    112 ** Function         PAN_SetRole
    113 **
    114 ** Description      This function is called by the application to set the PAN
    115 **                  profile role. This should be called after PAN_Register.
    116 **                  This can be called any time to change the PAN role
    117 **
    118 ** Parameters:      role        - is bit map of roles to be active
    119 **                                      PAN_ROLE_CLIENT is for PANU role
    120 **                                      PAN_ROLE_GN_SERVER is for GN role
    121 **                                      PAN_ROLE_NAP_SERVER is for NAP role
    122 **                  sec_mask    - Security mask for different roles
    123 **                                      It is array of UINT8. The byte represent the
    124 **                                      security for roles PANU, GN and NAP in order
    125 **                  p_user_name - Service name for PANU role
    126 **                  p_gn_name   - Service name for GN role
    127 **                  p_nap_name  - Service name for NAP role
    128 **                                      Can be NULL if user wants it to be default
    129 **
    130 ** Returns          PAN_SUCCESS     - if the role is set successfully
    131 **                  PAN_FAILURE     - if the role is not valid
    132 **
    133 *******************************************************************************/
    134 tPAN_RESULT PAN_SetRole (UINT8 role,
    135                          UINT8 *sec_mask,
    136                          char *p_user_name,
    137                          char *p_gn_name,
    138                          char *p_nap_name)
    139 {
    140     char                *p_desc;
    141     UINT8               security[3] = {PAN_PANU_SECURITY_LEVEL,
    142                                        PAN_GN_SECURITY_LEVEL,
    143                                        PAN_NAP_SECURITY_LEVEL};
    144     UINT8               *p_sec;
    145 
    146     /* If the role is not a valid combination reject it */
    147     if ((!(role & (PAN_ROLE_CLIENT | PAN_ROLE_GN_SERVER | PAN_ROLE_NAP_SERVER))) &&
    148         role != PAN_ROLE_INACTIVE)
    149     {
    150         PAN_TRACE_ERROR ("PAN role %d is invalid", role);
    151         return PAN_FAILURE;
    152     }
    153 
    154     /* If the current active role is same as the role being set do nothing */
    155     if (pan_cb.role == role)
    156     {
    157         PAN_TRACE_EVENT ("PAN role already was set to: %d", role);
    158         return PAN_SUCCESS;
    159     }
    160 
    161     if (!sec_mask)
    162         p_sec = security;
    163     else
    164         p_sec = sec_mask;
    165 
    166     /* Register all the roles with SDP */
    167     PAN_TRACE_API ("PAN_SetRole() called with role 0x%x", role);
    168 #if (defined (PAN_SUPPORTS_ROLE_NAP) && PAN_SUPPORTS_ROLE_NAP == TRUE)
    169     /* Check the service name */
    170     if ((p_nap_name == NULL) || (*p_nap_name == 0))
    171         p_nap_name = PAN_NAP_DEFAULT_SERVICE_NAME;
    172 
    173     if (role & PAN_ROLE_NAP_SERVER)
    174     {
    175         /* Registering for NAP service with SDP */
    176         p_desc = PAN_NAP_DEFAULT_DESCRIPTION;
    177 
    178         if (pan_cb.pan_nap_sdp_handle != 0)
    179             SDP_DeleteRecord (pan_cb.pan_nap_sdp_handle);
    180 
    181         pan_cb.pan_nap_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_NAP, p_sec[2], p_nap_name, p_desc);
    182 // btla-specific ++
    183         bta_sys_add_uuid(UUID_SERVCLASS_NAP);
    184 // btla-specific --
    185     }
    186     /* If the NAP role is already active and now being cleared delete the record */
    187     else if (pan_cb.role & PAN_ROLE_NAP_SERVER)
    188     {
    189         if (pan_cb.pan_nap_sdp_handle != 0)
    190         {
    191             SDP_DeleteRecord (pan_cb.pan_nap_sdp_handle);
    192             pan_cb.pan_nap_sdp_handle = 0;
    193 // btla-specific ++
    194             bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
    195 // btla-specific --
    196         }
    197     }
    198 #endif
    199 
    200 #if (defined (PAN_SUPPORTS_ROLE_GN) && PAN_SUPPORTS_ROLE_GN == TRUE)
    201     /* Check the service name */
    202     if ((p_gn_name == NULL) || (*p_gn_name == 0))
    203         p_gn_name = PAN_GN_DEFAULT_SERVICE_NAME;
    204 
    205     if (role & PAN_ROLE_GN_SERVER)
    206     {
    207         /* Registering for GN service with SDP */
    208         p_desc = PAN_GN_DEFAULT_DESCRIPTION;
    209 
    210         if (pan_cb.pan_gn_sdp_handle != 0)
    211             SDP_DeleteRecord (pan_cb.pan_gn_sdp_handle);
    212 
    213         pan_cb.pan_gn_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_GN, p_sec[1], p_gn_name, p_desc);
    214 // btla-specific ++
    215         bta_sys_add_uuid(UUID_SERVCLASS_GN);
    216 // btla-specific --
    217     }
    218     /* If the GN role is already active and now being cleared delete the record */
    219     else if (pan_cb.role & PAN_ROLE_GN_SERVER)
    220     {
    221         if (pan_cb.pan_gn_sdp_handle != 0)
    222         {
    223             SDP_DeleteRecord (pan_cb.pan_gn_sdp_handle);
    224             pan_cb.pan_gn_sdp_handle = 0;
    225 // btla-specific ++
    226             bta_sys_remove_uuid(UUID_SERVCLASS_GN);
    227 // btla-specific --
    228         }
    229     }
    230 #endif
    231 
    232 #if (defined (PAN_SUPPORTS_ROLE_PANU) && PAN_SUPPORTS_ROLE_PANU == TRUE)
    233     /* Check the service name */
    234     if ((p_user_name == NULL) || (*p_user_name == 0))
    235         p_user_name = PAN_PANU_DEFAULT_SERVICE_NAME;
    236 
    237     if (role & PAN_ROLE_CLIENT)
    238     {
    239         /* Registering for PANU service with SDP */
    240         p_desc = PAN_PANU_DEFAULT_DESCRIPTION;
    241         if (pan_cb.pan_user_sdp_handle != 0)
    242             SDP_DeleteRecord (pan_cb.pan_user_sdp_handle);
    243 
    244         pan_cb.pan_user_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_PANU, p_sec[0], p_user_name, p_desc);
    245 // btla-specific ++
    246         bta_sys_add_uuid(UUID_SERVCLASS_PANU);
    247 // btla-specific --
    248     }
    249     /* If the PANU role is already active and now being cleared delete the record */
    250     else if (pan_cb.role & PAN_ROLE_CLIENT)
    251     {
    252         if (pan_cb.pan_user_sdp_handle != 0)
    253         {
    254             SDP_DeleteRecord (pan_cb.pan_user_sdp_handle);
    255             pan_cb.pan_user_sdp_handle = 0;
    256 // btla-specific ++
    257             bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
    258 // btla-specific --
    259         }
    260     }
    261 #endif
    262 
    263     /* Check if it is a shutdown request */
    264     if (role == PAN_ROLE_INACTIVE)
    265         pan_close_all_connections ();
    266 
    267     pan_cb.role = role;
    268     PAN_TRACE_EVENT ("PAN role set to: %d", role);
    269     return PAN_SUCCESS;
    270 }
    271 
    272 
    273 
    274 /*******************************************************************************
    275 **
    276 ** Function         PAN_Connect
    277 **
    278 ** Description      This function is called by the application to initiate a
    279 **                  connection to the remote device
    280 **
    281 ** Parameters:      rem_bda     - BD Addr of the remote device
    282 **                  src_role    - Role of the local device for the connection
    283 **                  dst_role    - Role of the remote device for the connection
    284 **                                      PAN_ROLE_CLIENT is for PANU role
    285 **                                      PAN_ROLE_GN_SERVER is for GN role
    286 **                                      PAN_ROLE_NAP_SERVER is for NAP role
    287 **                  *handle     - Pointer for returning Handle to the connection
    288 **
    289 ** Returns          PAN_SUCCESS      - if the connection is initiated successfully
    290 **                  PAN_NO_RESOURCES - resources are not sufficent
    291 **                  PAN_FAILURE      - if the connection cannot be initiated
    292 **                                           this can be because of the combination of
    293 **                                           src and dst roles may not be valid or
    294 **                                           allowed at that point of time
    295 **
    296 *******************************************************************************/
    297 tPAN_RESULT PAN_Connect (BD_ADDR rem_bda, UINT8 src_role, UINT8 dst_role, UINT16 *handle)
    298 {
    299     tPAN_CONN       *pcb;
    300     tBNEP_RESULT    result;
    301     tBT_UUID        src_uuid, dst_uuid;
    302     UINT32 mx_chan_id;
    303 
    304     /*
    305     ** Initialize the handle so that in case of failure return values
    306     ** the profile will not get confused
    307     */
    308     *handle = BNEP_INVALID_HANDLE;
    309 
    310     /* Check if PAN is active or not */
    311     if (!(pan_cb.role & src_role))
    312     {
    313         PAN_TRACE_ERROR ("PAN is not active for the role %d", src_role);
    314         return PAN_FAILURE;
    315     }
    316 
    317     /* Validate the parameters before proceeding */
    318     if ((src_role != PAN_ROLE_CLIENT && src_role != PAN_ROLE_GN_SERVER && src_role != PAN_ROLE_NAP_SERVER) ||
    319         (dst_role != PAN_ROLE_CLIENT && dst_role != PAN_ROLE_GN_SERVER && dst_role != PAN_ROLE_NAP_SERVER))
    320     {
    321         PAN_TRACE_ERROR ("Either source %d or destination role %d is invalid", src_role, dst_role);
    322         return PAN_FAILURE;
    323     }
    324 
    325     /* Check if connection exists for this remote device */
    326     pcb = pan_get_pcb_by_addr (rem_bda);
    327 
    328     /* If we are PANU for this role validate destination role */
    329     if (src_role == PAN_ROLE_CLIENT)
    330     {
    331         if ((pan_cb.num_conns > 1) || (pan_cb.num_conns && (!pcb)))
    332         {
    333             /*
    334             ** If the request is not for existing connection reject it
    335             ** because if there is already a connection we cannot accept
    336             ** another connection in PANU role
    337             */
    338             PAN_TRACE_ERROR ("Cannot make PANU connections when there are more than one connection");
    339             return PAN_INVALID_SRC_ROLE;
    340         }
    341 
    342         src_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
    343         if (dst_role == PAN_ROLE_CLIENT)
    344         {
    345             dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
    346         }
    347         else if (dst_role == PAN_ROLE_GN_SERVER)
    348         {
    349             dst_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
    350         }
    351         else
    352         {
    353             dst_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
    354         }
    355         mx_chan_id = dst_uuid.uu.uuid16;
    356     }
    357     /* If destination is PANU role validate source role */
    358     else if (dst_role == PAN_ROLE_CLIENT)
    359     {
    360         if (pan_cb.num_conns && pan_cb.active_role == PAN_ROLE_CLIENT && !pcb)
    361         {
    362             PAN_TRACE_ERROR ("Device already have a connection in PANU role");
    363             return PAN_INVALID_SRC_ROLE;
    364         }
    365 
    366         dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
    367         if (src_role == PAN_ROLE_GN_SERVER)
    368         {
    369             src_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
    370         }
    371         else
    372         {
    373             src_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
    374         }
    375         mx_chan_id = src_uuid.uu.uuid16;
    376     }
    377     /* The role combination is not valid */
    378     else
    379     {
    380         PAN_TRACE_ERROR ("Source %d and Destination roles %d are not valid combination",
    381             src_role, dst_role);
    382         return PAN_FAILURE;
    383     }
    384 
    385     /* Allocate control block and initiate connection */
    386     if (!pcb)
    387         pcb = pan_allocate_pcb (rem_bda, BNEP_INVALID_HANDLE);
    388     if (!pcb)
    389     {
    390         PAN_TRACE_ERROR ("PAN Connection failed because of no resources");
    391         return PAN_NO_RESOURCES;
    392     }
    393     BTM_SetOutService(rem_bda, BTM_SEC_SERVICE_BNEP_PANU, mx_chan_id);
    394 
    395     PAN_TRACE_API ("PAN_Connect() for BD Addr %x.%x.%x.%x.%x.%x",
    396         rem_bda[0], rem_bda[1], rem_bda[2], rem_bda[3], rem_bda[4], rem_bda[5]);
    397     if (pcb->con_state == PAN_STATE_IDLE)
    398     {
    399         pan_cb.num_conns++;
    400     }
    401     else if (pcb->con_state == PAN_STATE_CONNECTED)
    402     {
    403         pcb->con_flags |= PAN_FLAGS_CONN_COMPLETED;
    404     }
    405     else
    406         /* PAN connection is still in progress */
    407         return PAN_WRONG_STATE;
    408 
    409     pcb->con_state = PAN_STATE_CONN_START;
    410     pcb->prv_src_uuid = pcb->src_uuid;
    411     pcb->prv_dst_uuid = pcb->dst_uuid;
    412 
    413     pcb->src_uuid     = src_uuid.uu.uuid16;
    414     pcb->dst_uuid     = dst_uuid.uu.uuid16;
    415 
    416     src_uuid.len      = 2;
    417     dst_uuid.len      = 2;
    418 
    419     result = BNEP_Connect (rem_bda, &src_uuid, &dst_uuid, &(pcb->handle));
    420     if (result != BNEP_SUCCESS)
    421     {
    422         pan_release_pcb (pcb);
    423         return result;
    424     }
    425 
    426     PAN_TRACE_DEBUG ("PAN_Connect() current active role set to %d", src_role);
    427     pan_cb.prv_active_role = pan_cb.active_role;
    428     pan_cb.active_role = src_role;
    429     *handle = pcb->handle;
    430     return PAN_SUCCESS;
    431 }
    432 
    433 
    434 
    435 
    436 /*******************************************************************************
    437 **
    438 ** Function         PAN_Disconnect
    439 **
    440 ** Description      This is used to disconnect the connection
    441 **
    442 ** Parameters:      handle           - handle for the connection
    443 **
    444 ** Returns          PAN_SUCCESS      - if the connection is closed successfully
    445 **                  PAN_FAILURE      - if the connection is not found or
    446 **                                           there is an error in disconnecting
    447 **
    448 *******************************************************************************/
    449 tPAN_RESULT PAN_Disconnect (UINT16 handle)
    450 {
    451     tPAN_CONN       *pcb;
    452     tBNEP_RESULT    result;
    453 
    454     /* Check if the connection exists */
    455     pcb = pan_get_pcb_by_handle (handle);
    456     if(!pcb)
    457     {
    458         PAN_TRACE_ERROR ("PAN connection not found for the handle %d", handle);
    459         return PAN_FAILURE;
    460     }
    461 
    462     result = BNEP_Disconnect (pcb->handle);
    463     if (pcb->con_state != PAN_STATE_IDLE)
    464         pan_cb.num_conns--;
    465 
    466     if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP)
    467         (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
    468 
    469     pan_release_pcb (pcb);
    470 
    471     if (result != BNEP_SUCCESS)
    472     {
    473         PAN_TRACE_EVENT ("Error in closing PAN connection");
    474         return PAN_FAILURE;
    475     }
    476 
    477     PAN_TRACE_EVENT ("PAN connection closed");
    478     return PAN_SUCCESS;
    479 }
    480 
    481 
    482 /*******************************************************************************
    483 **
    484 ** Function         PAN_Write
    485 **
    486 ** Description      This sends data over the PAN connections. If this is called
    487 **                  on GN or NAP side and the packet is multicast or broadcast
    488 **                  it will be sent on all the links. Otherwise the correct link
    489 **                  is found based on the destination address and forwarded on it.
    490 **
    491 ** Parameters:      handle   - handle for the connection
    492 **                  dst      - MAC or BD Addr of the destination device
    493 **                  src      - MAC or BD Addr of the source who sent this packet
    494 **                  protocol - protocol of the ethernet packet like IP or ARP
    495 **                  p_data   - pointer to the data
    496 **                  len      - length of the data
    497 **                  ext      - to indicate that extension headers present
    498 **
    499 ** Returns          PAN_SUCCESS       - if the data is sent successfully
    500 **                  PAN_FAILURE       - if the connection is not found or
    501 **                                           there is an error in sending data
    502 **
    503 *******************************************************************************/
    504 tPAN_RESULT PAN_Write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, UINT8 *p_data, UINT16 len, BOOLEAN ext)
    505 {
    506     BT_HDR *buffer;
    507 
    508     if (pan_cb.role == PAN_ROLE_INACTIVE || !pan_cb.num_conns) {
    509         PAN_TRACE_ERROR("%s PAN is not active, data write failed.", __func__);
    510         return PAN_FAILURE;
    511     }
    512 
    513     // If the packet is broadcast or multicast, we're going to have to create
    514     // a copy of the packet for each connection. We can save one extra copy
    515     // by fast-pathing here and calling BNEP_Write instead of placing the packet
    516     // in a BT_HDR buffer, calling BNEP_Write, and then freeing the buffer.
    517     if (dst[0] & 0x01) {
    518         int i;
    519         for (i = 0; i < MAX_PAN_CONNS; ++i) {
    520             if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
    521                 BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
    522         }
    523         return PAN_SUCCESS;
    524     }
    525 
    526     buffer = (BT_HDR *)GKI_getpoolbuf(PAN_POOL_ID);
    527     if (!buffer) {
    528         PAN_TRACE_ERROR("%s unable to acquire buffer from pool.", __func__);
    529         return PAN_NO_RESOURCES;
    530     }
    531 
    532     buffer->len = len;
    533     buffer->offset = PAN_MINIMUM_OFFSET;
    534     memcpy((UINT8 *)buffer + sizeof(BT_HDR) + buffer->offset, p_data, buffer->len);
    535 
    536     return PAN_WriteBuf(handle, dst, src, protocol, buffer, ext);
    537 }
    538 
    539 
    540 /*******************************************************************************
    541 **
    542 ** Function         PAN_WriteBuf
    543 **
    544 ** Description      This sends data over the PAN connections. If this is called
    545 **                  on GN or NAP side and the packet is multicast or broadcast
    546 **                  it will be sent on all the links. Otherwise the correct link
    547 **                  is found based on the destination address and forwarded on it
    548 **                  If the return value is not PAN_SUCCESS the application should
    549 **                  take care of releasing the message buffer
    550 **
    551 ** Parameters:      handle   - handle for the connection
    552 **                  dst      - MAC or BD Addr of the destination device
    553 **                  src      - MAC or BD Addr of the source who sent this packet
    554 **                  protocol - protocol of the ethernet packet like IP or ARP
    555 **                  p_buf    - pointer to the data buffer
    556 **                  ext      - to indicate that extension headers present
    557 **
    558 ** Returns          PAN_SUCCESS       - if the data is sent successfully
    559 **                  PAN_FAILURE       - if the connection is not found or
    560 **                                           there is an error in sending data
    561 **
    562 *******************************************************************************/
    563 tPAN_RESULT PAN_WriteBuf (UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, BT_HDR *p_buf, BOOLEAN ext)
    564 {
    565     tPAN_CONN       *pcb;
    566     UINT16          i;
    567     tBNEP_RESULT    result;
    568 
    569     if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
    570     {
    571         PAN_TRACE_ERROR ("PAN is not active Data write failed");
    572         GKI_freebuf (p_buf);
    573         return PAN_FAILURE;
    574     }
    575 
    576     /* Check if it is broadcast or multicast packet */
    577     if (dst[0] & 0x01)
    578     {
    579         UINT8 *data = (UINT8 *)p_buf + sizeof(BT_HDR) + p_buf->offset;
    580         for (i = 0; i < MAX_PAN_CONNS; ++i) {
    581             if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
    582                 BNEP_Write(pan_cb.pcb[i].handle, dst, data, p_buf->len, protocol, src, ext);
    583         }
    584         GKI_freebuf(p_buf);
    585         return PAN_SUCCESS;
    586     }
    587 
    588     /* Check if the data write is on PANU side */
    589     if (pan_cb.active_role == PAN_ROLE_CLIENT)
    590     {
    591         /* Data write is on PANU connection */
    592         for (i=0; i<MAX_PAN_CONNS; i++)
    593         {
    594             if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
    595                 pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU)
    596                 break;
    597         }
    598 
    599         if (i == MAX_PAN_CONNS)
    600         {
    601             PAN_TRACE_ERROR ("PAN Don't have any user connections");
    602             GKI_freebuf (p_buf);
    603             return PAN_FAILURE;
    604         }
    605 
    606         result = BNEP_WriteBuf (pan_cb.pcb[i].handle, dst, p_buf, protocol, src, ext);
    607         if (result == BNEP_IGNORE_CMD)
    608         {
    609             PAN_TRACE_DEBUG ("PAN ignored data write for PANU connection");
    610             return result;
    611         }
    612         else if (result != BNEP_SUCCESS)
    613         {
    614             PAN_TRACE_ERROR ("PAN failed to write data for the PANU connection");
    615             return result;
    616         }
    617 
    618         PAN_TRACE_DEBUG ("PAN successfully wrote data for the PANU connection");
    619         return PAN_SUCCESS;
    620     }
    621 
    622     /* findout to which connection the data is meant for */
    623     pcb = pan_get_pcb_by_handle (handle);
    624     if (!pcb)
    625     {
    626         PAN_TRACE_ERROR ("PAN Buf write for wrong handle");
    627         GKI_freebuf (p_buf);
    628         return PAN_FAILURE;
    629     }
    630 
    631     if (pcb->con_state != PAN_STATE_CONNECTED)
    632     {
    633         PAN_TRACE_ERROR ("PAN Buf write when conn is not active");
    634         GKI_freebuf (p_buf);
    635         return PAN_FAILURE;
    636     }
    637 
    638     result = BNEP_WriteBuf (pcb->handle, dst, p_buf, protocol, src, ext);
    639     if (result == BNEP_IGNORE_CMD)
    640     {
    641         PAN_TRACE_DEBUG ("PAN ignored data buf write to PANU");
    642         return result;
    643     }
    644     else if (result != BNEP_SUCCESS)
    645     {
    646         PAN_TRACE_ERROR ("PAN failed to send data buf to the PANU");
    647         return result;
    648     }
    649 
    650     PAN_TRACE_DEBUG ("PAN successfully sent data buf to the PANU");
    651     return PAN_SUCCESS;
    652 }
    653 
    654 
    655 /*******************************************************************************
    656 **
    657 ** Function         PAN_SetProtocolFilters
    658 **
    659 ** Description      This function is used to set protocol filters on the peer
    660 **
    661 ** Parameters:      handle      - handle for the connection
    662 **                  num_filters - number of protocol filter ranges
    663 **                  start       - array of starting protocol numbers
    664 **                  end         - array of ending protocol numbers
    665 **
    666 **
    667 ** Returns          PAN_SUCCESS        if protocol filters are set successfully
    668 **                  PAN_FAILURE        if connection not found or error in setting
    669 **
    670 *******************************************************************************/
    671 tPAN_RESULT PAN_SetProtocolFilters (UINT16 handle,
    672                                     UINT16 num_filters,
    673                                     UINT16 *p_start_array,
    674                                     UINT16 *p_end_array)
    675 {
    676     tPAN_CONN       *pcb;
    677     tPAN_RESULT     result;
    678 
    679     /* Check if the connection exists */
    680     pcb = pan_get_pcb_by_handle (handle);
    681     if(!pcb)
    682     {
    683         PAN_TRACE_ERROR ("PAN connection not found for the handle %d", handle);
    684         return PAN_FAILURE;
    685     }
    686 
    687     result = BNEP_SetProtocolFilters (pcb->handle, num_filters, p_start_array, p_end_array);
    688     if (result != BNEP_SUCCESS)
    689     {
    690         PAN_TRACE_ERROR ("PAN failed to set protocol filters for handle %d", handle);
    691         return result;
    692     }
    693 
    694     PAN_TRACE_API ("PAN successfully sent protocol filters for handle %d", handle);
    695     return PAN_SUCCESS;
    696 }
    697 
    698 
    699 
    700 /*******************************************************************************
    701 **
    702 ** Function         PAN_SetMulticastFilters
    703 **
    704 ** Description      This function is used to set multicast filters on the peer
    705 **
    706 ** Parameters:      handle      - handle for the connection
    707 **                  num_filters - number of multicast filter ranges
    708 **                  start       - array of starting multicast filter addresses
    709 **                  end         - array of ending multicast filter addresses
    710 **
    711 **
    712 ** Returns          PAN_SUCCESS        if multicast filters are set successfully
    713 **                  PAN_FAILURE        if connection not found or error in setting
    714 **
    715 *******************************************************************************/
    716 tBNEP_RESULT PAN_SetMulticastFilters (UINT16 handle,
    717                                       UINT16 num_mcast_filters,
    718                                       UINT8 *p_start_array,
    719                                       UINT8 *p_end_array)
    720 {
    721     tPAN_CONN       *pcb;
    722     tPAN_RESULT     result;
    723 
    724     /* Check if the connection exists */
    725     pcb = pan_get_pcb_by_handle (handle);
    726     if(!pcb)
    727     {
    728         PAN_TRACE_ERROR ("PAN connection not found for the handle %d", handle);
    729         return PAN_FAILURE;
    730     }
    731 
    732     result = BNEP_SetMulticastFilters (pcb->handle,
    733                             num_mcast_filters, p_start_array, p_end_array);
    734     if (result != BNEP_SUCCESS)
    735     {
    736         PAN_TRACE_ERROR ("PAN failed to set multicast filters for handle %d", handle);
    737         return result;
    738     }
    739 
    740     PAN_TRACE_API ("PAN successfully sent multicast filters for handle %d", handle);
    741     return PAN_SUCCESS;
    742 }
    743 
    744 
    745 /*******************************************************************************
    746 **
    747 ** Function         PAN_SetTraceLevel
    748 **
    749 ** Description      This function sets the trace level for PAN. If called with
    750 **                  a value of 0xFF, it simply reads the current trace level.
    751 **
    752 ** Returns          the new (current) trace level
    753 **
    754 *******************************************************************************/
    755 UINT8 PAN_SetTraceLevel (UINT8 new_level)
    756 {
    757     if (new_level != 0xFF)
    758         pan_cb.trace_level = new_level;
    759     else
    760         pan_dump_status ();
    761 
    762     return (pan_cb.trace_level);
    763 }
    764 
    765 /*******************************************************************************
    766 **
    767 ** Function         PAN_Init
    768 **
    769 ** Description      This function initializes the PAN module variables
    770 **
    771 ** Parameters:      none
    772 **
    773 ** Returns          none
    774 **
    775 *******************************************************************************/
    776 void PAN_Init (void)
    777 {
    778     memset (&pan_cb, 0, sizeof (tPAN_CB));
    779 
    780 #if defined(PAN_INITIAL_TRACE_LEVEL)
    781     pan_cb.trace_level = PAN_INITIAL_TRACE_LEVEL;
    782 #else
    783     pan_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
    784 #endif
    785 }
    786 
    787 
    788