1 /****************************************************************************** 2 * 3 * Copyright 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 <log/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 ******************************************************************************/ 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 ******************************************************************************/ 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 ******************************************************************************/ 89 static void bta_pan_conn_state_cback(uint16_t handle, const RawAddress& 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 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 ******************************************************************************/ 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 ******************************************************************************/ 171 static void bta_pan_data_buf_ind_cback(uint16_t handle, const RawAddress& src, 172 const RawAddress& dst, uint16_t protocol, 173 BT_HDR* p_buf, bool ext, bool forward) { 174 tBTA_PAN_SCB* p_scb = bta_pan_scb_by_handle(handle); 175 if (p_scb == NULL) { 176 return; 177 } 178 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 return; 185 } 186 187 BT_HDR* 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 193 /* copy params into the space before the data */ 194 ((tBTA_PAN_DATA_PARAMS*)p_new_buf)->src = src; 195 ((tBTA_PAN_DATA_PARAMS*)p_new_buf)->dst = dst; 196 ((tBTA_PAN_DATA_PARAMS*)p_new_buf)->protocol = protocol; 197 ((tBTA_PAN_DATA_PARAMS*)p_new_buf)->ext = ext; 198 ((tBTA_PAN_DATA_PARAMS*)p_new_buf)->forward = forward; 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 ******************************************************************************/ 217 static void bta_pan_pfilt_ind_cback(uint16_t handle, bool indication, 218 tBNEP_RESULT result, uint16_t num_filters, 219 uint8_t* p_filters) { 220 bta_pan_co_pfilt_ind( 221 handle, indication, 222 (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS 223 : BTA_PAN_FAIL), 224 num_filters, p_filters); 225 } 226 227 /******************************************************************************* 228 * 229 * Function bta_pan_mfilt_ind_cback 230 * 231 * Description 232 * 233 * 234 * Returns void 235 * 236 ******************************************************************************/ 237 static void bta_pan_mfilt_ind_cback(uint16_t handle, bool indication, 238 tBNEP_RESULT result, uint16_t num_mfilters, 239 uint8_t* p_mfilters) { 240 bta_pan_co_mfilt_ind( 241 handle, indication, 242 (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS 243 : BTA_PAN_FAIL), 244 num_mfilters, p_mfilters); 245 } 246 247 /******************************************************************************* 248 * 249 * Function bta_pan_has_multiple_connections 250 * 251 * Description Check whether there are multiple GN/NAP connections to 252 * different devices 253 * 254 * 255 * Returns bool 256 * 257 ******************************************************************************/ 258 static bool bta_pan_has_multiple_connections(uint8_t app_id) { 259 tBTA_PAN_SCB* p_scb = NULL; 260 bool found = false; 261 RawAddress bd_addr; 262 263 for (uint8_t index = 0; index < BTA_PAN_NUM_CONN; index++) { 264 p_scb = &bta_pan_cb.scb[index]; 265 if (p_scb->in_use && app_id == p_scb->app_id) { 266 /* save temp bd_addr */ 267 bd_addr = p_scb->bd_addr; 268 found = true; 269 break; 270 } 271 } 272 273 /* If cannot find a match then there is no connection at all */ 274 if (!found) return false; 275 276 /* Find whether there is another connection with different device other than 277 PANU. 278 Could be same service or different service */ 279 for (uint8_t index = 0; index < BTA_PAN_NUM_CONN; index++) { 280 p_scb = &bta_pan_cb.scb[index]; 281 if (p_scb->in_use && p_scb->app_id != bta_pan_cb.app_id[0] && 282 bd_addr != p_scb->bd_addr) { 283 return true; 284 } 285 } 286 return false; 287 } 288 289 /******************************************************************************* 290 * 291 * Function bta_pan_enable 292 * 293 * Description 294 * 295 * 296 * 297 * Returns void 298 * 299 ******************************************************************************/ 300 void bta_pan_enable(tBTA_PAN_DATA* p_data) { 301 tPAN_REGISTER reg_data; 302 uint16_t initial_discoverability; 303 uint16_t initial_connectability; 304 uint16_t d_window; 305 uint16_t d_interval; 306 uint16_t c_window; 307 uint16_t c_interval; 308 309 bta_pan_cb.p_cback = p_data->api_enable.p_cback; 310 311 reg_data.pan_conn_state_cb = bta_pan_conn_state_cback; 312 reg_data.pan_bridge_req_cb = NULL; 313 reg_data.pan_data_buf_ind_cb = bta_pan_data_buf_ind_cback; 314 reg_data.pan_data_ind_cb = NULL; 315 reg_data.pan_pfilt_ind_cb = bta_pan_pfilt_ind_cback; 316 reg_data.pan_mfilt_ind_cb = bta_pan_mfilt_ind_cback; 317 reg_data.pan_tx_data_flow_cb = bta_pan_data_flow_cb; 318 319 /* read connectability and discoverability settings. 320 Pan profile changes the settings. We have to change it back to 321 be consistent with other bta subsystems */ 322 initial_connectability = BTM_ReadConnectability(&c_window, &c_interval); 323 initial_discoverability = BTM_ReadDiscoverability(&d_window, &d_interval); 324 325 PAN_Register(®_data); 326 327 /* set it back to original value */ 328 BTM_SetDiscoverability(initial_discoverability, d_window, d_interval); 329 BTM_SetConnectability(initial_connectability, c_window, c_interval); 330 331 bta_pan_cb.flow_mask = bta_pan_co_init(&bta_pan_cb.q_level); 332 bta_pan_cb.p_cback(BTA_PAN_ENABLE_EVT, NULL); 333 } 334 335 /******************************************************************************* 336 * 337 * Function bta_pan_set_role 338 * 339 * Description 340 * 341 * Returns void 342 * 343 ******************************************************************************/ 344 void bta_pan_set_role(tBTA_PAN_DATA* p_data) { 345 tPAN_RESULT status; 346 tBTA_PAN bta_pan; 347 uint8_t sec[3]; 348 349 bta_pan_cb.app_id[0] = p_data->api_set_role.user_app_id; 350 bta_pan_cb.app_id[1] = p_data->api_set_role.gn_app_id; 351 bta_pan_cb.app_id[2] = p_data->api_set_role.nap_app_id; 352 353 sec[0] = p_data->api_set_role.user_sec_mask; 354 sec[1] = p_data->api_set_role.gn_sec_mask; 355 sec[2] = p_data->api_set_role.nap_sec_mask; 356 357 /* set security correctly in api and here */ 358 status = PAN_SetRole( 359 p_data->api_set_role.role, sec, p_data->api_set_role.user_name, 360 p_data->api_set_role.gn_name, p_data->api_set_role.nap_name); 361 362 bta_pan.set_role.role = p_data->api_set_role.role; 363 if (status == PAN_SUCCESS) { 364 if (p_data->api_set_role.role & PAN_ROLE_NAP_SERVER) 365 bta_sys_add_uuid(UUID_SERVCLASS_NAP); 366 else 367 bta_sys_remove_uuid(UUID_SERVCLASS_NAP); 368 369 if (p_data->api_set_role.role & PAN_ROLE_GN_SERVER) 370 bta_sys_add_uuid(UUID_SERVCLASS_GN); 371 else 372 bta_sys_remove_uuid(UUID_SERVCLASS_GN); 373 374 if (p_data->api_set_role.role & PAN_ROLE_CLIENT) 375 bta_sys_add_uuid(UUID_SERVCLASS_PANU); 376 else 377 bta_sys_remove_uuid(UUID_SERVCLASS_PANU); 378 379 bta_pan.set_role.status = BTA_PAN_SUCCESS; 380 } 381 /* if status is not success clear everything */ 382 else { 383 PAN_SetRole(0, 0, NULL, NULL, NULL); 384 bta_sys_remove_uuid(UUID_SERVCLASS_NAP); 385 bta_sys_remove_uuid(UUID_SERVCLASS_GN); 386 bta_sys_remove_uuid(UUID_SERVCLASS_PANU); 387 bta_pan.set_role.status = BTA_PAN_FAIL; 388 } 389 bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, &bta_pan); 390 } 391 392 /******************************************************************************* 393 * 394 * Function bta_pan_disable 395 * 396 * Description 397 * 398 * 399 * 400 * Returns void 401 * 402 ******************************************************************************/ 403 void bta_pan_disable(void) { 404 BT_HDR* p_buf; 405 tBTA_PAN_SCB* p_scb = &bta_pan_cb.scb[0]; 406 uint8_t i; 407 408 /* close all connections */ 409 PAN_SetRole(0, NULL, NULL, NULL, NULL); 410 411 #if (BTA_EIR_CANNED_UUID_LIST != TRUE) 412 bta_sys_remove_uuid(UUID_SERVCLASS_NAP); 413 bta_sys_remove_uuid(UUID_SERVCLASS_GN); 414 bta_sys_remove_uuid(UUID_SERVCLASS_PANU); 415 #endif // BTA_EIR_CANNED_UUID_LIST 416 /* free all queued up data buffers */ 417 for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) { 418 if (p_scb->in_use) { 419 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_scb->data_queue)) != 420 NULL) 421 osi_free(p_buf); 422 423 bta_pan_co_close(p_scb->handle, p_scb->app_id); 424 } 425 } 426 427 PAN_Deregister(); 428 } 429 430 /******************************************************************************* 431 * 432 * Function bta_pan_open 433 * 434 * Description 435 * 436 * Returns void 437 * 438 ******************************************************************************/ 439 void bta_pan_open(tBTA_PAN_SCB* p_scb, tBTA_PAN_DATA* p_data) { 440 tPAN_RESULT status; 441 tBTA_PAN bta_pan; 442 443 status = PAN_Connect(p_data->api_open.bd_addr, p_data->api_open.local_role, 444 p_data->api_open.peer_role, &p_scb->handle); 445 APPL_TRACE_DEBUG("%s pan connect status: %d", __func__, status); 446 447 if (status == PAN_SUCCESS) { 448 p_scb->bd_addr = p_data->api_open.bd_addr; 449 p_scb->local_role = p_data->api_open.local_role; 450 p_scb->peer_role = p_data->api_open.peer_role; 451 bta_pan.opening.bd_addr = p_data->api_open.bd_addr; 452 bta_pan.opening.handle = p_scb->handle; 453 bta_pan_cb.p_cback(BTA_PAN_OPENING_EVT, &bta_pan); 454 455 } else { 456 bta_pan_scb_dealloc(p_scb); 457 bta_pan.open.bd_addr = p_data->api_open.bd_addr; 458 bta_pan.open.status = BTA_PAN_FAIL; 459 bta_pan.open.local_role = p_data->api_open.local_role; 460 bta_pan.open.peer_role = p_data->api_open.peer_role; 461 bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, &bta_pan); 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, UNUSED_ATTR tBTA_PAN_DATA* p_data) { 477 tBTA_PAN_CONN* p_buf = (tBTA_PAN_CONN*)osi_malloc(sizeof(tBTA_PAN_CONN)); 478 479 PAN_Disconnect(p_scb->handle); 480 481 /* 482 * Send an event to BTA so that application will get the connection 483 * close event. 484 */ 485 p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT; 486 p_buf->hdr.layer_specific = p_scb->handle; 487 488 bta_sys_sendmsg(p_buf); 489 } 490 491 /******************************************************************************* 492 * 493 * Function bta_pan_conn_open 494 * 495 * Description process connection open event 496 * 497 * Returns void 498 * 499 ******************************************************************************/ 500 void bta_pan_conn_open(tBTA_PAN_SCB* p_scb, tBTA_PAN_DATA* p_data) { 501 tBTA_PAN bta_pan; 502 503 APPL_TRACE_DEBUG("%s pan connection result: %d", __func__, 504 p_data->conn.result); 505 506 bta_pan.open.bd_addr = p_scb->bd_addr; 507 bta_pan.open.handle = p_scb->handle; 508 bta_pan.open.local_role = p_scb->local_role; 509 bta_pan.open.peer_role = p_scb->peer_role; 510 511 if (p_data->conn.result == PAN_SUCCESS) { 512 bta_pan.open.status = BTA_PAN_SUCCESS; 513 p_scb->pan_flow_enable = true; 514 p_scb->app_flow_enable = true; 515 bta_sys_conn_open(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr); 516 } else { 517 bta_pan_scb_dealloc(p_scb); 518 bta_pan.open.status = BTA_PAN_FAIL; 519 } 520 521 p_scb->pan_flow_enable = true; 522 p_scb->app_flow_enable = true; 523 524 /* If app_id is NAP/GN, check whether there are multiple connections. 525 If there are, provide a special app_id to dm to enforce master role only. 526 */ 527 if ((p_scb->app_id == bta_pan_cb.app_id[1] || 528 p_scb->app_id == bta_pan_cb.app_id[2]) && 529 bta_pan_has_multiple_connections(p_scb->app_id)) { 530 p_scb->app_id = BTA_APP_ID_PAN_MULTI; 531 } 532 533 bta_sys_conn_open(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr); 534 bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, &bta_pan); 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 tBTA_PAN bta_pan; 550 BT_HDR* p_buf; 551 552 bta_pan.close.handle = p_data->hdr.layer_specific; 553 554 bta_sys_conn_close(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr); 555 556 /* free all queued up data buffers */ 557 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_scb->data_queue)) != NULL) 558 osi_free(p_buf); 559 560 bta_pan_scb_dealloc(p_scb); 561 562 bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, &bta_pan); 563 } 564 565 /******************************************************************************* 566 * 567 * Function bta_pan_rx_path 568 * 569 * Description Handle data on the RX path (data sent from the phone to 570 * BTA). 571 * 572 * 573 * Returns void 574 * 575 ******************************************************************************/ 576 void bta_pan_rx_path(tBTA_PAN_SCB* p_scb, UNUSED_ATTR tBTA_PAN_DATA* p_data) { 577 /* if data path configured for rx pull */ 578 if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL) { 579 /* if we can accept data */ 580 if (p_scb->pan_flow_enable) { 581 /* call application callout function for rx path */ 582 bta_pan_co_rx_path(p_scb->handle, p_scb->app_id); 583 } 584 } 585 /* else data path configured for rx push */ 586 else { 587 } 588 } 589 590 /******************************************************************************* 591 * 592 * Function bta_pan_tx_path 593 * 594 * Description Handle the TX data path (data sent from BTA to the phone). 595 * 596 * 597 * Returns void 598 * 599 ******************************************************************************/ 600 void bta_pan_tx_path(tBTA_PAN_SCB* p_scb, UNUSED_ATTR tBTA_PAN_DATA* p_data) { 601 bta_pan_pm_conn_busy(p_scb); 602 /* call application callout function for tx path */ 603 bta_pan_co_tx_path(p_scb->handle, p_scb->app_id); 604 605 /* free data that exceeds queue level */ 606 while (fixed_queue_length(p_scb->data_queue) > bta_pan_cb.q_level) { 607 BT_HDR* p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_scb->data_queue); 608 if (p_buf != nullptr) { 609 osi_free(p_buf); 610 } 611 } 612 613 bta_pan_pm_conn_idle(p_scb); 614 } 615 616 /******************************************************************************* 617 * 618 * Function bta_pan_tx_flow 619 * 620 * Description Set the application flow control state. 621 * 622 * 623 * Returns void 624 * 625 ******************************************************************************/ 626 void bta_pan_tx_flow(tBTA_PAN_SCB* p_scb, tBTA_PAN_DATA* p_data) { 627 p_scb->app_flow_enable = p_data->ci_tx_flow.enable; 628 } 629 630 /******************************************************************************* 631 * 632 * Function bta_pan_write_buf 633 * 634 * Description Handle a bta_pan_ci_rx_writebuf() and send data to PAN. 635 * 636 * 637 * Returns void 638 * 639 ******************************************************************************/ 640 void bta_pan_write_buf(tBTA_PAN_SCB* p_scb, tBTA_PAN_DATA* p_data) { 641 if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PUSH_BUF) { 642 bta_pan_pm_conn_busy(p_scb); 643 644 PAN_WriteBuf(p_scb->handle, ((tBTA_PAN_DATA_PARAMS*)p_data)->dst, 645 ((tBTA_PAN_DATA_PARAMS*)p_data)->src, 646 ((tBTA_PAN_DATA_PARAMS*)p_data)->protocol, (BT_HDR*)p_data, 647 ((tBTA_PAN_DATA_PARAMS*)p_data)->ext); 648 bta_pan_pm_conn_idle(p_scb); 649 } 650 } 651 652 /******************************************************************************* 653 * 654 * Function bta_pan_free_buf 655 * 656 * Description Frees the data buffer during closing state 657 * 658 * 659 * Returns void 660 * 661 ******************************************************************************/ 662 void bta_pan_free_buf(UNUSED_ATTR tBTA_PAN_SCB* p_scb, tBTA_PAN_DATA* p_data) { 663 osi_free(p_data); 664 } 665 666 #endif /* PAN_INCLUDED */ 667