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