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