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