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*******************************************************************************/ 54static 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*******************************************************************************/ 125static 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*******************************************************************************/ 166static 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*******************************************************************************/ 231static 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*******************************************************************************/ 252static 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*******************************************************************************/ 273void 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*******************************************************************************/ 321void 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*******************************************************************************/ 387void 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*******************************************************************************/ 431void 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*******************************************************************************/ 476void 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*******************************************************************************/ 505void 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*******************************************************************************/ 548void 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*******************************************************************************/ 587void 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*******************************************************************************/ 616void 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*******************************************************************************/ 681void 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*******************************************************************************/ 696void 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*******************************************************************************/ 721void 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