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