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