Home | History | Annotate | Download | only in pan
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2004-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 the pan action functions for the state machine.
     22  *
     23  ******************************************************************************/
     24 
     25 #include "bt_target.h"
     26 
     27 #if defined(PAN_INCLUDED) && (PAN_INCLUDED == TRUE)
     28 
     29 #include "bta_api.h"
     30 #include "bta_sys.h"
     31 #include "gki.h"
     32 #include "pan_api.h"
     33 #include "bta_pan_api.h"
     34 #include "bta_pan_int.h"
     35 #include "bta_pan_co.h"
     36 #include <string.h>
     37 #include "utl.h"
     38 
     39 
     40 /* RX and TX data flow mask */
     41 #define BTA_PAN_RX_MASK              0x0F
     42 #define BTA_PAN_TX_MASK              0xF0
     43 
     44 /*******************************************************************************
     45  **
     46  ** Function    bta_pan_pm_conn_busy
     47  **
     48  ** Description set pan pm connection busy state
     49  **
     50  ** Params      p_scb: state machine control block of pan connection
     51  **
     52  ** Returns     void
     53  **
     54  *******************************************************************************/
     55 static void bta_pan_pm_conn_busy(tBTA_PAN_SCB *p_scb)
     56 {
     57     if ((p_scb != NULL) && (p_scb->state != BTA_PAN_IDLE_ST))
     58         bta_sys_busy(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr);
     59 }
     60 
     61 /*******************************************************************************
     62  **
     63  ** Function    bta_pan_pm_conn_idle
     64  **
     65  ** Description set pan pm connection idle state
     66  **
     67  ** Params      p_scb: state machine control block of pan connection
     68  **
     69  ** Returns     void
     70  **
     71  *******************************************************************************/
     72 static void bta_pan_pm_conn_idle(tBTA_PAN_SCB *p_scb)
     73 {
     74     if ((p_scb != NULL) && (p_scb->state != BTA_PAN_IDLE_ST))
     75         bta_sys_idle(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr);
     76 }
     77 
     78 /*******************************************************************************
     79 **
     80 ** Function         bta_pan_conn_state_cback
     81 **
     82 ** Description      Connection state callback from Pan profile
     83 **
     84 **
     85 ** Returns          void
     86 **
     87 *******************************************************************************/
     88 static void bta_pan_conn_state_cback(UINT16 handle, BD_ADDR bd_addr, tPAN_RESULT state,
     89                                      BOOLEAN is_role_change, UINT8 src_role, UINT8 dst_role)
     90 {
     91 
     92     tBTA_PAN_CONN * p_buf;
     93     tBTA_PAN_SCB     *p_scb;
     94 
     95 
     96     if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL)
     97     {
     98         if((state == PAN_SUCCESS) && !is_role_change)
     99         {
    100             p_buf->hdr.event = BTA_PAN_CONN_OPEN_EVT;
    101             if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
    102             {
    103                 /* allocate an scb */
    104                 p_scb = bta_pan_scb_alloc();
    105 
    106             }
    107             /* we have exceeded maximum number of connections */
    108             if(!p_scb)
    109             {
    110                 PAN_Disconnect (handle);
    111                 return;
    112             }
    113 
    114             p_scb->handle = handle;
    115             p_scb->local_role = src_role;
    116             p_scb->peer_role = dst_role;
    117             p_scb->pan_flow_enable = TRUE;
    118             bdcpy(p_scb->bd_addr, bd_addr);
    119             GKI_init_q(&p_scb->data_queue);
    120 
    121             if(src_role == PAN_ROLE_CLIENT)
    122                 p_scb->app_id = bta_pan_cb.app_id[0];
    123             else if (src_role == PAN_ROLE_GN_SERVER)
    124                 p_scb->app_id = bta_pan_cb.app_id[1];
    125             else if (src_role == PAN_ROLE_NAP_SERVER)
    126                 p_scb->app_id = bta_pan_cb.app_id[2];
    127 
    128         }
    129         else if((state != PAN_SUCCESS) && !is_role_change)
    130         {
    131             p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT;
    132 
    133         }
    134         else
    135         {
    136             return;
    137         }
    138 
    139         p_buf->result = state;
    140         p_buf->hdr.layer_specific = handle;
    141         bta_sys_sendmsg(p_buf);
    142 
    143     }
    144 
    145 
    146 
    147 }
    148 
    149 /*******************************************************************************
    150 **
    151 ** Function         bta_pan_data_flow_cb
    152 **
    153 ** Description      Data flow status callback from PAN
    154 **
    155 **
    156 ** Returns          void
    157 **
    158 *******************************************************************************/
    159 static void bta_pan_data_flow_cb(UINT16 handle, tPAN_RESULT result)
    160 {
    161     BT_HDR  *p_buf;
    162     tBTA_PAN_SCB *p_scb;
    163 
    164     if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
    165         return;
    166 
    167     if(result == PAN_TX_FLOW_ON)
    168     {
    169         if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
    170         {
    171             p_buf->layer_specific = handle;
    172             p_buf->event = BTA_PAN_BNEP_FLOW_ENABLE_EVT;
    173             bta_sys_sendmsg(p_buf);
    174         }
    175         bta_pan_co_rx_flow(handle, p_scb->app_id, TRUE);
    176 
    177     }
    178     else if(result == PAN_TX_FLOW_OFF)
    179     {
    180 
    181         p_scb->pan_flow_enable = FALSE;
    182         bta_pan_co_rx_flow(handle, p_scb->app_id, FALSE);
    183 
    184     }
    185 
    186 
    187 }
    188 
    189 
    190 /*******************************************************************************
    191 **
    192 ** Function         bta_pan_data_buf_ind_cback
    193 **
    194 ** Description      data indication callback from pan profile
    195 **
    196 **
    197 ** Returns          void
    198 **
    199 *******************************************************************************/
    200 static void bta_pan_data_buf_ind_cback(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf,
    201                                    BOOLEAN ext, BOOLEAN forward)
    202 {
    203     tBTA_PAN_SCB *p_scb;
    204     BT_HDR * p_event;
    205     BT_HDR *p_new_buf;
    206 
    207     if ( sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset )
    208     {
    209         /* offset smaller than data structure in front of actual data */
    210         p_new_buf = (BT_HDR *)GKI_getpoolbuf( PAN_POOL_ID );
    211         if(!p_new_buf)
    212         {
    213             APPL_TRACE_WARNING("Cannot get a PAN GKI buffer");
    214             GKI_freebuf( p_buf );
    215             return;
    216         }
    217         else
    218         {
    219             memcpy( (UINT8 *)(p_new_buf+1)+sizeof(tBTA_PAN_DATA_PARAMS), (UINT8 *)(p_buf+1)+p_buf->offset, p_buf->len );
    220             p_new_buf->len    = p_buf->len;
    221             p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS);
    222             GKI_freebuf( p_buf );
    223         }
    224     }
    225     else
    226     {
    227         p_new_buf = p_buf;
    228     }
    229     /* copy params into the space before the data */
    230     bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->src, src);
    231     bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->dst, dst);
    232     ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->protocol = protocol;
    233     ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->ext = ext;
    234     ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->forward = forward;
    235 
    236 
    237     if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
    238     {
    239 
    240         GKI_freebuf( p_new_buf );
    241         return;
    242     }
    243 
    244     GKI_enqueue(&p_scb->data_queue, p_new_buf);
    245     if ((p_event = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
    246     {
    247         p_event->layer_specific = handle;
    248         p_event->event = BTA_PAN_RX_FROM_BNEP_READY_EVT;
    249         bta_sys_sendmsg(p_event);
    250     }
    251 
    252 }
    253 
    254 
    255 /*******************************************************************************
    256 **
    257 ** Function         bta_pan_pfilt_ind_cback
    258 **
    259 ** Description
    260 **
    261 **
    262 ** Returns          void
    263 **
    264 *******************************************************************************/
    265 static void bta_pan_pfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result,
    266                                     UINT16 num_filters, UINT8 *p_filters)
    267 {
    268 
    269     bta_pan_co_pfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL),
    270                                     num_filters, p_filters);
    271 
    272 
    273 }
    274 
    275 
    276 /*******************************************************************************
    277 **
    278 ** Function         bta_pan_mfilt_ind_cback
    279 **
    280 ** Description
    281 **
    282 **
    283 ** Returns          void
    284 **
    285 *******************************************************************************/
    286 static void bta_pan_mfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result,
    287                                     UINT16 num_mfilters, UINT8 *p_mfilters)
    288 {
    289 
    290     bta_pan_co_mfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL),
    291                                     num_mfilters, p_mfilters);
    292 }
    293 
    294 
    295 
    296 /*******************************************************************************
    297 **
    298 ** Function         bta_pan_enable
    299 **
    300 ** Description
    301 **
    302 **
    303 **
    304 ** Returns          void
    305 **
    306 *******************************************************************************/
    307 void bta_pan_enable(tBTA_PAN_DATA *p_data)
    308 {
    309     tPAN_REGISTER reg_data;
    310     UINT16  initial_discoverability;
    311     UINT16  initial_connectability;
    312     UINT16  d_window;
    313     UINT16  d_interval;
    314     UINT16  c_window;
    315     UINT16  c_interval;
    316 
    317     bta_pan_cb.p_cback = p_data->api_enable.p_cback;
    318 
    319     reg_data.pan_conn_state_cb  = bta_pan_conn_state_cback;
    320     reg_data.pan_bridge_req_cb  = NULL;
    321     reg_data.pan_data_buf_ind_cb = bta_pan_data_buf_ind_cback;
    322     reg_data.pan_data_ind_cb = NULL;
    323     reg_data.pan_pfilt_ind_cb = bta_pan_pfilt_ind_cback;
    324     reg_data.pan_mfilt_ind_cb = bta_pan_mfilt_ind_cback;
    325     reg_data.pan_tx_data_flow_cb = bta_pan_data_flow_cb;
    326 
    327     /* read connectability and discoverability settings.
    328     Pan profile changes the settings. We have to change it back to
    329     be consistent with other bta subsystems */
    330     initial_connectability = BTM_ReadConnectability(&c_window, &c_interval);
    331     initial_discoverability = BTM_ReadDiscoverability(&d_window, &d_interval);
    332 
    333 
    334     PAN_Register (&reg_data);
    335 
    336 
    337     /* set it back to original value */
    338     BTM_SetDiscoverability(initial_discoverability, d_window, d_interval);
    339     BTM_SetConnectability(initial_connectability, c_window, c_interval);
    340 
    341     bta_pan_cb.flow_mask = bta_pan_co_init(&bta_pan_cb.q_level);
    342     bta_pan_cb.p_cback(BTA_PAN_ENABLE_EVT, NULL);
    343 
    344 }
    345 
    346 /*******************************************************************************
    347 **
    348 ** Function         bta_pan_set_role
    349 **
    350 ** Description
    351 **
    352 ** Returns          void
    353 **
    354 *******************************************************************************/
    355 void bta_pan_set_role(tBTA_PAN_DATA *p_data)
    356 {
    357     tPAN_RESULT status;
    358     tBTA_PAN_SET_ROLE set_role;
    359     UINT8  sec[3];
    360 
    361 
    362     bta_pan_cb.app_id[0] = p_data->api_set_role.user_app_id;
    363     bta_pan_cb.app_id[1] = p_data->api_set_role.gn_app_id;
    364     bta_pan_cb.app_id[2] = p_data->api_set_role.nap_app_id;
    365 
    366     sec[0] = p_data->api_set_role.user_sec_mask;
    367     sec[1] = p_data->api_set_role.gn_sec_mask;
    368     sec[2] = p_data->api_set_role.nap_sec_mask;
    369 
    370     /* set security correctly in api and here */
    371     status = PAN_SetRole(p_data->api_set_role.role, sec,
    372                                      p_data->api_set_role.user_name,
    373                                      p_data->api_set_role.gn_name,
    374                                      p_data->api_set_role.nap_name);
    375 
    376     set_role.role = p_data->api_set_role.role;
    377     if(status == PAN_SUCCESS)
    378     {
    379         if(p_data->api_set_role.role & PAN_ROLE_NAP_SERVER )
    380             bta_sys_add_uuid(UUID_SERVCLASS_NAP);
    381         else
    382             bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
    383 
    384         if(p_data->api_set_role.role & PAN_ROLE_GN_SERVER )
    385             bta_sys_add_uuid(UUID_SERVCLASS_GN);
    386         else
    387             bta_sys_remove_uuid(UUID_SERVCLASS_GN);
    388 
    389         if(p_data->api_set_role.role & PAN_ROLE_CLIENT )
    390             bta_sys_add_uuid(UUID_SERVCLASS_PANU);
    391         else
    392             bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
    393 
    394         set_role.status = BTA_PAN_SUCCESS;
    395     }
    396     /* if status is not success clear everything */
    397     else
    398     {
    399         PAN_SetRole(0, 0, NULL, NULL, NULL);
    400         bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
    401         bta_sys_remove_uuid(UUID_SERVCLASS_GN);
    402         bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
    403         set_role.status = BTA_PAN_FAIL;
    404     }
    405     bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role);
    406 }
    407 
    408 
    409 
    410 /*******************************************************************************
    411 **
    412 ** Function         bta_pan_disable
    413 **
    414 ** Description
    415 **
    416 **
    417 **
    418 ** Returns          void
    419 **
    420 *******************************************************************************/
    421 void bta_pan_disable(void)
    422 {
    423 
    424     BT_HDR *p_buf;
    425     tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0];
    426     UINT8 i;
    427 
    428 
    429     /* close all connections */
    430     PAN_SetRole (0, NULL, NULL, NULL, NULL);
    431 
    432 #if (BTA_EIR_CANNED_UUID_LIST != TRUE)
    433     bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
    434     bta_sys_remove_uuid(UUID_SERVCLASS_GN);
    435     bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
    436 #endif // BTA_EIR_CANNED_UUID_LIST
    437     /* free all queued up data buffers */
    438     for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
    439     {
    440         if (p_scb->in_use)
    441         {
    442             while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
    443                 GKI_freebuf(p_buf);
    444 
    445             bta_pan_co_close(p_scb->handle, p_scb->app_id);
    446 
    447         }
    448     }
    449 
    450 
    451 
    452     PAN_Deregister();
    453 
    454 }
    455 
    456 /*******************************************************************************
    457 **
    458 ** Function         bta_pan_open
    459 **
    460 ** Description
    461 **
    462 ** Returns          void
    463 **
    464 *******************************************************************************/
    465 void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    466 {
    467     tPAN_RESULT status;
    468     tBTA_PAN_OPEN data;
    469     tBTA_PAN_OPENING    opening;
    470 
    471 
    472     status = PAN_Connect (p_data->api_open.bd_addr, p_data->api_open.local_role, p_data->api_open.peer_role,
    473                         &p_scb->handle);
    474     APPL_TRACE_DEBUG("%s pan connect status: %d", __func__, status);
    475 
    476     if(status == PAN_SUCCESS)
    477     {
    478 
    479         bdcpy(p_scb->bd_addr, p_data->api_open.bd_addr);
    480         p_scb->local_role = p_data->api_open.local_role;
    481         p_scb->peer_role = p_data->api_open.peer_role;
    482         bdcpy(opening.bd_addr, p_data->api_open.bd_addr);
    483         opening.handle = p_scb->handle;
    484         bta_pan_cb.p_cback(BTA_PAN_OPENING_EVT, (tBTA_PAN *)&opening);
    485 
    486 
    487     }
    488     else
    489     {
    490         bta_pan_scb_dealloc(p_scb);
    491         bdcpy(data.bd_addr, p_data->api_open.bd_addr);
    492         data.status = BTA_PAN_FAIL;
    493         data.local_role = p_data->api_open.local_role;
    494         data.peer_role = p_data->api_open.peer_role;
    495         bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
    496     }
    497 
    498 }
    499 
    500 
    501 /*******************************************************************************
    502 **
    503 ** Function         bta_pan_close
    504 **
    505 ** Description
    506 **
    507 **
    508 **
    509 ** Returns          void
    510 **
    511 *******************************************************************************/
    512 void bta_pan_api_close (tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    513 {
    514     tBTA_PAN_CONN * p_buf;
    515     UNUSED(p_data);
    516 
    517     PAN_Disconnect (p_scb->handle);
    518 
    519 
    520     /* send an event to BTA so that application will get the connection
    521        close event */
    522     if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL)
    523     {
    524         p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT;
    525 
    526         p_buf->hdr.layer_specific = p_scb->handle;
    527         bta_sys_sendmsg(p_buf);
    528 
    529     }
    530 }
    531 
    532 
    533 /*******************************************************************************
    534 **
    535 ** Function         bta_pan_conn_open
    536 **
    537 ** Description      process connection open event
    538 **
    539 ** Returns          void
    540 **
    541 *******************************************************************************/
    542 void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    543 {
    544 
    545     tBTA_PAN_OPEN data;
    546 
    547     APPL_TRACE_DEBUG("%s pan connection result: %d", __func__, p_data->conn.result);
    548 
    549     bdcpy(data.bd_addr, p_scb->bd_addr);
    550     data.handle = p_scb->handle;
    551     data.local_role = p_scb->local_role;
    552     data.peer_role = p_scb->peer_role;
    553 
    554     if(p_data->conn.result == PAN_SUCCESS)
    555     {
    556         data.status = BTA_PAN_SUCCESS;
    557         bta_pan_co_open(p_scb->handle, p_scb->app_id, p_scb->local_role, p_scb->peer_role, p_scb->bd_addr);
    558         p_scb->pan_flow_enable = TRUE;
    559         p_scb->app_flow_enable = TRUE;
    560         bta_sys_conn_open(BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
    561     }
    562     else
    563     {
    564         bta_pan_scb_dealloc(p_scb);
    565         data.status = BTA_PAN_FAIL;
    566     }
    567 
    568     bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
    569 
    570 
    571 }
    572 
    573 /*******************************************************************************
    574 **
    575 ** Function         bta_pan_conn_close
    576 **
    577 ** Description      process connection close event
    578 **
    579 **
    580 **
    581 ** Returns          void
    582 **
    583 *******************************************************************************/
    584 void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    585 {
    586 
    587     tBTA_PAN_CLOSE data;
    588     BT_HDR *p_buf;
    589 
    590     data.handle = p_data->hdr.layer_specific;
    591 
    592 
    593     bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
    594 
    595     /* free all queued up data buffers */
    596     while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
    597         GKI_freebuf(p_buf);
    598 
    599     GKI_init_q(&p_scb->data_queue);
    600 
    601     bta_pan_co_close(p_scb->handle, p_scb->app_id);
    602 
    603     bta_pan_scb_dealloc(p_scb);
    604 
    605     bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data);
    606 
    607 }
    608 
    609 
    610 
    611 
    612 /*******************************************************************************
    613 **
    614 ** Function         bta_pan_rx_path
    615 **
    616 ** Description      Handle data on the RX path (data sent from the phone to
    617 **                  BTA).
    618 **
    619 **
    620 ** Returns          void
    621 **
    622 *******************************************************************************/
    623 void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    624 {
    625     UNUSED(p_data);
    626 
    627     /* if data path configured for rx pull */
    628     if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL)
    629     {
    630         /* if we can accept data */
    631         if (p_scb->pan_flow_enable == TRUE)
    632         {
    633             /* call application callout function for rx path */
    634             bta_pan_co_rx_path(p_scb->handle, p_scb->app_id);
    635         }
    636     }
    637     /* else data path configured for rx push */
    638     else
    639     {
    640 
    641     }
    642 }
    643 
    644 /*******************************************************************************
    645 **
    646 ** Function         bta_pan_tx_path
    647 **
    648 ** Description      Handle the TX data path (data sent from BTA to the phone).
    649 **
    650 **
    651 ** Returns          void
    652 **
    653 *******************************************************************************/
    654 void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    655 {
    656     BT_HDR * p_buf;
    657     UNUSED(p_data);
    658 
    659     /* if data path configured for tx pull */
    660     if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PULL)
    661     {
    662         bta_pan_pm_conn_busy(p_scb);
    663         /* call application callout function for tx path */
    664         bta_pan_co_tx_path(p_scb->handle, p_scb->app_id);
    665 
    666         /* free data that exceeds queue level */
    667         while(GKI_queue_length(&p_scb->data_queue) > bta_pan_cb.q_level)
    668             GKI_freebuf(GKI_dequeue(&p_scb->data_queue));
    669         bta_pan_pm_conn_idle(p_scb);
    670     }
    671     /* if configured for zero copy push */
    672     else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF)
    673     {
    674         /* if app can accept data */
    675         if (p_scb->app_flow_enable == TRUE)
    676         {
    677             /* read data from the queue */
    678             if ((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
    679             {
    680                 /* send data to application */
    681                 bta_pan_co_tx_writebuf(p_scb->handle,
    682                                         p_scb->app_id,
    683                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->src,
    684                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->dst,
    685                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol,
    686                                         p_buf,
    687                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext,
    688                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward);
    689 
    690             }
    691             /* free data that exceeds queue level  */
    692             while(GKI_queue_length(&p_scb->data_queue) > bta_pan_cb.q_level)
    693                 GKI_freebuf(GKI_dequeue(&p_scb->data_queue));
    694 
    695             /* if there is more data to be passed to
    696             upper layer */
    697             if(!GKI_queue_is_empty(&p_scb->data_queue))
    698             {
    699                 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
    700                 {
    701                     p_buf->layer_specific = p_scb->handle;
    702                     p_buf->event = BTA_PAN_RX_FROM_BNEP_READY_EVT;
    703                     bta_sys_sendmsg(p_buf);
    704                 }
    705 
    706             }
    707 
    708         }
    709     }
    710 }
    711 
    712 /*******************************************************************************
    713 **
    714 ** Function         bta_pan_tx_flow
    715 **
    716 ** Description      Set the application flow control state.
    717 **
    718 **
    719 ** Returns          void
    720 **
    721 *******************************************************************************/
    722 void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    723 {
    724     p_scb->app_flow_enable = p_data->ci_tx_flow.enable;
    725 }
    726 
    727 /*******************************************************************************
    728 **
    729 ** Function         bta_pan_write_buf
    730 **
    731 ** Description      Handle a bta_pan_ci_rx_writebuf() and send data to PAN.
    732 **
    733 **
    734 ** Returns          void
    735 **
    736 *******************************************************************************/
    737 void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    738 {
    739     if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PUSH_BUF)
    740     {
    741         bta_pan_pm_conn_busy(p_scb);
    742 
    743         PAN_WriteBuf (p_scb->handle,
    744                       ((tBTA_PAN_DATA_PARAMS *)p_data)->dst,
    745                       ((tBTA_PAN_DATA_PARAMS *)p_data)->src,
    746                       ((tBTA_PAN_DATA_PARAMS *)p_data)->protocol,
    747                       (BT_HDR *)p_data,
    748                       ((tBTA_PAN_DATA_PARAMS *)p_data)->ext);
    749         bta_pan_pm_conn_idle(p_scb);
    750 
    751     }
    752 }
    753 
    754 /*******************************************************************************
    755 **
    756 ** Function         bta_pan_free_buf
    757 **
    758 ** Description      Frees the data buffer during closing state
    759 **
    760 **
    761 ** Returns          void
    762 **
    763 *******************************************************************************/
    764 void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
    765 {
    766     UNUSED(p_scb);
    767 
    768     GKI_freebuf(p_data);
    769 
    770 }
    771 
    772 #endif /* PAN_INCLUDED */
    773