OSDN Git Service

Serialize remote version query over LE am: 864e7734f2
[android-x86/system-bt.git] / bta / pan / bta_pan_act.c
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 "bt_common.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 *) osi_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             p_scb->data_queue = fixed_queue_new(SIZE_MAX);
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 *) osi_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 *)osi_getbuf(PAN_BUF_SIZE);
211         if(!p_new_buf)
212         {
213             APPL_TRACE_WARNING("Cannot get a PAN buffer");
214             osi_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             osi_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         osi_freebuf( p_new_buf );
241         return;
242     }
243
244     fixed_queue_enqueue(p_scb->data_queue, p_new_buf);
245     if ((p_event = (BT_HDR *) osi_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_has_multiple_connections
299 **
300 ** Description      Check whether there are multiple GN/NAP connections to
301 **                  different devices
302 **
303 **
304 ** Returns          BOOLEAN
305 **
306 *******************************************************************************/
307 static BOOLEAN bta_pan_has_multiple_connections(UINT8 app_id)
308 {
309     tBTA_PAN_SCB *p_scb = NULL;
310     BOOLEAN     found = FALSE;
311     BD_ADDR     bd_addr;
312
313     for (UINT8 index = 0; index < BTA_PAN_NUM_CONN; index++)
314     {
315         p_scb = &bta_pan_cb.scb[index];
316         if (p_scb->in_use == TRUE && app_id == p_scb->app_id)
317         {
318             /* save temp bd_addr */
319             bdcpy(bd_addr, p_scb->bd_addr);
320             found = TRUE;
321             break;
322         }
323     }
324
325     /* If cannot find a match then there is no connection at all */
326     if (found == FALSE)
327         return FALSE;
328
329     /* Find whether there is another connection with different device other than PANU.
330         Could be same service or different service */
331     for (UINT8 index = 0; index < BTA_PAN_NUM_CONN; index++)
332     {
333         p_scb = &bta_pan_cb.scb[index];
334         if (p_scb->in_use == TRUE && p_scb->app_id != bta_pan_cb.app_id[0] &&
335                 bdcmp(bd_addr, p_scb->bd_addr))
336         {
337             return TRUE;
338         }
339     }
340     return FALSE;
341 }
342
343 /*******************************************************************************
344 **
345 ** Function         bta_pan_enable
346 **
347 ** Description
348 **
349 **
350 **
351 ** Returns          void
352 **
353 *******************************************************************************/
354 void bta_pan_enable(tBTA_PAN_DATA *p_data)
355 {
356     tPAN_REGISTER reg_data;
357     UINT16  initial_discoverability;
358     UINT16  initial_connectability;
359     UINT16  d_window;
360     UINT16  d_interval;
361     UINT16  c_window;
362     UINT16  c_interval;
363
364     bta_pan_cb.p_cback = p_data->api_enable.p_cback;
365
366     reg_data.pan_conn_state_cb  = bta_pan_conn_state_cback;
367     reg_data.pan_bridge_req_cb  = NULL;
368     reg_data.pan_data_buf_ind_cb = bta_pan_data_buf_ind_cback;
369     reg_data.pan_data_ind_cb = NULL;
370     reg_data.pan_pfilt_ind_cb = bta_pan_pfilt_ind_cback;
371     reg_data.pan_mfilt_ind_cb = bta_pan_mfilt_ind_cback;
372     reg_data.pan_tx_data_flow_cb = bta_pan_data_flow_cb;
373
374     /* read connectability and discoverability settings.
375     Pan profile changes the settings. We have to change it back to
376     be consistent with other bta subsystems */
377     initial_connectability = BTM_ReadConnectability(&c_window, &c_interval);
378     initial_discoverability = BTM_ReadDiscoverability(&d_window, &d_interval);
379
380
381     PAN_Register (&reg_data);
382
383
384     /* set it back to original value */
385     BTM_SetDiscoverability(initial_discoverability, d_window, d_interval);
386     BTM_SetConnectability(initial_connectability, c_window, c_interval);
387
388     bta_pan_cb.flow_mask = bta_pan_co_init(&bta_pan_cb.q_level);
389     bta_pan_cb.p_cback(BTA_PAN_ENABLE_EVT, NULL);
390
391 }
392
393 /*******************************************************************************
394 **
395 ** Function         bta_pan_set_role
396 **
397 ** Description
398 **
399 ** Returns          void
400 **
401 *******************************************************************************/
402 void bta_pan_set_role(tBTA_PAN_DATA *p_data)
403 {
404     tPAN_RESULT status;
405     tBTA_PAN_SET_ROLE set_role;
406     UINT8  sec[3];
407
408
409     bta_pan_cb.app_id[0] = p_data->api_set_role.user_app_id;
410     bta_pan_cb.app_id[1] = p_data->api_set_role.gn_app_id;
411     bta_pan_cb.app_id[2] = p_data->api_set_role.nap_app_id;
412
413     sec[0] = p_data->api_set_role.user_sec_mask;
414     sec[1] = p_data->api_set_role.gn_sec_mask;
415     sec[2] = p_data->api_set_role.nap_sec_mask;
416
417     /* set security correctly in api and here */
418     status = PAN_SetRole(p_data->api_set_role.role, sec,
419                                      p_data->api_set_role.user_name,
420                                      p_data->api_set_role.gn_name,
421                                      p_data->api_set_role.nap_name);
422
423     set_role.role = p_data->api_set_role.role;
424     if(status == PAN_SUCCESS)
425     {
426         if(p_data->api_set_role.role & PAN_ROLE_NAP_SERVER )
427             bta_sys_add_uuid(UUID_SERVCLASS_NAP);
428         else
429             bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
430
431         if(p_data->api_set_role.role & PAN_ROLE_GN_SERVER )
432             bta_sys_add_uuid(UUID_SERVCLASS_GN);
433         else
434             bta_sys_remove_uuid(UUID_SERVCLASS_GN);
435
436         if(p_data->api_set_role.role & PAN_ROLE_CLIENT )
437             bta_sys_add_uuid(UUID_SERVCLASS_PANU);
438         else
439             bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
440
441         set_role.status = BTA_PAN_SUCCESS;
442     }
443     /* if status is not success clear everything */
444     else
445     {
446         PAN_SetRole(0, 0, NULL, NULL, NULL);
447         bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
448         bta_sys_remove_uuid(UUID_SERVCLASS_GN);
449         bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
450         set_role.status = BTA_PAN_FAIL;
451     }
452     bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role);
453 }
454
455
456
457 /*******************************************************************************
458 **
459 ** Function         bta_pan_disable
460 **
461 ** Description
462 **
463 **
464 **
465 ** Returns          void
466 **
467 *******************************************************************************/
468 void bta_pan_disable(void)
469 {
470
471     BT_HDR *p_buf;
472     tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0];
473     UINT8 i;
474
475
476     /* close all connections */
477     PAN_SetRole (0, NULL, NULL, NULL, NULL);
478
479 #if (BTA_EIR_CANNED_UUID_LIST != TRUE)
480     bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
481     bta_sys_remove_uuid(UUID_SERVCLASS_GN);
482     bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
483 #endif // BTA_EIR_CANNED_UUID_LIST
484     /* free all queued up data buffers */
485     for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
486     {
487         if (p_scb->in_use)
488         {
489             while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_scb->data_queue)) != NULL)
490                 osi_freebuf(p_buf);
491
492             bta_pan_co_close(p_scb->handle, p_scb->app_id);
493
494         }
495     }
496
497
498
499     PAN_Deregister();
500
501 }
502
503 /*******************************************************************************
504 **
505 ** Function         bta_pan_open
506 **
507 ** Description
508 **
509 ** Returns          void
510 **
511 *******************************************************************************/
512 void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
513 {
514     tPAN_RESULT status;
515     tBTA_PAN_OPEN data;
516     tBTA_PAN_OPENING    opening;
517
518
519     status = PAN_Connect (p_data->api_open.bd_addr, p_data->api_open.local_role, p_data->api_open.peer_role,
520                         &p_scb->handle);
521     APPL_TRACE_DEBUG("%s pan connect status: %d", __func__, status);
522
523     if(status == PAN_SUCCESS)
524     {
525
526         bdcpy(p_scb->bd_addr, p_data->api_open.bd_addr);
527         p_scb->local_role = p_data->api_open.local_role;
528         p_scb->peer_role = p_data->api_open.peer_role;
529         bdcpy(opening.bd_addr, p_data->api_open.bd_addr);
530         opening.handle = p_scb->handle;
531         bta_pan_cb.p_cback(BTA_PAN_OPENING_EVT, (tBTA_PAN *)&opening);
532
533
534     }
535     else
536     {
537         bta_pan_scb_dealloc(p_scb);
538         bdcpy(data.bd_addr, p_data->api_open.bd_addr);
539         data.status = BTA_PAN_FAIL;
540         data.local_role = p_data->api_open.local_role;
541         data.peer_role = p_data->api_open.peer_role;
542         bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
543     }
544
545 }
546
547
548 /*******************************************************************************
549 **
550 ** Function         bta_pan_close
551 **
552 ** Description
553 **
554 **
555 **
556 ** Returns          void
557 **
558 *******************************************************************************/
559 void bta_pan_api_close (tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
560 {
561     tBTA_PAN_CONN * p_buf;
562     UNUSED(p_data);
563
564     PAN_Disconnect (p_scb->handle);
565
566
567     /* send an event to BTA so that application will get the connection
568        close event */
569     if ((p_buf = (tBTA_PAN_CONN *) osi_getbuf(sizeof(tBTA_PAN_CONN))) != NULL)
570     {
571         p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT;
572
573         p_buf->hdr.layer_specific = p_scb->handle;
574         bta_sys_sendmsg(p_buf);
575
576     }
577 }
578
579
580 /*******************************************************************************
581 **
582 ** Function         bta_pan_conn_open
583 **
584 ** Description      process connection open event
585 **
586 ** Returns          void
587 **
588 *******************************************************************************/
589 void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
590 {
591
592     tBTA_PAN_OPEN data;
593
594     APPL_TRACE_DEBUG("%s pan connection result: %d", __func__, p_data->conn.result);
595
596     bdcpy(data.bd_addr, p_scb->bd_addr);
597     data.handle = p_scb->handle;
598     data.local_role = p_scb->local_role;
599     data.peer_role = p_scb->peer_role;
600
601     if(p_data->conn.result == PAN_SUCCESS)
602     {
603         data.status = BTA_PAN_SUCCESS;
604         p_scb->pan_flow_enable = TRUE;
605         p_scb->app_flow_enable = TRUE;
606         bta_sys_conn_open(BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
607     }
608     else
609     {
610         bta_pan_scb_dealloc(p_scb);
611         data.status = BTA_PAN_FAIL;
612     }
613
614     p_scb->pan_flow_enable = TRUE;
615     p_scb->app_flow_enable = TRUE;
616
617     /* If app_id is NAP/GN, check whether there are multiple connections.
618        If there are, provide a special app_id to dm to enforce master role only. */
619     if ((p_scb->app_id == bta_pan_cb.app_id[1] || p_scb->app_id == bta_pan_cb.app_id[2]) &&
620             bta_pan_has_multiple_connections(p_scb->app_id))
621     {
622         p_scb->app_id = BTA_APP_ID_PAN_MULTI;
623     }
624
625     bta_sys_conn_open(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr);
626     bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
627
628
629 }
630
631 /*******************************************************************************
632 **
633 ** Function         bta_pan_conn_close
634 **
635 ** Description      process connection close event
636 **
637 **
638 **
639 ** Returns          void
640 **
641 *******************************************************************************/
642 void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
643 {
644
645     tBTA_PAN_CLOSE data;
646     BT_HDR *p_buf;
647
648     data.handle = p_data->hdr.layer_specific;
649
650     bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
651
652     /* free all queued up data buffers */
653     while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_scb->data_queue)) != NULL)
654         osi_freebuf(p_buf);
655
656     bta_pan_scb_dealloc(p_scb);
657
658     bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data);
659
660 }
661
662
663
664
665 /*******************************************************************************
666 **
667 ** Function         bta_pan_rx_path
668 **
669 ** Description      Handle data on the RX path (data sent from the phone to
670 **                  BTA).
671 **
672 **
673 ** Returns          void
674 **
675 *******************************************************************************/
676 void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
677 {
678     UNUSED(p_data);
679
680     /* if data path configured for rx pull */
681     if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL)
682     {
683         /* if we can accept data */
684         if (p_scb->pan_flow_enable == TRUE)
685         {
686             /* call application callout function for rx path */
687             bta_pan_co_rx_path(p_scb->handle, p_scb->app_id);
688         }
689     }
690     /* else data path configured for rx push */
691     else
692     {
693
694     }
695 }
696
697 /*******************************************************************************
698 **
699 ** Function         bta_pan_tx_path
700 **
701 ** Description      Handle the TX data path (data sent from BTA to the phone).
702 **
703 **
704 ** Returns          void
705 **
706 *******************************************************************************/
707 void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
708 {
709     BT_HDR * p_buf;
710     UNUSED(p_data);
711
712     /* if data path configured for tx pull */
713     if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PULL)
714     {
715         bta_pan_pm_conn_busy(p_scb);
716         /* call application callout function for tx path */
717         bta_pan_co_tx_path(p_scb->handle, p_scb->app_id);
718
719         /* free data that exceeds queue level */
720         while (fixed_queue_length(p_scb->data_queue) > bta_pan_cb.q_level)
721             osi_freebuf(fixed_queue_try_dequeue(p_scb->data_queue));
722         bta_pan_pm_conn_idle(p_scb);
723     }
724     /* if configured for zero copy push */
725     else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF)
726     {
727         /* if app can accept data */
728         if (p_scb->app_flow_enable == TRUE)
729         {
730             /* read data from the queue */
731             if ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_scb->data_queue)) != NULL)
732             {
733                 /* send data to application */
734                 bta_pan_co_tx_writebuf(p_scb->handle,
735                                         p_scb->app_id,
736                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->src,
737                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->dst,
738                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol,
739                                         p_buf,
740                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext,
741                                         ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward);
742
743             }
744             /* free data that exceeds queue level  */
745             while (fixed_queue_length(p_scb->data_queue) > bta_pan_cb.q_level)
746                 osi_freebuf(fixed_queue_try_dequeue(p_scb->data_queue));
747
748             /* if there is more data to be passed to
749             upper layer */
750             if (!fixed_queue_is_empty(p_scb->data_queue))
751             {
752                 if ((p_buf = (BT_HDR *) osi_getbuf(sizeof(BT_HDR))) != NULL)
753                 {
754                     p_buf->layer_specific = p_scb->handle;
755                     p_buf->event = BTA_PAN_RX_FROM_BNEP_READY_EVT;
756                     bta_sys_sendmsg(p_buf);
757                 }
758
759             }
760
761         }
762     }
763 }
764
765 /*******************************************************************************
766 **
767 ** Function         bta_pan_tx_flow
768 **
769 ** Description      Set the application flow control state.
770 **
771 **
772 ** Returns          void
773 **
774 *******************************************************************************/
775 void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
776 {
777     p_scb->app_flow_enable = p_data->ci_tx_flow.enable;
778 }
779
780 /*******************************************************************************
781 **
782 ** Function         bta_pan_write_buf
783 **
784 ** Description      Handle a bta_pan_ci_rx_writebuf() and send data to PAN.
785 **
786 **
787 ** Returns          void
788 **
789 *******************************************************************************/
790 void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
791 {
792     if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PUSH_BUF)
793     {
794         bta_pan_pm_conn_busy(p_scb);
795
796         PAN_WriteBuf (p_scb->handle,
797                       ((tBTA_PAN_DATA_PARAMS *)p_data)->dst,
798                       ((tBTA_PAN_DATA_PARAMS *)p_data)->src,
799                       ((tBTA_PAN_DATA_PARAMS *)p_data)->protocol,
800                       (BT_HDR *)p_data,
801                       ((tBTA_PAN_DATA_PARAMS *)p_data)->ext);
802         bta_pan_pm_conn_idle(p_scb);
803
804     }
805 }
806
807 /*******************************************************************************
808 **
809 ** Function         bta_pan_free_buf
810 **
811 ** Description      Frees the data buffer during closing state
812 **
813 **
814 ** Returns          void
815 **
816 *******************************************************************************/
817 void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
818 {
819     UNUSED(p_scb);
820
821     osi_freebuf(p_data);
822
823 }
824
825 #endif /* PAN_INCLUDED */