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