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