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