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