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