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 *******************************************************************************/
55static 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 *******************************************************************************/
72static 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*******************************************************************************/
88static 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*******************************************************************************/
159static 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*******************************************************************************/
200static 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*******************************************************************************/
265static 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*******************************************************************************/
286static 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*******************************************************************************/
307void 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*******************************************************************************/
355void 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*******************************************************************************/
421void 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*******************************************************************************/
465void 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*******************************************************************************/
512void 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*******************************************************************************/
542void 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*******************************************************************************/
584void 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*******************************************************************************/
623void 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*******************************************************************************/
654void 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*******************************************************************************/
722void 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*******************************************************************************/
737void 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*******************************************************************************/
764void 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