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