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     UINT8           service_id;
    303     UINT32 mx_chan_id;
    304 
    305     /*
    306     ** Initialize the handle so that in case of failure return values
    307     ** the profile will not get confused
    308     */
    309     *handle = BNEP_INVALID_HANDLE;
    310 
    311     /* Check if PAN is active or not */
    312     if (!(pan_cb.role & src_role))
    313     {
    314         PAN_TRACE_ERROR ("PAN is not active for the role %d", src_role);
    315         return PAN_FAILURE;
    316     }
    317 
    318     /* Validate the parameters before proceeding */
    319     if ((src_role != PAN_ROLE_CLIENT && src_role != PAN_ROLE_GN_SERVER && src_role != PAN_ROLE_NAP_SERVER) ||
    320         (dst_role != PAN_ROLE_CLIENT && dst_role != PAN_ROLE_GN_SERVER && dst_role != PAN_ROLE_NAP_SERVER))
    321     {
    322         PAN_TRACE_ERROR ("Either source %d or destination role %d is invalid", src_role, dst_role);
    323         return PAN_FAILURE;
    324     }
    325 
    326     /* Check if connection exists for this remote device */
    327     pcb = pan_get_pcb_by_addr (rem_bda);
    328 
    329     /* If we are PANU for this role validate destination role */
    330     if (src_role == PAN_ROLE_CLIENT)
    331     {
    332         if ((pan_cb.num_conns > 1) || (pan_cb.num_conns && (!pcb)))
    333         {
    334             /*
    335             ** If the request is not for existing connection reject it
    336             ** because if there is already a connection we cannot accept
    337             ** another connection in PANU role
    338             */
    339             PAN_TRACE_ERROR ("Cannot make PANU connections when there are more than one connection");
    340             return PAN_INVALID_SRC_ROLE;
    341         }
    342 
    343         src_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
    344         if (dst_role == PAN_ROLE_CLIENT)
    345         {
    346             service_id = BTM_SEC_SERVICE_BNEP_PANU;
    347             dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
    348         }
    349         else if (dst_role == PAN_ROLE_GN_SERVER)
    350         {
    351             service_id = BTM_SEC_SERVICE_BNEP_GN;
    352             dst_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
    353         }
    354         else
    355         {
    356             service_id = BTM_SEC_SERVICE_BNEP_NAP;
    357             dst_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
    358         }
    359         mx_chan_id = dst_uuid.uu.uuid16;
    360     }
    361     /* If destination is PANU role validate source role */
    362     else if (dst_role == PAN_ROLE_CLIENT)
    363     {
    364         if (pan_cb.num_conns && pan_cb.active_role == PAN_ROLE_CLIENT && !pcb)
    365         {
    366             PAN_TRACE_ERROR ("Device already have a connection in PANU role");
    367             return PAN_INVALID_SRC_ROLE;
    368         }
    369 
    370         dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
    371         if (src_role == PAN_ROLE_GN_SERVER)
    372         {
    373             service_id = BTM_SEC_SERVICE_BNEP_GN;
    374             src_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
    375         }
    376         else
    377         {
    378             service_id = BTM_SEC_SERVICE_BNEP_NAP;
    379             src_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
    380         }
    381         mx_chan_id = src_uuid.uu.uuid16;
    382     }
    383     /* The role combination is not valid */
    384     else
    385     {
    386         PAN_TRACE_ERROR ("Source %d and Destination roles %d are not valid combination",
    387             src_role, dst_role);
    388         return PAN_FAILURE;
    389     }
    390 
    391     /* Allocate control block and initiate connection */
    392     if (!pcb)
    393         pcb = pan_allocate_pcb (rem_bda, BNEP_INVALID_HANDLE);
    394     if (!pcb)
    395     {
    396         PAN_TRACE_ERROR ("PAN Connection failed because of no resources");
    397         return PAN_NO_RESOURCES;
    398     }
    399     BTM_SetOutService(rem_bda, BTM_SEC_SERVICE_BNEP_PANU, mx_chan_id);
    400 
    401     PAN_TRACE_API ("PAN_Connect() for BD Addr %x.%x.%x.%x.%x.%x",
    402         rem_bda[0], rem_bda[1], rem_bda[2], rem_bda[3], rem_bda[4], rem_bda[5]);
    403     if (pcb->con_state == PAN_STATE_IDLE)
    404     {
    405         pan_cb.num_conns++;
    406     }
    407     else if (pcb->con_state == PAN_STATE_CONNECTED)
    408     {
    409         pcb->con_flags |= PAN_FLAGS_CONN_COMPLETED;
    410     }
    411     else
    412         /* PAN connection is still in progress */
    413         return PAN_WRONG_STATE;
    414 
    415     pcb->con_state = PAN_STATE_CONN_START;
    416     pcb->prv_src_uuid = pcb->src_uuid;
    417     pcb->prv_dst_uuid = pcb->dst_uuid;
    418 
    419     pcb->src_uuid     = src_uuid.uu.uuid16;
    420     pcb->dst_uuid     = dst_uuid.uu.uuid16;
    421 
    422     src_uuid.len      = 2;
    423     dst_uuid.len      = 2;
    424 
    425     result = BNEP_Connect (rem_bda, &src_uuid, &dst_uuid, &(pcb->handle));
    426     if (result != BNEP_SUCCESS)
    427     {
    428         pan_release_pcb (pcb);
    429         return result;
    430     }
    431 
    432     PAN_TRACE_DEBUG ("PAN_Connect() current active role set to %d", src_role);
    433     pan_cb.prv_active_role = pan_cb.active_role;
    434     pan_cb.active_role = src_role;
    435     *handle = pcb->handle;
    436     return PAN_SUCCESS;
    437 }
    438 
    439 
    440 
    441 
    442 /*******************************************************************************
    443 **
    444 ** Function         PAN_Disconnect
    445 **
    446 ** Description      This is used to disconnect the connection
    447 **
    448 ** Parameters:      handle           - handle for the connection
    449 **
    450 ** Returns          PAN_SUCCESS      - if the connection is closed successfully
    451 **                  PAN_FAILURE      - if the connection is not found or
    452 **                                           there is an error in disconnecting
    453 **
    454 *******************************************************************************/
    455 tPAN_RESULT PAN_Disconnect (UINT16 handle)
    456 {
    457     tPAN_CONN       *pcb;
    458     tBNEP_RESULT    result;
    459 
    460     /* Check if the connection exists */
    461     pcb = pan_get_pcb_by_handle (handle);
    462     if(!pcb)
    463     {
    464         PAN_TRACE_ERROR ("PAN connection not found for the handle %d", handle);
    465         return PAN_FAILURE;
    466     }
    467 
    468     result = BNEP_Disconnect (pcb->handle);
    469     if (pcb->con_state != PAN_STATE_IDLE)
    470         pan_cb.num_conns--;
    471 
    472     if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP)
    473         (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
    474 
    475     pan_release_pcb (pcb);
    476 
    477     if (result != BNEP_SUCCESS)
    478     {
    479         PAN_TRACE_EVENT ("Error in closing PAN connection");
    480         return PAN_FAILURE;
    481     }
    482 
    483     PAN_TRACE_EVENT ("PAN connection closed");
    484     return PAN_SUCCESS;
    485 }
    486 
    487 
    488 /*******************************************************************************
    489 **
    490 ** Function         PAN_Write
    491 **
    492 ** Description      This sends data over the PAN connections. If this is called
    493 **                  on GN or NAP side and the packet is multicast or broadcast
    494 **                  it will be sent on all the links. Otherwise the correct link
    495 **                  is found based on the destination address and forwarded on it.
    496 **
    497 ** Parameters:      handle   - handle for the connection
    498 **                  dst      - MAC or BD Addr of the destination device
    499 **                  src      - MAC or BD Addr of the source who sent this packet
    500 **                  protocol - protocol of the ethernet packet like IP or ARP
    501 **                  p_data   - pointer to the data
    502 **                  len      - length of the data
    503 **                  ext      - to indicate that extension headers present
    504 **
    505 ** Returns          PAN_SUCCESS       - if the data is sent successfully
    506 **                  PAN_FAILURE       - if the connection is not found or
    507 **                                           there is an error in sending data
    508 **
    509 *******************************************************************************/
    510 tPAN_RESULT PAN_Write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, UINT8 *p_data, UINT16 len, BOOLEAN ext)
    511 {
    512     BT_HDR *buffer;
    513 
    514     if (pan_cb.role == PAN_ROLE_INACTIVE || !pan_cb.num_conns) {
    515         PAN_TRACE_ERROR("%s PAN is not active, data write failed.", __func__);
    516         return PAN_FAILURE;
    517     }
    518 
    519     // If the packet is broadcast or multicast, we're going to have to create
    520     // a copy of the packet for each connection. We can save one extra copy
    521     // by fast-pathing here and calling BNEP_Write instead of placing the packet
    522     // in a BT_HDR buffer, calling BNEP_Write, and then freeing the buffer.
    523     if (dst[0] & 0x01) {
    524         int i;
    525         for (i = 0; i < MAX_PAN_CONNS; ++i) {
    526             if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
    527                 BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
    528         }
    529         return PAN_SUCCESS;
    530     }
    531 
    532     buffer = (BT_HDR *)GKI_getpoolbuf(PAN_POOL_ID);
    533     if (!buffer) {
    534         PAN_TRACE_ERROR("%s unable to acquire buffer from pool.", __func__);
    535         return PAN_NO_RESOURCES;
    536     }
    537 
    538     buffer->len = len;
    539     buffer->offset = PAN_MINIMUM_OFFSET;
    540     memcpy((UINT8 *)buffer + sizeof(BT_HDR) + buffer->offset, p_data, buffer->len);
    541 
    542     return PAN_WriteBuf(handle, dst, src, protocol, buffer, ext);
    543 }
    544 
    545 
    546 /*******************************************************************************
    547 **
    548 ** Function         PAN_WriteBuf
    549 **
    550 ** Description      This sends data over the PAN connections. If this is called
    551 **                  on GN or NAP side and the packet is multicast or broadcast
    552 **                  it will be sent on all the links. Otherwise the correct link
    553 **                  is found based on the destination address and forwarded on it
    554 **                  If the return value is not PAN_SUCCESS the application should
    555 **                  take care of releasing the message buffer
    556 **
    557 ** Parameters:      handle   - handle for the connection
    558 **                  dst      - MAC or BD Addr of the destination device
    559 **                  src      - MAC or BD Addr of the source who sent this packet
    560 **                  protocol - protocol of the ethernet packet like IP or ARP
    561 **                  p_buf    - pointer to the data buffer
    562 **                  ext      - to indicate that extension headers present
    563 **
    564 ** Returns          PAN_SUCCESS       - if the data is sent successfully
    565 **                  PAN_FAILURE       - if the connection is not found or
    566 **                                           there is an error in sending data
    567 **
    568 *******************************************************************************/
    569 tPAN_RESULT PAN_WriteBuf (UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, BT_HDR *p_buf, BOOLEAN ext)
    570 {
    571     tPAN_CONN       *pcb;
    572     UINT16          i;
    573     tBNEP_RESULT    result;
    574 
    575     if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
    576     {
    577         PAN_TRACE_ERROR ("PAN is not active Data write failed");
    578         GKI_freebuf (p_buf);
    579         return PAN_FAILURE;
    580     }
    581 
    582     /* Check if it is broadcast or multicast packet */
    583     if (dst[0] & 0x01)
    584     {
    585         UINT8 *data = (UINT8 *)p_buf + sizeof(BT_HDR) + p_buf->offset;
    586         for (i = 0; i < MAX_PAN_CONNS; ++i) {
    587             if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
    588                 BNEP_Write(pan_cb.pcb[i].handle, dst, data, p_buf->len, protocol, src, ext);
    589         }
    590         GKI_freebuf(p_buf);
    591         return PAN_SUCCESS;
    592     }
    593 
    594     /* Check if the data write is on PANU side */
    595     if (pan_cb.active_role == PAN_ROLE_CLIENT)
    596     {
    597         /* Data write is on PANU connection */
    598         for (i=0; i<MAX_PAN_CONNS; i++)
    599         {
    600             if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
    601                 pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU)
    602                 break;
    603         }
    604 
    605         if (i == MAX_PAN_CONNS)
    606         {
    607             PAN_TRACE_ERROR ("PAN Don't have any user connections");
    608             GKI_freebuf (p_buf);
    609             return PAN_FAILURE;
    610         }
    611 
    612         result = BNEP_WriteBuf (pan_cb.pcb[i].handle, dst, p_buf, protocol, src, ext);
    613         if (result == BNEP_IGNORE_CMD)
    614         {
    615             PAN_TRACE_DEBUG ("PAN ignored data write for PANU connection");
    616             return result;
    617         }
    618         else if (result != BNEP_SUCCESS)
    619         {
    620             PAN_TRACE_ERROR ("PAN failed to write data for the PANU connection");
    621             return result;
    622         }
    623 
    624         PAN_TRACE_DEBUG ("PAN successfully wrote data for the PANU connection");
    625         return PAN_SUCCESS;
    626     }
    627 
    628     /* findout to which connection the data is meant for */
    629     pcb = pan_get_pcb_by_handle (handle);
    630     if (!pcb)
    631     {
    632         PAN_TRACE_ERROR ("PAN Buf write for wrong handle");
    633         GKI_freebuf (p_buf);
    634         return PAN_FAILURE;
    635     }
    636 
    637     if (pcb->con_state != PAN_STATE_CONNECTED)
    638     {
    639         PAN_TRACE_ERROR ("PAN Buf write when conn is not active");
    640         GKI_freebuf (p_buf);
    641         return PAN_FAILURE;
    642     }
    643 
    644     result = BNEP_WriteBuf (pcb->handle, dst, p_buf, protocol, src, ext);
    645     if (result == BNEP_IGNORE_CMD)
    646     {
    647         PAN_TRACE_DEBUG ("PAN ignored data buf write to PANU");
    648         return result;
    649     }
    650     else if (result != BNEP_SUCCESS)
    651     {
    652         PAN_TRACE_ERROR ("PAN failed to send data buf to the PANU");
    653         return result;
    654     }
    655 
    656     PAN_TRACE_DEBUG ("PAN successfully sent data buf to the PANU");
    657     return PAN_SUCCESS;
    658 }
    659 
    660 
    661 /*******************************************************************************
    662 **
    663 ** Function         PAN_SetProtocolFilters
    664 **
    665 ** Description      This function is used to set protocol filters on the peer
    666 **
    667 ** Parameters:      handle      - handle for the connection
    668 **                  num_filters - number of protocol filter ranges
    669 **                  start       - array of starting protocol numbers
    670 **                  end         - array of ending protocol numbers
    671 **
    672 **
    673 ** Returns          PAN_SUCCESS        if protocol filters are set successfully
    674 **                  PAN_FAILURE        if connection not found or error in setting
    675 **
    676 *******************************************************************************/
    677 tPAN_RESULT PAN_SetProtocolFilters (UINT16 handle,
    678                                     UINT16 num_filters,
    679                                     UINT16 *p_start_array,
    680                                     UINT16 *p_end_array)
    681 {
    682 #if (defined (BNEP_SUPPORTS_PROT_FILTERS) && BNEP_SUPPORTS_PROT_FILTERS == TRUE)
    683     tPAN_CONN       *pcb;
    684     tPAN_RESULT     result;
    685 
    686     /* Check if the connection exists */
    687     pcb = pan_get_pcb_by_handle (handle);
    688     if(!pcb)
    689     {
    690         PAN_TRACE_ERROR ("PAN connection not found for the handle %d", handle);
    691         return PAN_FAILURE;
    692     }
    693 
    694     result = BNEP_SetProtocolFilters (pcb->handle, num_filters, p_start_array, p_end_array);
    695     if (result != BNEP_SUCCESS)
    696     {
    697         PAN_TRACE_ERROR ("PAN failed to set protocol filters for handle %d", handle);
    698         return result;
    699     }
    700 
    701     PAN_TRACE_API ("PAN successfully sent protocol filters for handle %d", handle);
    702     return PAN_SUCCESS;
    703 #else
    704     return PAN_FAILURE;
    705 #endif
    706 }
    707 
    708 
    709 
    710 /*******************************************************************************
    711 **
    712 ** Function         PAN_SetMulticastFilters
    713 **
    714 ** Description      This function is used to set multicast filters on the peer
    715 **
    716 ** Parameters:      handle      - handle for the connection
    717 **                  num_filters - number of multicast filter ranges
    718 **                  start       - array of starting multicast filter addresses
    719 **                  end         - array of ending multicast filter addresses
    720 **
    721 **
    722 ** Returns          PAN_SUCCESS        if multicast filters are set successfully
    723 **                  PAN_FAILURE        if connection not found or error in setting
    724 **
    725 *******************************************************************************/
    726 tBNEP_RESULT PAN_SetMulticastFilters (UINT16 handle,
    727                                       UINT16 num_mcast_filters,
    728                                       UINT8 *p_start_array,
    729                                       UINT8 *p_end_array)
    730 {
    731 #if (defined (BNEP_SUPPORTS_MULTI_FILTERS) && BNEP_SUPPORTS_MULTI_FILTERS == TRUE)
    732     tPAN_CONN       *pcb;
    733     tPAN_RESULT     result;
    734 
    735     /* Check if the connection exists */
    736     pcb = pan_get_pcb_by_handle (handle);
    737     if(!pcb)
    738     {
    739         PAN_TRACE_ERROR ("PAN connection not found for the handle %d", handle);
    740         return PAN_FAILURE;
    741     }
    742 
    743     result = BNEP_SetMulticastFilters (pcb->handle,
    744                             num_mcast_filters, p_start_array, p_end_array);
    745     if (result != BNEP_SUCCESS)
    746     {
    747         PAN_TRACE_ERROR ("PAN failed to set multicast filters for handle %d", handle);
    748         return result;
    749     }
    750 
    751     PAN_TRACE_API ("PAN successfully sent multicast filters for handle %d", handle);
    752     return PAN_SUCCESS;
    753 #else
    754     return PAN_FAILURE;
    755 #endif
    756 }
    757 
    758 
    759 /*******************************************************************************
    760 **
    761 ** Function         PAN_SetTraceLevel
    762 **
    763 ** Description      This function sets the trace level for PAN. If called with
    764 **                  a value of 0xFF, it simply reads the current trace level.
    765 **
    766 ** Returns          the new (current) trace level
    767 **
    768 *******************************************************************************/
    769 UINT8 PAN_SetTraceLevel (UINT8 new_level)
    770 {
    771     if (new_level != 0xFF)
    772         pan_cb.trace_level = new_level;
    773     else
    774         pan_dump_status ();
    775 
    776     return (pan_cb.trace_level);
    777 }
    778 
    779 /*******************************************************************************
    780 **
    781 ** Function         PAN_Init
    782 **
    783 ** Description      This function initializes the PAN module variables
    784 **
    785 ** Parameters:      none
    786 **
    787 ** Returns          none
    788 **
    789 *******************************************************************************/
    790 void PAN_Init (void)
    791 {
    792     memset (&pan_cb, 0, sizeof (tPAN_CB));
    793 
    794 #if defined(PAN_INITIAL_TRACE_LEVEL)
    795     pan_cb.trace_level = PAN_INITIAL_TRACE_LEVEL;
    796 #else
    797     pan_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
    798 #endif
    799 }
    800 
    801 
    802