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