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 module contains the AVDTP adaption layer. 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 "wcassert.h" 34 35 36/******************************************************************************* 37** 38** Function avdt_ad_type_to_tcid 39** 40** Description Derives the TCID from the channel type and SCB. 41** 42** 43** Returns TCID value. 44** 45*******************************************************************************/ 46UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb) 47{ 48 UINT8 scb_idx; 49 50 if (type == AVDT_CHAN_SIG) 51 { 52 return 0; 53 } 54 else 55 { 56 scb_idx = avdt_scb_to_hdl(p_scb) - 1; 57 /* 58 AVDT_TRACE_DEBUG2("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type)); 59 */ 60 return ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type); 61 } 62} 63 64/******************************************************************************* 65** 66** Function avdt_ad_tcid_to_type 67** 68** Description Derives the channel type from the TCID. 69** 70** 71** Returns Channel type value. 72** 73*******************************************************************************/ 74static UINT8 avdt_ad_tcid_to_type(UINT8 tcid) 75{ 76 UINT8 type; 77 78 if (tcid == 0) 79 { 80 type = AVDT_CHAN_SIG; 81 } 82 else 83 { 84 /* tcid translates to type based on number of channels, as follows: 85 ** only media channel : tcid=1,2,3,4,5,6... type=1,1,1,1,1,1... 86 ** media and report : tcid=1,2,3,4,5,6... type=1,2,1,2,1,2... 87 ** media, report, recov : tcid=1,2,3,4,5,6... type=1,2,3,1,2,3... 88 */ 89 type = ((tcid + AVDT_CHAN_NUM_TYPES - 2) % (AVDT_CHAN_NUM_TYPES - 1)) + 1; 90 } 91 AVDT_TRACE_DEBUG2("tcid: %d, type: %d", tcid, type); 92 return type; 93} 94 95 96/******************************************************************************* 97** 98** Function avdt_ad_init 99** 100** Description Initialize adaption layer. 101** 102** 103** Returns Nothing. 104** 105*******************************************************************************/ 106void avdt_ad_init(void) 107{ 108 int i; 109 tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl; 110 memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD)); 111 112 /* make sure the peer_mtu is a valid value */ 113 for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) 114 { 115 p_tbl->peer_mtu = L2CAP_DEFAULT_MTU; 116 } 117} 118 119 120/******************************************************************************* 121** 122** Function avdt_ad_tc_tbl_by_st 123** 124** Description Find adaption layer transport channel table entry matching 125** the given state. 126** 127** 128** Returns Pointer to matching entry. For control channel it returns 129** the matching entry. For media or other it returns the 130** first matching entry (there could be more than one). 131** 132*******************************************************************************/ 133tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state) 134{ 135 int i; 136 tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl; 137 UINT8 ccb_idx; 138 139 if (p_ccb == NULL) 140 { 141 /* resending security req */ 142 for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) 143 { 144 /* must be AVDT_CHAN_SIG - tcid always zero */ 145 if ((p_tbl->tcid == 0) && 146 (p_tbl->state == state)) 147 { 148 break; 149 } 150 } 151 } 152 else 153 { 154 ccb_idx = avdt_ccb_to_idx(p_ccb); 155 156 for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) 157 { 158 if (type == AVDT_CHAN_SIG) 159 { 160 /* if control channel, tcid always zero */ 161 if ((p_tbl->tcid == 0) && 162 (p_tbl->ccb_idx == ccb_idx) && 163 (p_tbl->state == state)) 164 { 165 break; 166 } 167 } 168 else 169 { 170 /* if other channel, tcid is always > zero */ 171 if ((p_tbl->tcid > 0) && 172 (p_tbl->ccb_idx == ccb_idx) && 173 (p_tbl->state == state)) 174 { 175 break; 176 } 177 } 178 } 179 } 180 181 /* if nothing found return null */ 182 if (i == AVDT_NUM_TC_TBL) 183 { 184 p_tbl = NULL; 185 } 186 187 return p_tbl; 188} 189 190 191/******************************************************************************* 192** 193** Function avdt_ad_tc_tbl_by_lcid 194** 195** Description Find adaption layer transport channel table entry by LCID. 196** 197** 198** Returns Pointer to entry. 199** 200*******************************************************************************/ 201tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid) 202{ 203 UINT8 idx; 204 205 idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID]; 206 207 if (idx < AVDT_NUM_TC_TBL) 208 { 209 return &avdt_cb.ad.tc_tbl[idx]; 210 } 211 else 212 { 213 return NULL; 214 } 215} 216 217 218/******************************************************************************* 219** 220** Function avdt_ad_tc_tbl_by_type 221** 222** Description This function retrieves the transport channel table entry 223** for a particular channel. 224** 225** 226** Returns Pointer to transport channel table entry. 227** 228*******************************************************************************/ 229tAVDT_TC_TBL *avdt_ad_tc_tbl_by_type(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb) 230{ 231 UINT8 tcid; 232 int i; 233 tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl; 234 UINT8 ccb_idx = avdt_ccb_to_idx(p_ccb); 235 236 /* get tcid from type, scb */ 237 tcid = avdt_ad_type_to_tcid(type, p_scb); 238 239 for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) 240 { 241 if ((p_tbl->tcid == tcid) && (p_tbl->ccb_idx == ccb_idx)) 242 { 243 break; 244 } 245 } 246 247 WC_ASSERT(i != AVDT_NUM_TC_TBL); 248 249 return p_tbl; 250} 251 252 253/******************************************************************************* 254** 255** Function avdt_ad_tc_tbl_alloc 256** 257** Description Allocate an entry in the traffic channel table. 258** 259** 260** Returns Pointer to entry. 261** 262*******************************************************************************/ 263tAVDT_TC_TBL *avdt_ad_tc_tbl_alloc(tAVDT_CCB *p_ccb) 264{ 265 int i; 266 tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl; 267 268 /* find next free entry in tc table */ 269 for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) 270 { 271 if (p_tbl->state == AVDT_AD_ST_UNUSED) 272 { 273 break; 274 } 275 } 276 277 /* sanity check */ 278 WC_ASSERT(i != AVDT_NUM_TC_TBL); 279 280 /* initialize entry */ 281 p_tbl->peer_mtu = L2CAP_DEFAULT_MTU; 282 p_tbl->cfg_flags = 0; 283 p_tbl->ccb_idx = avdt_ccb_to_idx(p_ccb); 284 p_tbl->state = AVDT_AD_ST_IDLE; 285 286 return p_tbl; 287} 288 289/******************************************************************************* 290** 291** Function avdt_ad_tc_tbl_to_idx 292** 293** Description Convert a transport channel table entry to an index. 294** 295** 296** Returns Index value. 297** 298*******************************************************************************/ 299UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl) 300{ 301 AVDT_TRACE_DEBUG1("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdt_cb.ad.tc_tbl)); 302 /* use array arithmetic to determine index */ 303 return (UINT8) (p_tbl - avdt_cb.ad.tc_tbl); 304} 305 306/******************************************************************************* 307** 308** Function avdt_ad_tc_close_ind 309** 310** Description This function is called by the L2CAP interface when the 311** L2CAP channel is closed. It looks up the CCB or SCB for 312** the channel and sends it a close event. The reason 313** parameter is the same value passed by the L2CAP 314** callback function. 315** 316** 317** Returns Nothing. 318** 319*******************************************************************************/ 320void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason) 321{ 322 tAVDT_CCB *p_ccb; 323 tAVDT_SCB *p_scb; 324 tAVDT_SCB_TC_CLOSE close; 325 326 close.old_tc_state = p_tbl->state; 327 /* clear avdt_ad_tc_tbl entry */ 328 p_tbl->state = AVDT_AD_ST_UNUSED; 329 p_tbl->cfg_flags = 0; 330 p_tbl->peer_mtu = L2CAP_DEFAULT_MTU; 331 332 AVDT_TRACE_DEBUG2("avdt_ad_tc_close_ind tcid: %d, old: %d", 333 p_tbl->tcid, close.old_tc_state); 334 /* if signaling channel, notify ccb that channel open */ 335 if (p_tbl->tcid == 0) 336 { 337 p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); 338 avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL); 339 } 340 /* if media or other channel, notify scb that channel close */ 341 else 342 { 343 /* look up scb in stream routing table by ccb, tcid */ 344 p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl); 345 if (p_scb != NULL) 346 { 347 close.tcid = p_tbl->tcid; 348 close.type = avdt_ad_tcid_to_type(p_tbl->tcid); 349 avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, (tAVDT_SCB_EVT *)&close); 350 } 351 } 352} 353 354/******************************************************************************* 355** 356** Function avdt_ad_tc_open_ind 357** 358** Description This function is called by the L2CAP interface when 359** the L2CAP channel is opened. It looks up the CCB or SCB 360** for the channel and sends it an open event. 361** 362** 363** Returns Nothing. 364** 365*******************************************************************************/ 366void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl) 367{ 368 tAVDT_CCB *p_ccb; 369 tAVDT_SCB *p_scb; 370 tAVDT_OPEN open; 371 tAVDT_EVT_HDR evt; 372 373 p_tbl->state = AVDT_AD_ST_OPEN; 374 375 /* if signaling channel, notify ccb that channel open */ 376 if (p_tbl->tcid == 0) 377 { 378 /* set the signal channel to use high priority within the ACL link */ 379 L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH); 380 381 p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); 382 /* use err_param to indicate the role of connection. 383 * AVDT_ACP, if ACP */ 384 evt.err_param = AVDT_INT; 385 if(p_tbl->cfg_flags & AVDT_L2C_CFG_CONN_ACP) 386 { 387 evt.err_param = AVDT_ACP; 388 } 389 avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, (tAVDT_CCB_EVT *)&evt); 390 } 391 /* if media or other channel, notify scb that channel open */ 392 else 393 { 394 /* look up scb in stream routing table by ccb, tcid */ 395 p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl); 396 397 /* put lcid in event data */ 398 if (p_scb != NULL) 399 { 400 open.peer_mtu = p_tbl->peer_mtu; 401 open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid; 402 open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid); 403 avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, (tAVDT_SCB_EVT *) &open); 404 } 405 } 406} 407 408 409/******************************************************************************* 410** 411** Function avdt_ad_tc_cong_ind 412** 413** Description This function is called by the L2CAP interface layer when 414** L2CAP calls the congestion callback. It looks up the CCB 415** or SCB for the channel and sends it a congestion event. 416** The is_congested parameter is the same value passed by 417** the L2CAP callback function. 418** 419** 420** Returns Nothing. 421** 422*******************************************************************************/ 423void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested) 424{ 425 tAVDT_CCB *p_ccb; 426 tAVDT_SCB *p_scb; 427 428 /* if signaling channel, notify ccb of congestion */ 429 if (p_tbl->tcid == 0) 430 { 431 p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); 432 avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested); 433 } 434 /* if media or other channel, notify scb that channel open */ 435 else 436 { 437 /* look up scb in stream routing table by ccb, tcid */ 438 p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl); 439 if (p_scb != NULL) 440 { 441 avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, (tAVDT_SCB_EVT *) &is_congested); 442 } 443 } 444} 445 446 447/******************************************************************************* 448** 449** Function avdt_ad_tc_data_ind 450** 451** Description This function is called by the L2CAP interface layer when 452** incoming data is received from L2CAP. It looks up the CCB 453** or SCB for the channel and routes the data accordingly. 454** 455** 456** Returns Nothing. 457** 458*******************************************************************************/ 459void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf) 460{ 461 tAVDT_CCB *p_ccb; 462 tAVDT_SCB *p_scb; 463 464 /* store type (media, recovery, reporting) */ 465 p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid); 466 467 468 /* if signaling channel, handle control message */ 469 if (p_tbl->tcid == 0) 470 { 471 p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); 472 avdt_msg_ind(p_ccb, p_buf); 473 } 474 /* if media or other channel, send event to scb */ 475 else 476 { 477 p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl); 478 if (p_scb != NULL) 479 { 480 avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf); 481 } 482 else 483 GKI_freebuf(p_buf); 484 } 485} 486 487/******************************************************************************* 488** 489** Function avdt_ad_write_req 490** 491** Description This function is called by a CCB or SCB to send data to a 492** transport channel. It looks up the LCID of the channel 493** based on the type, CCB, and SCB (if present). Then it 494** passes the data to L2CA_DataWrite(). 495** 496** 497** Returns AVDT_AD_SUCCESS, if data accepted, else FALSE 498** AVDT_AD_CONGESTED, if data accepted and the channel is congested 499** AVDT_AD_FAILED, if error 500** 501*******************************************************************************/ 502UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf) 503{ 504 UINT8 tcid; 505 506 /* get tcid from type, scb */ 507 tcid = avdt_ad_type_to_tcid(type, p_scb); 508 509 510 return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid, p_buf); 511} 512 513 514/******************************************************************************* 515** 516** Function avdt_ad_open_req 517** 518** Description This function is called by a CCB or SCB to open a transport 519** channel. This function allocates and initializes a 520** transport channel table entry. The channel can be opened 521** in two roles: as an initiator or acceptor. When opened 522** as an initiator the function will start an L2CAP connection. 523** When opened as an acceptor the function simply configures 524** the table entry to listen for an incoming channel. 525** 526** 527** Returns Nothing. 528** 529*******************************************************************************/ 530void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role) 531{ 532 tAVDT_TC_TBL *p_tbl; 533 UINT16 lcid; 534 535 p_tbl = avdt_ad_tc_tbl_alloc(p_ccb); 536 537 p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb); 538 AVDT_TRACE_DEBUG3("avdt_ad_open_req: type: %d, role: %d, tcid:%d", 539 type, role, p_tbl->tcid); 540 541 if (type == AVDT_CHAN_SIG) 542 { 543 /* if signaling, get mtu from registration control block */ 544 p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu; 545 p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO; 546 } 547 else 548 { 549 /* otherwise get mtu from scb */ 550 p_tbl->my_mtu = p_scb->cs.mtu; 551 p_tbl->my_flush_to = p_scb->cs.flush_to; 552 553 /* also set scb_hdl in rt_tbl */ 554 avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl = avdt_scb_to_hdl(p_scb); 555 AVDT_TRACE_DEBUG3("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d", 556 avdt_ccb_to_idx(p_ccb), p_tbl->tcid, 557 avdt_scb_to_hdl(p_scb)); 558 } 559 560 /* if we're acceptor, we're done; just sit back and listen */ 561 if (role == AVDT_ACP) 562 { 563 p_tbl->state = AVDT_AD_ST_ACP; 564 } 565 /* else we're inititator, start the L2CAP connection */ 566 else 567 { 568 p_tbl->state = AVDT_AD_ST_CONN; 569 570 /* call l2cap connect req */ 571 if ((lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)) != 0) 572 { 573 /* if connect req ok, store tcid in lcid table */ 574 avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); 575 AVDT_TRACE_DEBUG2("avdt_cb.ad.lcid_tbl[%d] = %d", 576 (lcid - L2CAP_BASE_APPL_CID), avdt_ad_tc_tbl_to_idx(p_tbl)); 577 578 avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; 579 AVDT_TRACE_DEBUG3("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x", 580 avdt_ccb_to_idx(p_ccb), p_tbl->tcid, 581 lcid); 582 } 583 else 584 { 585 /* if connect req failed, call avdt_ad_tc_close_ind() */ 586 avdt_ad_tc_close_ind(p_tbl, 0); 587 } 588 } 589} 590 591/******************************************************************************* 592** 593** Function avdt_ad_close_req 594** 595** Description This function is called by a CCB or SCB to close a 596** transport channel. The function looks up the LCID for the 597** channel and calls L2CA_DisconnectReq(). 598** 599** 600** Returns Nothing. 601** 602*******************************************************************************/ 603void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb) 604{ 605 UINT8 tcid; 606 tAVDT_TC_TBL *p_tbl; 607 608 p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb); 609 AVDT_TRACE_DEBUG1("avdt_ad_close_req state: %d", p_tbl->state); 610 611 switch(p_tbl->state) 612 { 613 case AVDT_AD_ST_UNUSED: 614 /* probably for reporting */ 615 break; 616 case AVDT_AD_ST_ACP: 617 /* if we're listening on this channel, send ourselves a close ind */ 618 avdt_ad_tc_close_ind(p_tbl, 0); 619 break; 620 default: 621 /* get tcid from type, scb */ 622 tcid = avdt_ad_type_to_tcid(type, p_scb); 623 624 /* call l2cap disconnect req */ 625 L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid); 626 } 627} 628 629