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