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