1 /****************************************************************************** 2 * 3 * Copyright (C) 2001-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 main BNEP functions 22 * 23 ******************************************************************************/ 24 25 #include "bt_target.h" 26 #include <stdlib.h> 27 #include <string.h> 28 #include <stdio.h> 29 30 #include "gki.h" 31 #include "bt_types.h" 32 #include "l2cdefs.h" 33 #include "hcidefs.h" 34 #include "hcimsgs.h" 35 36 #include "l2c_api.h" 37 #include "l2cdefs.h" 38 39 #include "btu.h" 40 #include "btm_api.h" 41 42 #include "bnep_api.h" 43 #include "bnep_int.h" 44 45 46 /********************************************************************************/ 47 /* G L O B A L B N E P D A T A */ 48 /********************************************************************************/ 49 #if BNEP_DYNAMIC_MEMORY == FALSE 50 tBNEP_CB bnep_cb; 51 #endif 52 53 const UINT16 bnep_frame_hdr_sizes[] = {14, 1, 2, 8, 8}; 54 55 /********************************************************************************/ 56 /* L O C A L F U N C T I O N P R O T O T Y P E S */ 57 /********************************************************************************/ 58 static void bnep_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id); 59 static void bnep_connect_cfm (UINT16 l2cap_cid, UINT16 result); 60 static void bnep_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 61 static void bnep_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 62 static void bnep_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed); 63 static void bnep_disconnect_cfm (UINT16 l2cap_cid, UINT16 result); 64 static void bnep_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg); 65 static void bnep_congestion_ind (UINT16 lcid, BOOLEAN is_congested); 66 67 static void bnep_read_addr_cb (void *p_bda); 68 69 70 /******************************************************************************* 71 ** 72 ** Function bnep_register_with_l2cap 73 ** 74 ** Description This function registers BNEP PSM with L2CAP 75 ** 76 ** Returns void 77 ** 78 *******************************************************************************/ 79 tBNEP_RESULT bnep_register_with_l2cap (void) 80 { 81 /* Initialize the L2CAP configuration. We only care about MTU and flush */ 82 memset(&bnep_cb.l2cap_my_cfg, 0, sizeof(tL2CAP_CFG_INFO)); 83 84 bnep_cb.l2cap_my_cfg.mtu_present = TRUE; 85 bnep_cb.l2cap_my_cfg.mtu = BNEP_MTU_SIZE; 86 bnep_cb.l2cap_my_cfg.flush_to_present = TRUE; 87 bnep_cb.l2cap_my_cfg.flush_to = BNEP_FLUSH_TO; 88 89 bnep_cb.reg_info.pL2CA_ConnectInd_Cb = bnep_connect_ind; 90 bnep_cb.reg_info.pL2CA_ConnectCfm_Cb = bnep_connect_cfm; 91 bnep_cb.reg_info.pL2CA_ConfigInd_Cb = bnep_config_ind; 92 bnep_cb.reg_info.pL2CA_ConfigCfm_Cb = bnep_config_cfm; 93 bnep_cb.reg_info.pL2CA_DisconnectInd_Cb = bnep_disconnect_ind; 94 bnep_cb.reg_info.pL2CA_DisconnectCfm_Cb = bnep_disconnect_cfm; 95 bnep_cb.reg_info.pL2CA_DataInd_Cb = bnep_data_ind; 96 bnep_cb.reg_info.pL2CA_CongestionStatus_Cb = bnep_congestion_ind; 97 98 /* Now, register with L2CAP */ 99 if (!L2CA_Register (BT_PSM_BNEP, &bnep_cb.reg_info)) 100 { 101 BNEP_TRACE_ERROR0 ("BNEP - Registration failed"); 102 return BNEP_SECURITY_FAIL; 103 } 104 105 return BNEP_SUCCESS; 106 } 107 108 109 /******************************************************************************* 110 ** 111 ** Function bnep_connect_ind 112 ** 113 ** Description This function handles an inbound connection indication 114 ** from L2CAP. This is the case where we are acting as a 115 ** server. 116 ** 117 ** Returns void 118 ** 119 *******************************************************************************/ 120 static void bnep_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id) 121 { 122 tBNEP_CONN *p_bcb = bnepu_find_bcb_by_bd_addr (bd_addr); 123 124 /* If we are not acting as server, or already have a connection, or have */ 125 /* no more resources to handle the connection, reject the connection. */ 126 if (!(bnep_cb.profile_registered) || (p_bcb) 127 || ((p_bcb = bnepu_allocate_bcb(bd_addr)) == NULL)) 128 { 129 L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0); 130 return; 131 } 132 133 /* Transition to the next appropriate state, waiting for config setup. */ 134 p_bcb->con_state = BNEP_STATE_CFG_SETUP; 135 136 /* Save the L2CAP Channel ID. */ 137 p_bcb->l2cap_cid = l2cap_cid; 138 139 /* Send response to the L2CAP layer. */ 140 L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); 141 142 /* Send a Configuration Request. */ 143 L2CA_ConfigReq (l2cap_cid, &bnep_cb.l2cap_my_cfg); 144 145 /* Start timer waiting for config setup */ 146 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT); 147 148 BNEP_TRACE_EVENT1("BNEP - Rcvd L2CAP conn ind, CID: 0x%x", p_bcb->l2cap_cid); 149 150 } 151 152 153 /******************************************************************************* 154 ** 155 ** Function bnep_connect_cfm 156 ** 157 ** Description This function handles the connect confirm events 158 ** from L2CAP. This is the case when we are acting as a 159 ** client and have sent a connect request. 160 ** 161 ** Returns void 162 ** 163 *******************************************************************************/ 164 static void bnep_connect_cfm (UINT16 l2cap_cid, UINT16 result) 165 { 166 tBNEP_CONN *bcb; 167 168 /* Find CCB based on CID */ 169 if ((bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL) 170 { 171 BNEP_TRACE_WARNING1 ("BNEP - Rcvd conn cnf for unknown CID 0x%x", l2cap_cid); 172 return; 173 } 174 175 /* If the connection response contains success status, then */ 176 /* Transition to the next state and startup the timer. */ 177 if ((result == L2CAP_CONN_OK) && (bcb->con_state == BNEP_STATE_CONN_START)) 178 { 179 bcb->con_state = BNEP_STATE_CFG_SETUP; 180 181 /* Send a Configuration Request. */ 182 L2CA_ConfigReq (l2cap_cid, &bnep_cb.l2cap_my_cfg); 183 184 /* Start timer waiting for config results */ 185 btu_start_timer (&bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT); 186 187 BNEP_TRACE_EVENT1 ("BNEP - got conn cnf, sent cfg req, CID: 0x%x", bcb->l2cap_cid); 188 } 189 else 190 { 191 BNEP_TRACE_WARNING2 ("BNEP - Rcvd conn cnf with error: 0x%x CID 0x%x", result, bcb->l2cap_cid); 192 193 /* Tell the upper layer, if he has a callback */ 194 if (bnep_cb.p_conn_state_cb && 195 bcb->con_flags & BNEP_FLAGS_IS_ORIG) 196 { 197 (*bnep_cb.p_conn_state_cb) (bcb->handle, bcb->rem_bda, BNEP_CONN_FAILED, FALSE); 198 } 199 200 bnepu_release_bcb (bcb); 201 } 202 } 203 204 /******************************************************************************* 205 ** 206 ** Function bnep_config_ind 207 ** 208 ** Description This function processes the L2CAP configuration indication 209 ** event. 210 ** 211 ** Returns void 212 ** 213 *******************************************************************************/ 214 static void bnep_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) 215 { 216 tBNEP_CONN *p_bcb; 217 UINT16 result, mtu = 0; 218 219 /* Find CCB based on CID */ 220 if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL) 221 { 222 BNEP_TRACE_WARNING1 ("BNEP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid); 223 return; 224 } 225 226 BNEP_TRACE_EVENT1 ("BNEP - Rcvd cfg ind, CID: 0x%x", l2cap_cid); 227 228 /* Remember the remote MTU size */ 229 if ((!p_cfg->mtu_present) || (p_cfg->mtu < BNEP_MIN_MTU_SIZE)) 230 { 231 mtu = p_cfg->mtu; 232 p_cfg->flush_to_present = FALSE; 233 p_cfg->mtu_present = TRUE; 234 p_cfg->mtu = BNEP_MIN_MTU_SIZE; 235 p_cfg->result = result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 236 } 237 else 238 { 239 if (p_cfg->mtu > BNEP_MTU_SIZE) 240 p_bcb->rem_mtu_size = BNEP_MTU_SIZE; 241 else 242 p_bcb->rem_mtu_size = p_cfg->mtu; 243 244 /* For now, always accept configuration from the other side */ 245 p_cfg->flush_to_present = FALSE; 246 p_cfg->mtu_present = FALSE; 247 p_cfg->result = result = L2CAP_CFG_OK; 248 } 249 250 L2CA_ConfigRsp (l2cap_cid, p_cfg); 251 252 if (result != L2CAP_CFG_OK) 253 { 254 BNEP_TRACE_EVENT2 ("BNEP - Rcvd cfg ind with bad MTU %d, CID: 0x%x", mtu, l2cap_cid); 255 return; 256 } 257 258 p_bcb->con_flags |= BNEP_FLAGS_HIS_CFG_DONE; 259 260 if (p_bcb->con_flags & BNEP_FLAGS_MY_CFG_DONE) 261 { 262 p_bcb->con_state = BNEP_STATE_SEC_CHECKING; 263 264 /* Start timer waiting for setup or response */ 265 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_HOST_TIMEOUT); 266 267 if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) 268 { 269 btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE, 270 BTM_SEC_PROTO_BNEP, 271 bnep_get_uuid32(&(p_bcb->src_uuid)), 272 &bnep_sec_check_complete, p_bcb); 273 } 274 } 275 } 276 277 278 /******************************************************************************* 279 ** 280 ** Function bnep_config_cfm 281 ** 282 ** Description This function processes the L2CAP configuration confirmation 283 ** event. 284 ** 285 ** Returns void 286 ** 287 *******************************************************************************/ 288 static void bnep_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) 289 { 290 tBNEP_CONN *p_bcb; 291 292 BNEP_TRACE_EVENT2 ("BNEP - Rcvd cfg cfm, CID: 0x%x Result: %d", l2cap_cid, p_cfg->result); 293 294 /* Find CCB based on CID */ 295 if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL) 296 { 297 BNEP_TRACE_WARNING1 ("BNEP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid); 298 return; 299 } 300 301 /* For now, always accept configuration from the other side */ 302 if (p_cfg->result == L2CAP_CFG_OK) 303 { 304 p_bcb->con_flags |= BNEP_FLAGS_MY_CFG_DONE; 305 306 if (p_bcb->con_flags & BNEP_FLAGS_HIS_CFG_DONE) 307 { 308 p_bcb->con_state = BNEP_STATE_SEC_CHECKING; 309 310 /* Start timer waiting for setup or response */ 311 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_HOST_TIMEOUT); 312 313 if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) 314 { 315 btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE, 316 BTM_SEC_PROTO_BNEP, 317 bnep_get_uuid32(&(p_bcb->src_uuid)), 318 &bnep_sec_check_complete, p_bcb); 319 } 320 } 321 } 322 else 323 { 324 /* Tell the upper layer, if he has a callback */ 325 if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) 326 { 327 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED_CFG, FALSE); 328 } 329 330 L2CA_DisconnectReq (p_bcb->l2cap_cid); 331 332 bnepu_release_bcb (p_bcb); 333 } 334 } 335 336 337 /******************************************************************************* 338 ** 339 ** Function bnep_disconnect_ind 340 ** 341 ** Description This function handles a disconnect event from L2CAP. If 342 ** requested to, we ack the disconnect before dropping the CCB 343 ** 344 ** Returns void 345 ** 346 *******************************************************************************/ 347 static void bnep_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed) 348 { 349 tBNEP_CONN *p_bcb; 350 351 if (ack_needed) 352 L2CA_DisconnectRsp (l2cap_cid); 353 354 /* Find CCB based on CID */ 355 if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL) 356 { 357 BNEP_TRACE_WARNING1 ("BNEP - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid); 358 return; 359 } 360 361 BNEP_TRACE_EVENT1 ("BNEP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid); 362 363 /* Tell the user if he has a callback */ 364 if (p_bcb->con_state == BNEP_STATE_CONNECTED) 365 { 366 if (bnep_cb.p_conn_state_cb) 367 (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_DISCONNECTED, FALSE); 368 } 369 else 370 { 371 if (((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) || 372 p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) 373 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE); 374 } 375 376 bnepu_release_bcb (p_bcb); 377 } 378 379 380 381 /******************************************************************************* 382 ** 383 ** Function bnep_disconnect_cfm 384 ** 385 ** Description This function gets the disconnect confirm event from L2CAP 386 ** 387 ** Returns void 388 ** 389 *******************************************************************************/ 390 static void bnep_disconnect_cfm (UINT16 l2cap_cid, UINT16 result) 391 { 392 BNEP_TRACE_EVENT2 ("BNEP - Rcvd L2CAP disc cfm, CID: 0x%x, Result 0x%x", l2cap_cid, result); 393 } 394 395 396 397 /******************************************************************************* 398 ** 399 ** Function bnep_congestion_ind 400 ** 401 ** Description This is a callback function called by L2CAP when 402 ** congestion status changes 403 ** 404 *******************************************************************************/ 405 static void bnep_congestion_ind (UINT16 l2cap_cid, BOOLEAN is_congested) 406 { 407 tBNEP_CONN *p_bcb; 408 409 /* Find BCB based on CID */ 410 if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL) 411 { 412 BNEP_TRACE_WARNING1 ("BNEP - Rcvd L2CAP cong, unknown CID: 0x%x", l2cap_cid); 413 return; 414 } 415 416 if (is_congested) 417 { 418 p_bcb->con_flags |= BNEP_FLAGS_L2CAP_CONGESTED; 419 if(bnep_cb.p_tx_data_flow_cb) 420 { 421 bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_OFF); 422 } 423 } 424 else 425 { 426 p_bcb->con_flags &= ~BNEP_FLAGS_L2CAP_CONGESTED; 427 428 if(bnep_cb.p_tx_data_flow_cb) 429 { 430 bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_ON); 431 } 432 433 /* While not congested, send as many buffers as we can */ 434 while (!(p_bcb->con_flags & BNEP_FLAGS_L2CAP_CONGESTED)) 435 { 436 BT_HDR *p_buf = (BT_HDR *)GKI_dequeue (&p_bcb->xmit_q); 437 438 if (!p_buf) 439 break; 440 441 L2CA_DataWrite (l2cap_cid, p_buf); 442 } 443 } 444 } 445 446 447 448 /******************************************************************************* 449 ** 450 ** Function bnep_data_ind 451 ** 452 ** Description This function is called when data is received from L2CAP. 453 ** if we are the originator of the connection, we are the SDP 454 ** client, and the received message is queued up for the client. 455 ** 456 ** If we are the destination of the connection, we are the SDP 457 ** server, so the message is passed to the server processing 458 ** function. 459 ** 460 ** Returns void 461 ** 462 *******************************************************************************/ 463 static void bnep_data_ind (UINT16 l2cap_cid, BT_HDR *p_buf) 464 { 465 tBNEP_CONN *p_bcb; 466 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; 467 UINT16 rem_len = p_buf->len; 468 UINT8 type, ctrl_type, ext_type = 0; 469 BOOLEAN extension_present, fw_ext_present; 470 UINT16 protocol = 0; 471 UINT8 *p_src_addr, *p_dst_addr; 472 473 474 /* Find CCB based on CID */ 475 if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL) 476 { 477 BNEP_TRACE_WARNING1 ("BNEP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid); 478 GKI_freebuf (p_buf); 479 return; 480 } 481 482 /* Get the type and extension bits */ 483 type = *p++; 484 extension_present = type >> 7; 485 type &= 0x7f; 486 if ((rem_len <= bnep_frame_hdr_sizes[type]) || (rem_len > BNEP_MTU_SIZE)) 487 { 488 BNEP_TRACE_EVENT2 ("BNEP - rcvd frame, bad len: %d type: 0x%02x", p_buf->len, type); 489 GKI_freebuf (p_buf); 490 return; 491 } 492 493 rem_len--; 494 495 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) && 496 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)) && 497 (type != BNEP_FRAME_CONTROL)) 498 { 499 BNEP_TRACE_WARNING2 ("BNEP - Ignored L2CAP data while in state: %d, CID: 0x%x", 500 p_bcb->con_state, l2cap_cid); 501 502 if (extension_present) 503 { 504 /* 505 ** When there is no connection if a data packet is received 506 ** with unknown control extension headers then those should be processed 507 ** according to complain/ignore law 508 */ 509 UINT8 ext, length, *p_data; 510 UINT16 org_len, new_len; 511 /* parse the extension headers and process unknown control headers */ 512 org_len = rem_len; 513 new_len = 0; 514 p_data = p; 515 do { 516 517 ext = *p++; 518 length = *p++; 519 p += length; 520 521 if ((!(ext & 0x7F)) && (*p > BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG)) 522 bnep_send_command_not_understood (p_bcb, *p); 523 524 new_len += (length + 2); 525 526 if (new_len > org_len) 527 break; 528 529 } while (ext & 0x80); 530 } 531 532 GKI_freebuf (p_buf); 533 return; 534 } 535 536 if (type > BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY) 537 { 538 BNEP_TRACE_EVENT1 ("BNEP - rcvd frame, unknown type: 0x%02x", type); 539 GKI_freebuf (p_buf); 540 return; 541 } 542 543 BNEP_TRACE_DEBUG3 ("BNEP - rcv frame, type: %d len: %d Ext: %d", type, p_buf->len, extension_present); 544 545 /* Initialize addresses to 'not supplied' */ 546 p_src_addr = p_dst_addr = NULL; 547 548 switch (type) 549 { 550 case BNEP_FRAME_GENERAL_ETHERNET: 551 p_dst_addr = p; 552 p += BD_ADDR_LEN; 553 p_src_addr = p; 554 p += BD_ADDR_LEN; 555 BE_STREAM_TO_UINT16 (protocol, p); 556 rem_len -= 14; 557 break; 558 559 case BNEP_FRAME_CONTROL: 560 ctrl_type = *p; 561 p = bnep_process_control_packet (p_bcb, p, &rem_len, FALSE); 562 563 if (ctrl_type == BNEP_SETUP_CONNECTION_REQUEST_MSG && 564 p_bcb->con_state != BNEP_STATE_CONNECTED && 565 extension_present && p && rem_len) 566 { 567 p_bcb->p_pending_data = (BT_HDR *)GKI_getbuf (rem_len); 568 if (p_bcb->p_pending_data) 569 { 570 memcpy ((UINT8 *)(p_bcb->p_pending_data + 1), p, rem_len); 571 p_bcb->p_pending_data->len = rem_len; 572 p_bcb->p_pending_data->offset = 0; 573 } 574 } 575 else 576 { 577 while (extension_present && p && rem_len) 578 { 579 ext_type = *p++; 580 extension_present = ext_type >> 7; 581 ext_type &= 0x7F; 582 583 /* if unknown extension present stop processing */ 584 if (ext_type) 585 break; 586 587 p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE); 588 } 589 } 590 GKI_freebuf (p_buf); 591 return; 592 593 case BNEP_FRAME_COMPRESSED_ETHERNET: 594 BE_STREAM_TO_UINT16 (protocol, p); 595 rem_len -= 2; 596 break; 597 598 case BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY: 599 p_src_addr = p; 600 p += BD_ADDR_LEN; 601 BE_STREAM_TO_UINT16 (protocol, p); 602 rem_len -= 8; 603 break; 604 605 case BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY: 606 p_dst_addr = p; 607 p += BD_ADDR_LEN; 608 BE_STREAM_TO_UINT16 (protocol, p); 609 rem_len -= 8; 610 break; 611 } 612 613 /* Process the header extension if there is one */ 614 while (extension_present && p && rem_len) 615 { 616 ext_type = *p; 617 extension_present = ext_type >> 7; 618 ext_type &= 0x7F; 619 620 /* if unknown extension present stop processing */ 621 if (ext_type) 622 { 623 BNEP_TRACE_EVENT1 ("Data extension type 0x%x found", ext_type); 624 break; 625 } 626 627 p++; 628 rem_len--; 629 p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE); 630 } 631 632 p_buf->offset += p_buf->len - rem_len; 633 p_buf->len = rem_len; 634 635 /* Always give the upper layer MAC addresses */ 636 if (!p_src_addr) 637 p_src_addr = (UINT8 *) p_bcb->rem_bda; 638 639 if (!p_dst_addr) 640 p_dst_addr = (UINT8 *) bnep_cb.my_bda; 641 642 /* check whether there are any extensions to be forwarded */ 643 if (ext_type) 644 fw_ext_present = TRUE; 645 else 646 fw_ext_present = FALSE; 647 648 if (bnep_cb.p_data_buf_cb) 649 { 650 (*bnep_cb.p_data_buf_cb)(p_bcb->handle, p_src_addr, p_dst_addr, protocol, p_buf, fw_ext_present); 651 } 652 else if (bnep_cb.p_data_ind_cb) 653 { 654 (*bnep_cb.p_data_ind_cb)(p_bcb->handle, p_src_addr, p_dst_addr, protocol, p, rem_len, fw_ext_present); 655 GKI_freebuf (p_buf); 656 } 657 } 658 659 660 661 /******************************************************************************* 662 ** 663 ** Function bnep_process_timeout 664 ** 665 ** Description This function processes a timeout. If it is a startup 666 ** timeout, we check for reading our BD address. If it 667 ** is an L2CAP timeout, we send a disconnect req to L2CAP. 668 ** 669 ** Returns void 670 ** 671 *******************************************************************************/ 672 void bnep_process_timeout (TIMER_LIST_ENT *p_tle) 673 { 674 tBNEP_CONN *p_bcb; 675 676 if (!p_tle->param) 677 { 678 if (!bnep_cb.got_my_bd_addr) 679 { 680 if (BTM_IsDeviceUp()) 681 BTM_ReadLocalDeviceAddr (bnep_read_addr_cb); 682 683 btu_start_timer (&bnep_cb.bnep_tle, BTU_TTYPE_BNEP, 2); 684 } 685 return; 686 } 687 688 p_bcb = (tBNEP_CONN *)p_tle->param; 689 690 BNEP_TRACE_EVENT4 ("BNEP - CCB timeout in state: %d CID: 0x%x flags %x, re_transmit %d", 691 p_bcb->con_state, p_bcb->l2cap_cid, p_bcb->con_flags, p_bcb->re_transmits); 692 693 if (p_bcb->con_state == BNEP_STATE_CONN_SETUP) 694 { 695 BNEP_TRACE_EVENT2 ("BNEP - CCB timeout in state: %d CID: 0x%x", 696 p_bcb->con_state, p_bcb->l2cap_cid); 697 698 if (!(p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)) 699 { 700 L2CA_DisconnectReq (p_bcb->l2cap_cid); 701 702 bnepu_release_bcb (p_bcb); 703 return; 704 } 705 706 if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS) 707 { 708 bnep_send_conn_req (p_bcb); 709 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT); 710 } 711 else 712 { 713 L2CA_DisconnectReq (p_bcb->l2cap_cid); 714 715 if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) 716 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE); 717 718 bnepu_release_bcb (p_bcb); 719 return; 720 } 721 } 722 else if (p_bcb->con_state != BNEP_STATE_CONNECTED) 723 { 724 BNEP_TRACE_EVENT2 ("BNEP - CCB timeout in state: %d CID: 0x%x", 725 p_bcb->con_state, p_bcb->l2cap_cid); 726 727 L2CA_DisconnectReq (p_bcb->l2cap_cid); 728 729 /* Tell the user if he has a callback */ 730 if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) 731 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE); 732 733 bnepu_release_bcb (p_bcb); 734 } 735 #if (defined (BNEP_SUPPORTS_PROT_FILTERS) && BNEP_SUPPORTS_PROT_FILTERS == TRUE) 736 else if (p_bcb->con_flags & BNEP_FLAGS_FILTER_RESP_PEND) 737 { 738 if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS) 739 { 740 bnepu_send_peer_our_filters (p_bcb); 741 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT); 742 } 743 else 744 { 745 L2CA_DisconnectReq (p_bcb->l2cap_cid); 746 747 /* Tell the user if he has a callback */ 748 if (bnep_cb.p_conn_state_cb) 749 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, FALSE); 750 751 bnepu_release_bcb (p_bcb); 752 return; 753 } 754 } 755 #endif 756 #if (defined (BNEP_SUPPORTS_MULTI_FILTERS) && BNEP_SUPPORTS_MULTI_FILTERS == TRUE) 757 else if (p_bcb->con_flags & BNEP_FLAGS_MULTI_RESP_PEND) 758 { 759 if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS) 760 { 761 bnepu_send_peer_our_multi_filters (p_bcb); 762 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT); 763 } 764 else 765 { 766 L2CA_DisconnectReq (p_bcb->l2cap_cid); 767 768 /* Tell the user if he has a callback */ 769 if (bnep_cb.p_conn_state_cb) 770 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, FALSE); 771 772 bnepu_release_bcb (p_bcb); 773 return; 774 } 775 } 776 #endif 777 } 778 779 780 /******************************************************************************* 781 ** 782 ** Function bnep_connected 783 ** 784 ** Description This function is called when a connection is established 785 ** (after config). 786 ** 787 ** Returns void 788 ** 789 *******************************************************************************/ 790 void bnep_connected (tBNEP_CONN *p_bcb) 791 { 792 BOOLEAN is_role_change; 793 794 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) 795 is_role_change = TRUE; 796 else 797 is_role_change = FALSE; 798 799 p_bcb->con_state = BNEP_STATE_CONNECTED; 800 p_bcb->con_flags |= BNEP_FLAGS_CONN_COMPLETED; 801 p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD); 802 803 /* Ensure timer is stopped */ 804 btu_stop_timer (&p_bcb->conn_tle); 805 p_bcb->re_transmits = 0; 806 807 /* Tell the upper layer, if he has a callback */ 808 if (bnep_cb.p_conn_state_cb) 809 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SUCCESS, is_role_change); 810 } 811 812 813 /******************************************************************************* 814 ** 815 ** Function bnep_read_addr_cb 816 ** 817 ** Description This function is called by BTM when the local BD address 818 ** is read. It saves the BD address, and flags it as read. 819 ** 820 ** Returns void 821 ** 822 *******************************************************************************/ 823 static void bnep_read_addr_cb (void *p_bda) 824 { 825 UINT8 *bda = (UINT8 *)p_bda; 826 if (p_bda && 827 (bda[0] | bda[1] | bda[2] | bda[3] | bda[4] | bda[5]) != 0) 828 { 829 /* Save my BD address */ 830 memcpy (bnep_cb.my_bda, p_bda, BD_ADDR_LEN); 831 832 bnep_cb.got_my_bd_addr = TRUE; 833 } 834 else 835 /* Retry after a couple seconds */ 836 btu_start_timer (&bnep_cb.bnep_tle, BTU_TTYPE_BNEP, 2); 837 } 838 839