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