1/****************************************************************************** 2 * 3 * Copyright (C) 1999-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 L2CAP UCD code 22 * 23 ******************************************************************************/ 24 25#include <stdlib.h> 26#include <string.h> 27#include <stdio.h> 28 29#include "bt_common.h" 30#include "bt_types.h" 31#include "hcidefs.h" 32#include "hcimsgs.h" 33#include "l2cdefs.h" 34#include "l2c_int.h" 35#include "btu.h" 36#include "btm_api.h" 37#include "btm_int.h" 38 39#if (L2CAP_UCD_INCLUDED == TRUE) 40 41extern fixed_queue_t *btu_bta_alarm_queue; 42 43static BOOLEAN l2c_ucd_connect ( BD_ADDR rem_bda ); 44 45/******************************************************************************* 46** 47** Function l2c_ucd_discover_cback 48** 49** Description UCD Discover callback 50** 51** Returns void 52** 53*******************************************************************************/ 54static void l2c_ucd_discover_cback (BD_ADDR rem_bda, UINT8 info_type, UINT32 data) 55{ 56 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0]; 57 UINT16 xx; 58 59 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_discover_cback"); 60 61 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) 62 { 63 if (p_rcb->in_use) 64 { 65 /* if this application is waiting UCD reception info */ 66 if (( info_type == L2CAP_UCD_INFO_TYPE_RECEPTION ) 67 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION )) 68 { 69 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data); 70 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_RECEPTION); 71 } 72 73 /* if this application is waiting UCD MTU info */ 74 if (( info_type == L2CAP_UCD_INFO_TYPE_MTU ) 75 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU )) 76 { 77 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data); 78 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_MTU); 79 } 80 } 81 } 82} 83 84/******************************************************************************* 85** 86** Function l2c_ucd_data_ind_cback 87** 88** Description UCD Data callback 89** 90** Returns void 91** 92*******************************************************************************/ 93static void l2c_ucd_data_ind_cback (BD_ADDR rem_bda, BT_HDR *p_buf) 94{ 95 UINT8 *p; 96 UINT16 psm; 97 tL2C_RCB *p_rcb; 98 99 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_data_ind_cback"); 100 101 p = (UINT8 *)(p_buf + 1) + p_buf->offset; 102 STREAM_TO_UINT16(psm, p) 103 104 p_buf->offset += L2CAP_UCD_OVERHEAD; 105 p_buf->len -= L2CAP_UCD_OVERHEAD; 106 107 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) 108 { 109 L2CAP_TRACE_ERROR ("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x", psm); 110 osi_free(p_buf); 111 } 112 else 113 { 114 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf); 115 } 116} 117 118/******************************************************************************* 119** 120** Function l2c_ucd_congestion_status_cback 121** 122** Description UCD Congestion Status callback 123** 124** Returns void 125** 126*******************************************************************************/ 127static void l2c_ucd_congestion_status_cback (BD_ADDR rem_bda, BOOLEAN is_congested) 128{ 129 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0]; 130 UINT16 xx; 131 132 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_congestion_status_cback"); 133 134 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) 135 { 136 if (( p_rcb->in_use ) 137 &&( p_rcb->ucd.state != L2C_UCD_STATE_UNUSED )) 138 { 139 if ( p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) 140 { 141 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCDCongestionStatus_Cb (%d), PSM=0x%04x, BDA: %08x%04x,", 142 is_congested, p_rcb->psm, 143 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 144 (rem_bda[4]<<8)+rem_bda[5]); 145 146 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ( rem_bda, is_congested ); 147 } 148 } 149 } 150} 151 152/******************************************************************************* 153** 154** Function l2c_ucd_disconnect_ind_cback 155** 156** Description UCD disconnect callback (This prevent to access null pointer) 157** 158** Returns void 159** 160*******************************************************************************/ 161static void l2c_ucd_disconnect_ind_cback (UINT16 cid, BOOLEAN result) 162{ 163 /* do nothing */ 164} 165 166/******************************************************************************* 167** 168** Function l2c_ucd_config_ind_cback 169** 170** Description UCD config callback (This prevent to access null pointer) 171** 172** Returns void 173** 174*******************************************************************************/ 175static void l2c_ucd_config_ind_cback (UINT16 cid, tL2CAP_CFG_INFO *p_cfg) 176{ 177 /* do nothing */ 178} 179 180/******************************************************************************* 181** 182** Function l2c_ucd_config_cfm_cback 183** 184** Description UCD config callback (This prevent to access null pointer) 185** 186** Returns void 187** 188*******************************************************************************/ 189static void l2c_ucd_config_cfm_cback (UINT16 cid, tL2CAP_CFG_INFO *p_cfg) 190{ 191 /* do nothing */ 192} 193 194/******************************************************************************* 195** 196** Function L2CA_UcdRegister 197** 198** Description Register PSM on UCD. 199** 200** Parameters: tL2CAP_UCD_CB_INFO 201** 202** Return value: TRUE if successs 203** 204*******************************************************************************/ 205BOOLEAN L2CA_UcdRegister ( UINT16 psm, tL2CAP_UCD_CB_INFO *p_cb_info ) 206{ 207 tL2C_RCB *p_rcb; 208 209 L2CAP_TRACE_API ("L2CA_UcdRegister() PSM: 0x%04x", psm); 210 211 if ((!p_cb_info->pL2CA_UCD_Discover_Cb) 212 || (!p_cb_info->pL2CA_UCD_Data_Cb)) 213 { 214 L2CAP_TRACE_ERROR ("L2CAP - no callback registering PSM(0x%04x) on UCD", psm); 215 return (FALSE); 216 } 217 218 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) 219 { 220 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm); 221 return (FALSE); 222 } 223 224 p_rcb->ucd.state = L2C_UCD_STATE_W4_DATA; 225 p_rcb->ucd.cb_info = *p_cb_info; 226 227 /* check if master rcb is created for UCD */ 228 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL) 229 { 230 if ((p_rcb = l2cu_allocate_rcb (L2C_UCD_RCB_ID)) == NULL) 231 { 232 L2CAP_TRACE_ERROR ("L2CAP - no RCB available for L2CA_UcdRegister"); 233 return (FALSE); 234 } 235 else 236 { 237 /* these callback functions will forward data to each UCD application */ 238 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb = l2c_ucd_discover_cback; 239 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb = l2c_ucd_data_ind_cback; 240 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb = l2c_ucd_congestion_status_cback; 241 242 memset (&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO)); 243 p_rcb->api.pL2CA_DisconnectInd_Cb = l2c_ucd_disconnect_ind_cback; 244 245 /* This will make L2CAP check UCD congestion callback */ 246 p_rcb->api.pL2CA_CongestionStatus_Cb = NULL; 247 248 /* do nothing but prevent crash */ 249 p_rcb->api.pL2CA_ConfigInd_Cb = l2c_ucd_config_ind_cback; 250 p_rcb->api.pL2CA_ConfigCfm_Cb = l2c_ucd_config_cfm_cback; 251 } 252 } 253 254 return (TRUE); 255} 256 257/******************************************************************************* 258** 259** Function L2CA_UcdDeregister 260** 261** Description Deregister PSM on UCD. 262** 263** Parameters: PSM 264** 265** Return value: TRUE if successs 266** 267*******************************************************************************/ 268BOOLEAN L2CA_UcdDeregister ( UINT16 psm ) 269{ 270 tL2C_CCB *p_ccb; 271 tL2C_RCB *p_rcb; 272 UINT16 xx; 273 274 L2CAP_TRACE_API ("L2CA_UcdDeregister() PSM: 0x%04x", psm); 275 276 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) 277 { 278 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x", psm); 279 return (FALSE); 280 } 281 282 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED; 283 284 /* check this was the last UCD registration */ 285 p_rcb = &l2cb.rcb_pool[0]; 286 287 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) 288 { 289 if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED)) 290 return (TRUE); 291 } 292 293 /* delete master rcb for UCD */ 294 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL) 295 { 296 l2cu_release_rcb (p_rcb); 297 } 298 299 /* delete CCB for UCD */ 300 p_ccb = l2cb.ccb_pool; 301 for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ ) 302 { 303 if (( p_ccb->in_use ) 304 &&( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )) 305 { 306 l2cu_release_ccb (p_ccb); 307 } 308 p_ccb++; 309 } 310 311 return (TRUE); 312} 313 314/******************************************************************************* 315** 316** Function L2CA_UcdDiscover 317** 318** Description Discover UCD of remote device. 319** 320** Parameters: PSM 321** BD_ADDR of remote device 322** info_type : L2CAP_UCD_INFO_TYPE_RECEPTION 323** L2CAP_UCD_INFO_TYPE_MTU 324** 325** 326** Return value: TRUE if successs 327** 328*******************************************************************************/ 329BOOLEAN L2CA_UcdDiscover ( UINT16 psm, BD_ADDR rem_bda, UINT8 info_type ) 330{ 331 tL2C_LCB *p_lcb; 332 tL2C_CCB *p_ccb; 333 tL2C_RCB *p_rcb; 334 335 L2CAP_TRACE_API ("L2CA_UcdDiscover() PSM: 0x%04x BDA: %08x%04x, InfoType=0x%02x", psm, 336 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 337 (rem_bda[4]<<8)+rem_bda[5], info_type); 338 339 /* Fail if the PSM is not registered */ 340 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) 341 ||( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED )) 342 { 343 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x", psm); 344 return (FALSE); 345 } 346 347 /* First, see if we already have a link to the remote */ 348 /* then find the channel control block for UCD. */ 349 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) 350 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) 351 { 352 if ( l2c_ucd_connect (rem_bda) == FALSE ) 353 { 354 return (FALSE); 355 } 356 } 357 358 /* set waiting flags in rcb */ 359 360 if ( info_type & L2CAP_UCD_INFO_TYPE_RECEPTION ) 361 p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION; 362 363 if ( info_type & L2CAP_UCD_INFO_TYPE_MTU ) 364 p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU; 365 366 /* if link is already established */ 367 if ((p_lcb)&&(p_lcb->link_state == LST_CONNECTED)) 368 { 369 if (!p_ccb) 370 { 371 p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID); 372 } 373 l2c_ucd_check_pending_info_req(p_ccb); 374 } 375 return (TRUE); 376} 377 378/******************************************************************************* 379** 380** Function L2CA_UcdDataWrite 381** 382** Description Send UCD to remote device 383** 384** Parameters: PSM 385** BD Address of remote 386** Pointer to buffer of type BT_HDR 387** flags : L2CAP_FLUSHABLE_CH_BASED 388** L2CAP_FLUSHABLE_PKT 389** L2CAP_NON_FLUSHABLE_PKT 390** 391** Return value L2CAP_DW_SUCCESS, if data accepted 392** L2CAP_DW_FAILED, if error 393** 394*******************************************************************************/ 395UINT16 L2CA_UcdDataWrite (UINT16 psm, BD_ADDR rem_bda, BT_HDR *p_buf, UINT16 flags) 396{ 397 tL2C_LCB *p_lcb; 398 tL2C_CCB *p_ccb; 399 tL2C_RCB *p_rcb; 400 UINT8 *p; 401 402 L2CAP_TRACE_API ("L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm, 403 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 404 (rem_bda[4]<<8)+rem_bda[5]); 405 406 /* Fail if the PSM is not registered */ 407 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) 408 ||( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED )) 409 { 410 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x", psm); 411 osi_free(p_buf); 412 return (L2CAP_DW_FAILED); 413 } 414 415 /* First, see if we already have a link to the remote */ 416 /* then find the channel control block for UCD */ 417 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) 418 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) 419 { 420 if ( l2c_ucd_connect (rem_bda) == FALSE ) 421 { 422 osi_free(p_buf); 423 return (L2CAP_DW_FAILED); 424 } 425 426 /* If we still don't have lcb and ccb after connect attempt, then can't proceed */ 427 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) 428 || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) 429 { 430 osi_free(p_buf); 431 return (L2CAP_DW_FAILED); 432 } 433 } 434 435 /* write PSM */ 436 p_buf->offset -= L2CAP_UCD_OVERHEAD; 437 p_buf->len += L2CAP_UCD_OVERHEAD; 438 p = (UINT8 *)(p_buf + 1) + p_buf->offset; 439 440 UINT16_TO_STREAM (p, psm); 441 442 /* UCD MTU check */ 443 if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu)) 444 { 445 L2CAP_TRACE_WARNING ("L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be sent", p_lcb->handle); 446 osi_free(p_buf); 447 return (L2CAP_DW_FAILED); 448 } 449 450 /* If already congested, do not accept any more packets */ 451 if (p_ccb->cong_sent) 452 { 453 L2CAP_TRACE_ERROR ("L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: %u buff_quota: %u", 454 p_lcb->handle, 455 (fixed_queue_length(p_ccb->xmit_hold_q) + 456 fixed_queue_length(p_lcb->ucd_out_sec_pending_q)), 457 p_ccb->buff_quota); 458 459 osi_free(p_buf); 460 return (L2CAP_DW_FAILED); 461 } 462 463 /* channel based, packet based flushable or non-flushable */ 464 p_buf->layer_specific = flags; 465 466 l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf); 467 468 if (p_ccb->cong_sent) 469 return (L2CAP_DW_CONGESTED); 470 else 471 return (L2CAP_DW_SUCCESS); 472} 473 474/******************************************************************************* 475** 476** Function L2CA_UcdSetIdleTimeout 477** 478** Description Set UCD Idle timeout. 479** 480** Parameters: BD Addr 481** Timeout in second 482** 483** Return value: TRUE if successs 484** 485*******************************************************************************/ 486BOOLEAN L2CA_UcdSetIdleTimeout ( BD_ADDR rem_bda, UINT16 timeout ) 487{ 488 tL2C_LCB *p_lcb; 489 tL2C_CCB *p_ccb; 490 491 L2CAP_TRACE_API ("L2CA_UcdSetIdleTimeout() Timeout: 0x%04x BDA: %08x%04x", timeout, 492 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 493 (rem_bda[4]<<8)+rem_bda[5]); 494 495 /* First, see if we already have a link to the remote */ 496 /* then find the channel control block. */ 497 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) 498 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) 499 { 500 L2CAP_TRACE_WARNING ("L2CAP - no UCD channel"); 501 return (FALSE); 502 } 503 else 504 { 505 p_ccb->fixed_chnl_idle_tout = timeout; 506 return (TRUE); 507 } 508} 509 510/******************************************************************************* 511** 512** Function L2CA_UCDSetTxPriority 513** 514** Description Sets the transmission priority for a connectionless channel. 515** 516** Returns TRUE if a valid channel, else FALSE 517** 518*******************************************************************************/ 519BOOLEAN L2CA_UCDSetTxPriority ( BD_ADDR rem_bda, tL2CAP_CHNL_PRIORITY priority ) 520{ 521 tL2C_LCB *p_lcb; 522 tL2C_CCB *p_ccb; 523 524 L2CAP_TRACE_API ("L2CA_UCDSetTxPriority() priority: 0x%02x BDA: %08x%04x", priority, 525 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 526 (rem_bda[4]<<8)+rem_bda[5]); 527 528 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) 529 { 530 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_UCDSetTxPriority"); 531 return (FALSE); 532 } 533 534 /* Find the channel control block */ 535 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL) 536 { 537 L2CAP_TRACE_WARNING ("L2CAP - no CCB for L2CA_UCDSetTxPriority"); 538 return (FALSE); 539 } 540 541 /* it will update the order of CCB in LCB by priority and update round robin service variables */ 542 l2cu_change_pri_ccb (p_ccb, priority); 543 544 return (TRUE); 545} 546 547/******************************************************************************* 548** 549** Function l2c_ucd_connect 550** 551** Description Connect UCD to remote device. 552** 553** Parameters: BD_ADDR of remote device 554** 555** Return value: TRUE if successs 556** 557*******************************************************************************/ 558static BOOLEAN l2c_ucd_connect ( BD_ADDR rem_bda ) 559{ 560 tL2C_LCB *p_lcb; 561 tL2C_CCB *p_ccb; 562 tL2C_RCB *p_rcb; 563 564 L2CAP_TRACE_DEBUG ("l2c_ucd_connect() BDA: %08x%04x", 565 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 566 (rem_bda[4]<<8)+rem_bda[5]); 567 568 /* Fail if we have not established communications with the controller */ 569 if (!BTM_IsDeviceUp()) 570 { 571 L2CAP_TRACE_WARNING ("l2c_ucd_connect - BTU not ready"); 572 return (FALSE); 573 } 574 575 /* First, see if we already have a link to the remote */ 576 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) 577 { 578 /* No link. Get an LCB and start link establishment */ 579 if ( ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE, BT_TRANSPORT_BR_EDR)) == NULL) 580 || (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE) ) 581 { 582 L2CAP_TRACE_WARNING ("L2CAP - conn not started l2c_ucd_connect"); 583 return (FALSE); 584 } 585 } 586 else if ( p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) ) 587 { 588 if (!(p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) 589 { 590 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_connect"); 591 return (FALSE); 592 } 593 } 594 595 /* Find the channel control block. */ 596 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL) 597 { 598 /* Allocate a channel control block */ 599 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL) 600 { 601 L2CAP_TRACE_WARNING ("L2CAP - no CCB for l2c_ucd_connect"); 602 return (FALSE); 603 } 604 else 605 { 606 /* Set CID for the connection */ 607 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID; 608 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID; 609 610 /* Set the default idle timeout value to use */ 611 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT; 612 613 /* Set the default channel priority value to use */ 614 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY); 615 616 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL) 617 { 618 L2CAP_TRACE_WARNING ("L2CAP - no UCD registered, l2c_ucd_connect"); 619 return (FALSE); 620 } 621 /* Save UCD registration info */ 622 p_ccb->p_rcb = p_rcb; 623 624 /* There is no configuration, so if the link is up, the channel is up */ 625 if (p_lcb->link_state == LST_CONNECTED) 626 { 627 p_ccb->chnl_state = CST_OPEN; 628 } 629 } 630 } 631 632 return (TRUE); 633} 634 635/******************************************************************************* 636** 637** Function l2c_ucd_delete_sec_pending_q 638** 639** Description discard all of UCD packets in security pending queue 640** 641** Returns None 642** 643*******************************************************************************/ 644void l2c_ucd_delete_sec_pending_q(tL2C_LCB *p_lcb) 645{ 646 /* clean up any security pending UCD */ 647 while (! fixed_queue_is_empty(p_lcb->ucd_out_sec_pending_q)) 648 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q)); 649 fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL); 650 p_lcb->ucd_out_sec_pending_q = NULL; 651 652 while (! fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q)) 653 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q)); 654 fixed_queue_free(p_lcb->ucd_in_sec_pending_q); 655 p_lcb->ucd_in_sec_pending_q = NULL; 656} 657 658/******************************************************************************* 659** 660** Function l2c_ucd_check_pending_info_req 661** 662** Description check if any application is waiting for UCD information 663** 664** Return TRUE if any pending UCD info request 665** 666*******************************************************************************/ 667BOOLEAN l2c_ucd_check_pending_info_req(tL2C_CCB *p_ccb) 668{ 669 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0]; 670 UINT16 xx; 671 BOOLEAN pending = FALSE; 672 673 if (p_ccb == NULL) 674 { 675 L2CAP_TRACE_ERROR ("L2CAP - NULL p_ccb in l2c_ucd_check_pending_info_req"); 676 return (FALSE); 677 } 678 679 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) 680 { 681 if (p_rcb->in_use) 682 { 683 /* if application is waiting UCD reception info */ 684 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION) 685 { 686 /* if this information is available */ 687 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) ) 688 { 689 if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) 690 { 691 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_check_pending_info_req"); 692 693 l2c_ucd_delete_sec_pending_q(p_ccb->p_lcb); 694 l2cu_release_ccb (p_ccb); 695 } 696 697 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr, 698 L2CAP_UCD_INFO_TYPE_RECEPTION, 699 p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION); 700 } 701 else 702 { 703 pending = TRUE; 704 if (p_ccb->p_lcb->w4_info_rsp == FALSE) 705 { 706 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_EXTENDED_FEATURES_INFO_TYPE); 707 } 708 } 709 } 710 711 /* if application is waiting for UCD MTU */ 712 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU) 713 { 714 /* if this information is available */ 715 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_CONNLESS_MTU_INFO_TYPE)) 716 { 717 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr, 718 L2CAP_UCD_INFO_TYPE_MTU, 719 p_ccb->p_lcb->ucd_mtu); 720 } 721 else 722 { 723 pending = TRUE; 724 if (p_ccb->p_lcb->w4_info_rsp == FALSE) 725 { 726 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_CONNLESS_MTU_INFO_TYPE); 727 } 728 } 729 } 730 } 731 } 732 return (pending); 733} 734 735/******************************************************************************* 736** 737** Function l2c_ucd_enqueue_pending_out_sec_q 738** 739** Description enqueue outgoing UCD packet into security pending queue 740** and check congestion 741** 742** Return None 743** 744*******************************************************************************/ 745void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB *p_ccb, void *p_data) 746{ 747 fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data); 748 l2cu_check_channel_congestion (p_ccb); 749} 750 751/******************************************************************************* 752** 753** Function l2c_ucd_check_pending_out_sec_q 754** 755** Description check outgoing security 756** 757** Return TRUE if any UCD packet for security 758** 759*******************************************************************************/ 760BOOLEAN l2c_ucd_check_pending_out_sec_q(tL2C_CCB *p_ccb) 761{ 762 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->p_lcb->ucd_out_sec_pending_q); 763 764 if (p_buf != NULL) 765 { 766 UINT16 psm; 767 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; 768 769 STREAM_TO_UINT16(psm, p) 770 771 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP; 772 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm, 773 p_ccb->p_lcb->handle, CONNLESS_ORIG, &l2c_link_sec_comp, p_ccb); 774 775 return (TRUE); 776 } 777 return (FALSE); 778} 779 780/******************************************************************************* 781** 782** Function l2c_ucd_send_pending_out_sec_q 783** 784** Description dequeue UCD packet from security pending queue and 785** enqueue it into CCB 786** 787** Return None 788** 789*******************************************************************************/ 790void l2c_ucd_send_pending_out_sec_q(tL2C_CCB *p_ccb) 791{ 792 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q); 793 794 if (p_buf != NULL) 795 { 796 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_buf); 797 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL); 798 } 799} 800 801/******************************************************************************* 802** 803** Function l2c_ucd_discard_pending_out_sec_q 804** 805** Description dequeue UCD packet from security pending queue and 806** discard it. 807** 808** Return None 809** 810*******************************************************************************/ 811void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB *p_ccb) 812{ 813 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q); 814 815 /* we may need to report to application */ 816 osi_free(p_buf); 817} 818 819/******************************************************************************* 820** 821** Function l2c_ucd_check_pending_in_sec_q 822** 823** Description check incoming security 824** 825** Return TRUE if any UCD packet for security 826** 827*******************************************************************************/ 828BOOLEAN l2c_ucd_check_pending_in_sec_q(tL2C_CCB *p_ccb) 829{ 830 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q); 831 832 if (p_buf != NULL) 833 { 834 UINT16 psm; 835 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; 836 STREAM_TO_UINT16(psm, p) 837 838 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP; 839 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm, 840 p_ccb->p_lcb->handle, CONNLESS_TERM, &l2c_link_sec_comp, p_ccb); 841 842 return (TRUE); 843 } 844 return (FALSE); 845} 846 847/******************************************************************************* 848** 849** Function l2c_ucd_send_pending_in_sec_q 850** 851** Description dequeue UCD packet from security pending queue and 852** send it to application 853** 854** Return None 855** 856*******************************************************************************/ 857void l2c_ucd_send_pending_in_sec_q(tL2C_CCB *p_ccb) 858{ 859 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q) 860 861 if (p_buf != NULL) 862 { 863 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr, (BT_HDR *)p_buf); 864 } 865} 866 867/******************************************************************************* 868** 869** Function l2c_ucd_discard_pending_in_sec_q 870** 871** Description dequeue UCD packet from security pending queue and 872** discard it. 873** 874** Return None 875** 876*******************************************************************************/ 877void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB *p_ccb) 878{ 879 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q); 880 osi_free(p_buf); 881} 882 883/******************************************************************************* 884** 885** Function l2c_ucd_check_rx_pkts 886** 887** Description Check if UCD reception is registered. 888** Process received UCD packet if application is expecting. 889** 890** Return TRUE if UCD reception is registered 891** 892*******************************************************************************/ 893BOOLEAN l2c_ucd_check_rx_pkts(tL2C_LCB *p_lcb, BT_HDR *p_msg) 894{ 895 tL2C_CCB *p_ccb; 896 tL2C_RCB *p_rcb; 897 898 if (((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) != NULL) 899 ||((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL)) 900 { 901 if (p_ccb == NULL) 902 { 903 /* Allocate a channel control block */ 904 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL) 905 { 906 L2CAP_TRACE_WARNING ("L2CAP - no CCB for UCD reception"); 907 osi_free(p_msg); 908 return TRUE; 909 } 910 else 911 { 912 /* Set CID for the connection */ 913 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID; 914 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID; 915 916 /* Set the default idle timeout value to use */ 917 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT; 918 919 /* Set the default channel priority value to use */ 920 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY); 921 922 /* Save registration info */ 923 p_ccb->p_rcb = p_rcb; 924 925 p_ccb->chnl_state = CST_OPEN; 926 } 927 } 928 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg); 929 return TRUE; 930 } 931 else 932 return FALSE; 933} 934 935/******************************************************************************* 936** 937** Function l2c_ucd_process_event 938** 939** Description This is called from main state machine when LCID is connectionless 940** Process the event if it is for UCD. 941** 942** Return TRUE if the event is consumed by UCD 943** FALSE if the event needs to be processed by main state machine 944** 945*******************************************************************************/ 946BOOLEAN l2c_ucd_process_event(tL2C_CCB *p_ccb, UINT16 event, void *p_data) 947{ 948 /* if the event is not processed by this function, this variable will be set to FALSE */ 949 BOOLEAN done = TRUE; 950 951 switch (p_ccb->chnl_state) 952 { 953 case CST_CLOSED: 954 switch (event) 955 { 956 case L2CEVT_LP_CONNECT_CFM: /* Link came up */ 957 /* check if waiting for UCD info */ 958 if (!l2c_ucd_check_pending_info_req (p_ccb)) 959 { 960 /* check if any outgoing UCD packet is waiting security check */ 961 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) 962 { 963 p_ccb->chnl_state = CST_OPEN; 964 } 965 } 966 break; 967 968 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 969 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data); 970 break; 971 972 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 973 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data); 974 break; 975 976 case L2CEVT_L2CAP_INFO_RSP: 977 /* check if waiting for UCD info */ 978 if (!l2c_ucd_check_pending_info_req (p_ccb)) 979 { 980 /* check if any outgoing UCD packet is waiting security check */ 981 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) 982 { 983 p_ccb->chnl_state = CST_OPEN; 984 } 985 } 986 break; 987 988 default: 989 done = FALSE; /* main state machine continues to process event */ 990 break; 991 } 992 break; 993 994 case CST_ORIG_W4_SEC_COMP: 995 switch (event) 996 { 997 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */ 998 /* check if any outgoing UCD packet is waiting security check */ 999 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) 1000 { 1001 p_ccb->chnl_state = CST_OPEN; 1002 } 1003 break; 1004 1005 case L2CEVT_SEC_COMP: /* Security completed success */ 1006 p_ccb->chnl_state = CST_OPEN; 1007 l2c_ucd_send_pending_out_sec_q(p_ccb); 1008 1009 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_out_sec_pending_q)) 1010 { 1011 /* start a timer to send next UCD packet in OPEN state */ 1012 /* it will prevent stack overflow */ 1013 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0, 1014 l2c_ccb_timer_timeout, p_ccb, 1015 btu_general_alarm_queue); 1016 } 1017 else 1018 { 1019 /* start a timer for idle timeout of UCD */ 1020 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000; 1021 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms, 1022 l2c_ccb_timer_timeout, p_ccb, 1023 btu_general_alarm_queue); 1024 } 1025 break; 1026 1027 case L2CEVT_SEC_COMP_NEG: 1028 p_ccb->chnl_state = CST_OPEN; 1029 l2c_ucd_discard_pending_out_sec_q(p_ccb); 1030 1031 /* start a timer for idle timeout of UCD */ 1032 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000; 1033 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms, 1034 l2c_ccb_timer_timeout, p_ccb, 1035 btu_general_alarm_queue); 1036 break; 1037 1038 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1039 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data); 1040 break; 1041 1042 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1043 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data); 1044 break; 1045 1046 case L2CEVT_L2CAP_INFO_RSP: 1047 /* check if waiting for UCD info */ 1048 l2c_ucd_check_pending_info_req (p_ccb); 1049 break; 1050 1051 default: 1052 done = FALSE; /* main state machine continues to process event */ 1053 break; 1054 } 1055 break; 1056 1057 1058 case CST_TERM_W4_SEC_COMP: 1059 switch (event) 1060 { 1061 case L2CEVT_SEC_COMP: 1062 p_ccb->chnl_state = CST_OPEN; 1063 l2c_ucd_send_pending_in_sec_q (p_ccb); 1064 1065 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_in_sec_pending_q)) 1066 { 1067 /* start a timer to check next UCD packet in OPEN state */ 1068 /* it will prevent stack overflow */ 1069 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0, 1070 l2c_ccb_timer_timeout, p_ccb, 1071 btu_general_alarm_queue); 1072 } 1073 else 1074 { 1075 /* start a timer for idle timeout of UCD */ 1076 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000; 1077 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms, 1078 l2c_ccb_timer_timeout, p_ccb, 1079 btu_general_alarm_queue); 1080 } 1081 break; 1082 1083 case L2CEVT_SEC_COMP_NEG: 1084 if (((tL2C_CONN_INFO *)p_data)->status == BTM_DELAY_CHECK) 1085 { 1086 done = FALSE; 1087 break; 1088 } 1089 p_ccb->chnl_state = CST_OPEN; 1090 l2c_ucd_discard_pending_in_sec_q (p_ccb); 1091 1092 /* start a timer for idle timeout of UCD */ 1093 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000; 1094 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms, 1095 l2c_ccb_timer_timeout, p_ccb, 1096 btu_general_alarm_queue); 1097 break; 1098 1099 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1100 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data); 1101 break; 1102 1103 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1104 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data); 1105 break; 1106 1107 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */ 1108 /* check if any incoming UCD packet is waiting security check */ 1109 if (!l2c_ucd_check_pending_in_sec_q(p_ccb)) 1110 { 1111 p_ccb->chnl_state = CST_OPEN; 1112 } 1113 break; 1114 1115 case L2CEVT_L2CAP_INFO_RSP: 1116 /* check if waiting for UCD info */ 1117 l2c_ucd_check_pending_info_req (p_ccb); 1118 break; 1119 1120 default: 1121 done = FALSE; /* main state machine continues to process event */ 1122 break; 1123 } 1124 break; 1125 1126 case CST_OPEN: 1127 switch (event) 1128 { 1129 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1130 /* stop idle timer of UCD */ 1131 alarm_cancel(p_ccb->l2c_ccb_timer); 1132 1133 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data); 1134 l2c_ucd_check_pending_in_sec_q (p_ccb); 1135 break; 1136 1137 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1138 /* stop idle timer of UCD */ 1139 alarm_cancel(p_ccb->l2c_ccb_timer); 1140 1141 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data); 1142 1143 /* coverity[check_return] */ /* coverity[unchecked_value] */ 1144 /* success changes state, failure stays in current state */ 1145 l2c_ucd_check_pending_out_sec_q (p_ccb); 1146 break; 1147 1148 case L2CEVT_TIMEOUT: 1149 /* check if any UCD packet is waiting security check */ 1150 if ((!l2c_ucd_check_pending_in_sec_q(p_ccb)) 1151 &&(!l2c_ucd_check_pending_out_sec_q(p_ccb))) 1152 { 1153 l2cu_release_ccb (p_ccb); 1154 } 1155 break; 1156 1157 case L2CEVT_L2CAP_INFO_RSP: 1158 /* check if waiting for UCD info */ 1159 l2c_ucd_check_pending_info_req (p_ccb); 1160 break; 1161 1162 default: 1163 done = FALSE; /* main state machine continues to process event */ 1164 break; 1165 } 1166 break; 1167 1168 default: 1169 done = FALSE; /* main state machine continues to process event */ 1170 break; 1171 } 1172 1173 return done; 1174} 1175#endif /* (L2CAP_UCD_INCLUDED == TRUE) */ 1176