1 /****************************************************************************** 2 * 3 * Copyright (C) 2002-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 AVDTP adaption layer module interfaces to L2CAP 22 * 23 ******************************************************************************/ 24 25 #include <string.h> 26 #include "data_types.h" 27 #include "bt_target.h" 28 #include "bt_utils.h" 29 #include "avdt_api.h" 30 #include "avdtc_api.h" 31 #include "avdt_int.h" 32 #include "l2c_api.h" 33 #include "l2cdefs.h" 34 #include "btm_api.h" 35 #include "btm_int.h" 36 37 38 /* callback function declarations */ 39 void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id); 40 void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result); 41 void avdt_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg); 42 void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg); 43 void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed); 44 void avdt_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result); 45 void avdt_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested); 46 void avdt_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf); 47 48 /* L2CAP callback function structure */ 49 const tL2CAP_APPL_INFO avdt_l2c_appl = { 50 avdt_l2c_connect_ind_cback, 51 avdt_l2c_connect_cfm_cback, 52 NULL, 53 avdt_l2c_config_ind_cback, 54 avdt_l2c_config_cfm_cback, 55 avdt_l2c_disconnect_ind_cback, 56 avdt_l2c_disconnect_cfm_cback, 57 NULL, 58 avdt_l2c_data_ind_cback, 59 avdt_l2c_congestion_ind_cback, 60 NULL /* tL2CA_TX_COMPLETE_CB */ 61 }; 62 63 /******************************************************************************* 64 ** 65 ** Function avdt_sec_check_complete_term 66 ** 67 ** Description The function called when Security Manager finishes 68 ** verification of the service side connection 69 ** 70 ** Returns void 71 ** 72 *******************************************************************************/ 73 static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport, 74 void *p_ref_data, UINT8 res) 75 { 76 tAVDT_CCB *p_ccb = NULL; 77 tL2CAP_CFG_INFO cfg; 78 tAVDT_TC_TBL *p_tbl; 79 UNUSED(p_ref_data); 80 81 AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d", res); 82 if (!bd_addr) 83 { 84 AVDT_TRACE_WARNING("avdt_sec_check_complete_term: NULL BD_ADDR"); 85 return; 86 87 } 88 p_ccb = avdt_ccb_by_bd(bd_addr); 89 90 p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_ACP); 91 if (p_tbl == NULL) 92 return; 93 94 if (res == BTM_SUCCESS) 95 { 96 /* Send response to the L2CAP layer. */ 97 L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK); 98 99 /* store idx in LCID table, store LCID in routing table */ 100 avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); 101 avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid; 102 103 /* transition to configuration state */ 104 p_tbl->state = AVDT_AD_ST_CFG; 105 106 /* Send L2CAP config req */ 107 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 108 cfg.mtu_present = TRUE; 109 cfg.mtu = p_tbl->my_mtu; 110 cfg.flush_to_present = TRUE; 111 cfg.flush_to = p_tbl->my_flush_to; 112 L2CA_ConfigReq(p_tbl->lcid, &cfg); 113 } 114 else 115 { 116 L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK); 117 avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK); 118 } 119 } 120 121 /******************************************************************************* 122 ** 123 ** Function avdt_sec_check_complete_orig 124 ** 125 ** Description The function called when Security Manager finishes 126 ** verification of the service side connection 127 ** 128 ** Returns void 129 ** 130 *******************************************************************************/ 131 static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT trasnport, 132 void *p_ref_data, UINT8 res) 133 { 134 tAVDT_CCB *p_ccb = NULL; 135 tL2CAP_CFG_INFO cfg; 136 tAVDT_TC_TBL *p_tbl; 137 UNUSED(p_ref_data); 138 139 AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d", res); 140 if (bd_addr) 141 p_ccb = avdt_ccb_by_bd(bd_addr); 142 p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT); 143 if(p_tbl == NULL) 144 return; 145 146 if( res == BTM_SUCCESS ) 147 { 148 /* set channel state */ 149 p_tbl->state = AVDT_AD_ST_CFG; 150 151 /* Send L2CAP config req */ 152 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 153 cfg.mtu_present = TRUE; 154 cfg.mtu = p_tbl->my_mtu; 155 cfg.flush_to_present = TRUE; 156 cfg.flush_to = p_tbl->my_flush_to; 157 L2CA_ConfigReq(p_tbl->lcid, &cfg); 158 } 159 else 160 { 161 L2CA_DisconnectReq (p_tbl->lcid); 162 avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK); 163 } 164 } 165 /******************************************************************************* 166 ** 167 ** Function avdt_l2c_connect_ind_cback 168 ** 169 ** Description This is the L2CAP connect indication callback function. 170 ** 171 ** 172 ** Returns void 173 ** 174 *******************************************************************************/ 175 void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id) 176 { 177 tAVDT_CCB *p_ccb; 178 tAVDT_TC_TBL *p_tbl = NULL; 179 UINT16 result; 180 tL2CAP_CFG_INFO cfg; 181 tBTM_STATUS rc; 182 UNUSED(psm); 183 184 /* do we already have a control channel for this peer? */ 185 if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL) 186 { 187 /* no, allocate ccb */ 188 if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL) 189 { 190 /* no ccb available, reject L2CAP connection */ 191 result = L2CAP_CONN_NO_RESOURCES; 192 } 193 else 194 { 195 /* allocate and set up entry; first channel is always signaling */ 196 p_tbl = avdt_ad_tc_tbl_alloc(p_ccb); 197 p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu; 198 p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO; 199 p_tbl->tcid = AVDT_CHAN_SIG; 200 p_tbl->lcid = lcid; 201 p_tbl->id = id; 202 p_tbl->state = AVDT_AD_ST_SEC_ACP; 203 p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP; 204 205 /* Check the security */ 206 rc = btm_sec_mx_access_request (bd_addr, AVDT_PSM, 207 FALSE, BTM_SEC_PROTO_AVDT, 208 AVDT_CHAN_SIG, 209 &avdt_sec_check_complete_term, NULL); 210 if(rc == BTM_CMD_STARTED) 211 { 212 L2CA_ConnectRsp (p_ccb->peer_addr, p_tbl->id, lcid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); 213 } 214 return; 215 } 216 } 217 /* deal with simultaneous control channel connect case */ 218 else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_CONN)) != NULL) 219 { 220 /* reject their connection */ 221 result = L2CAP_CONN_NO_RESOURCES; 222 } 223 /* this must be a traffic channel; are we accepting a traffic channel 224 ** for this ccb? 225 */ 226 else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_MEDIA, p_ccb, AVDT_AD_ST_ACP)) != NULL) 227 { 228 /* yes; proceed with connection */ 229 result = L2CAP_CONN_OK; 230 } 231 #if AVDT_REPORTING == TRUE 232 /* this must be a reporting channel; are we accepting a reporting channel 233 ** for this ccb? 234 */ 235 else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_REPORT, p_ccb, AVDT_AD_ST_ACP)) != NULL) 236 { 237 /* yes; proceed with connection */ 238 result = L2CAP_CONN_OK; 239 } 240 #endif 241 /* else we're not listening for traffic channel; reject */ 242 else 243 { 244 result = L2CAP_CONN_NO_PSM; 245 } 246 247 /* Send L2CAP connect rsp */ 248 L2CA_ConnectRsp(bd_addr, id, lcid, result, 0); 249 250 /* if result ok, proceed with connection */ 251 if (result == L2CAP_CONN_OK) 252 { 253 /* store idx in LCID table, store LCID in routing table */ 254 avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); 255 avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; 256 257 /* transition to configuration state */ 258 p_tbl->state = AVDT_AD_ST_CFG; 259 260 /* Send L2CAP config req */ 261 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 262 cfg.mtu_present = TRUE; 263 cfg.mtu = p_tbl->my_mtu; 264 cfg.flush_to_present = TRUE; 265 cfg.flush_to = p_tbl->my_flush_to; 266 L2CA_ConfigReq(lcid, &cfg); 267 } 268 } 269 270 /******************************************************************************* 271 ** 272 ** Function avdt_l2c_connect_cfm_cback 273 ** 274 ** Description This is the L2CAP connect confirm callback function. 275 ** 276 ** 277 ** Returns void 278 ** 279 *******************************************************************************/ 280 void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result) 281 { 282 tAVDT_TC_TBL *p_tbl; 283 tL2CAP_CFG_INFO cfg; 284 tAVDT_CCB *p_ccb; 285 286 AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d", 287 lcid, result); 288 /* look up info for this channel */ 289 if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) 290 { 291 /* if in correct state */ 292 if (p_tbl->state == AVDT_AD_ST_CONN) 293 { 294 /* if result successful */ 295 if (result == L2CAP_CONN_OK) 296 { 297 if(p_tbl->tcid != AVDT_CHAN_SIG) 298 { 299 /* set channel state */ 300 p_tbl->state = AVDT_AD_ST_CFG; 301 302 /* Send L2CAP config req */ 303 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 304 cfg.mtu_present = TRUE; 305 cfg.mtu = p_tbl->my_mtu; 306 cfg.flush_to_present = TRUE; 307 cfg.flush_to = p_tbl->my_flush_to; 308 L2CA_ConfigReq(lcid, &cfg); 309 } 310 else 311 { 312 p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); 313 if(p_ccb == NULL) 314 { 315 result = L2CAP_CONN_NO_RESOURCES; 316 } 317 else 318 { 319 /* set channel state */ 320 p_tbl->state = AVDT_AD_ST_SEC_INT; 321 p_tbl->lcid = lcid; 322 p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT; 323 324 /* Check the security */ 325 btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM, 326 TRUE, BTM_SEC_PROTO_AVDT, 327 AVDT_CHAN_SIG, 328 &avdt_sec_check_complete_orig, NULL); 329 } 330 } 331 } 332 333 /* failure; notify adaption that channel closed */ 334 if (result != L2CAP_CONN_OK) 335 { 336 avdt_ad_tc_close_ind(p_tbl, result); 337 } 338 } 339 } 340 } 341 342 /******************************************************************************* 343 ** 344 ** Function avdt_l2c_config_cfm_cback 345 ** 346 ** Description This is the L2CAP config confirm callback function. 347 ** 348 ** 349 ** Returns void 350 ** 351 *******************************************************************************/ 352 void avdt_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) 353 { 354 tAVDT_TC_TBL *p_tbl; 355 356 /* look up info for this channel */ 357 if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) 358 { 359 /* if in correct state */ 360 if (p_tbl->state == AVDT_AD_ST_CFG) 361 { 362 /* if result successful */ 363 if (p_cfg->result == L2CAP_CONN_OK) 364 { 365 /* update cfg_flags */ 366 p_tbl->cfg_flags |= AVDT_L2C_CFG_CFM_DONE; 367 368 /* if configuration complete */ 369 if (p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) 370 { 371 avdt_ad_tc_open_ind(p_tbl); 372 } 373 } 374 /* else failure */ 375 else 376 { 377 /* Send L2CAP disconnect req */ 378 L2CA_DisconnectReq(lcid); 379 } 380 } 381 } 382 } 383 384 /******************************************************************************* 385 ** 386 ** Function avdt_l2c_config_ind_cback 387 ** 388 ** Description This is the L2CAP config indication callback function. 389 ** 390 ** 391 ** Returns void 392 ** 393 *******************************************************************************/ 394 void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) 395 { 396 tAVDT_TC_TBL *p_tbl; 397 398 /* look up info for this channel */ 399 if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) 400 { 401 /* store the mtu in tbl */ 402 if (p_cfg->mtu_present) 403 { 404 p_tbl->peer_mtu = p_cfg->mtu; 405 } 406 else 407 { 408 p_tbl->peer_mtu = L2CAP_DEFAULT_MTU; 409 } 410 AVDT_TRACE_DEBUG("peer_mtu: %d, lcid: x%x",p_tbl->peer_mtu, lcid); 411 412 /* send L2CAP configure response */ 413 memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO)); 414 p_cfg->result = L2CAP_CFG_OK; 415 L2CA_ConfigRsp(lcid, p_cfg); 416 417 /* if first config ind */ 418 if ((p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) == 0) 419 { 420 /* update cfg_flags */ 421 p_tbl->cfg_flags |= AVDT_L2C_CFG_IND_DONE; 422 423 /* if configuration complete */ 424 if (p_tbl->cfg_flags & AVDT_L2C_CFG_CFM_DONE) 425 { 426 avdt_ad_tc_open_ind(p_tbl); 427 } 428 } 429 } 430 } 431 432 /******************************************************************************* 433 ** 434 ** Function avdt_l2c_disconnect_ind_cback 435 ** 436 ** Description This is the L2CAP disconnect indication callback function. 437 ** 438 ** 439 ** Returns void 440 ** 441 *******************************************************************************/ 442 void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed) 443 { 444 tAVDT_TC_TBL *p_tbl; 445 446 AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d", 447 lcid, ack_needed); 448 /* look up info for this channel */ 449 if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) 450 { 451 if (ack_needed) 452 { 453 /* send L2CAP disconnect response */ 454 L2CA_DisconnectRsp(lcid); 455 } 456 457 avdt_ad_tc_close_ind(p_tbl, 0); 458 } 459 } 460 461 /******************************************************************************* 462 ** 463 ** Function avdt_l2c_disconnect_cfm_cback 464 ** 465 ** Description This is the L2CAP disconnect confirm callback function. 466 ** 467 ** 468 ** Returns void 469 ** 470 *******************************************************************************/ 471 void avdt_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result) 472 { 473 tAVDT_TC_TBL *p_tbl; 474 475 AVDT_TRACE_DEBUG("avdt_l2c_disconnect_cfm_cback lcid: %d, result: %d", 476 lcid, result); 477 /* look up info for this channel */ 478 if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) 479 { 480 avdt_ad_tc_close_ind(p_tbl, result); 481 } 482 } 483 484 /******************************************************************************* 485 ** 486 ** Function avdt_l2c_congestion_ind_cback 487 ** 488 ** Description This is the L2CAP congestion indication callback function. 489 ** 490 ** 491 ** Returns void 492 ** 493 *******************************************************************************/ 494 void avdt_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested) 495 { 496 tAVDT_TC_TBL *p_tbl; 497 498 /* look up info for this channel */ 499 if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) 500 { 501 avdt_ad_tc_cong_ind(p_tbl, is_congested); 502 } 503 } 504 505 /******************************************************************************* 506 ** 507 ** Function avdt_l2c_data_ind_cback 508 ** 509 ** Description This is the L2CAP data indication callback function. 510 ** 511 ** 512 ** Returns void 513 ** 514 *******************************************************************************/ 515 void avdt_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf) 516 { 517 tAVDT_TC_TBL *p_tbl; 518 519 /* look up info for this channel */ 520 if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) 521 { 522 avdt_ad_tc_data_ind(p_tbl, p_buf); 523 } 524 else /* prevent buffer leak */ 525 GKI_freebuf(p_buf); 526 } 527 528