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