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 #define LOG_TAG "bluetooth-a2dp"
26 
27 #include <bluetooth/log.h>
28 #include <string.h>
29 
30 #include "avdt_api.h"
31 #include "avdt_int.h"
32 #include "internal_include/bt_target.h"
33 #include "l2c_api.h"
34 #include "l2cdefs.h"
35 #include "osi/include/allocator.h"
36 #include "stack/include/bt_hdr.h"
37 #include "stack/include/btm_sec_api_types.h"
38 
39 using namespace bluetooth;
40 
LookupAvdtpScb(const AvdtpTransportChannel & tc)41 AvdtpScb* AvdtpAdaptationLayer::LookupAvdtpScb(
42     const AvdtpTransportChannel& tc) {
43   if (tc.ccb_idx >= AVDT_NUM_LINKS) {
44     log::error("AvdtpScb entry not found: invalid ccb_idx:{}", tc.ccb_idx);
45     return nullptr;
46   }
47   if (tc.tcid >= AVDT_NUM_RT_TBL) {
48     log::error("AvdtpScb entry not found: invalid tcid:{}", tc.tcid);
49     return nullptr;
50   }
51   const AvdtpRoutingEntry& re = rt_tbl[tc.ccb_idx][tc.tcid];
52   log::verbose("ccb_idx:{} tcid:{} scb_hdl:{}", tc.ccb_idx, tc.tcid,
53                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   log::verbose("type:{}, tcid: {}", 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   log::verbose("tcid: {}, type: {}", 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   log::assert_that(i != AVDT_NUM_TC_TBL, "assert failed: 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   log::assert_that(i != AVDT_NUM_TC_TBL, "assert failed: 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   log::verbose("avdt_ad_tc_tbl_to_idx: {}", (long)(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   log::verbose("tcid: {}, old: {}", p_tbl->tcid, close.old_tc_state);
310   /* if signaling channel, notify ccb that channel open */
311   if (p_tbl->tcid == 0) {
312     p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
313     avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
314     return;
315   }
316   /* if media or other channel, notify scb that channel close */
317   /* look up scb in stream routing table by ccb, tcid */
318   p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
319   if (p_scb == nullptr) {
320     log::error("Cannot find AvdtScb entry: ccb_idx:{} tcid:{}", p_tbl->ccb_idx,
321                p_tbl->tcid);
322     return;
323   }
324   close.tcid = p_tbl->tcid;
325   close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
326   tAVDT_SCB_EVT avdt_scb_evt;
327   avdt_scb_evt.close = close;
328   avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, &avdt_scb_evt);
329 }
330 
331 /*******************************************************************************
332  *
333  * Function         avdt_ad_tc_open_ind
334  *
335  * Description      This function is called by the L2CAP interface when
336  *                  the L2CAP channel is opened.  It looks up the CCB or SCB
337  *                  for the channel and sends it an open event.
338  *
339  *
340  * Returns          Nothing.
341  *
342  ******************************************************************************/
avdt_ad_tc_open_ind(AvdtpTransportChannel * p_tbl)343 void avdt_ad_tc_open_ind(AvdtpTransportChannel* p_tbl) {
344   AvdtpCcb* p_ccb;
345   AvdtpScb* p_scb;
346   tAVDT_OPEN open;
347   tAVDT_EVT_HDR evt;
348 
349   log::verbose("p_tbl:{} state:{} ccb_idx:{} tcid:{} scb_hdl:{}",
350                fmt::ptr(p_tbl), p_tbl->state, p_tbl->ccb_idx, p_tbl->tcid,
351                avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
352 
353   p_tbl->state = AVDT_AD_ST_OPEN;
354 
355   /* if signaling channel, notify ccb that channel open */
356   if (p_tbl->tcid == 0) {
357     /* set the signal channel to use high priority within the ACL link */
358     if (!L2CA_SetTxPriority(
359             avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid,
360             L2CAP_CHNL_PRIORITY_HIGH)) {
361       log::warn("Unable to set L2CAP transmit high priority cid:{}",
362                 avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid);
363     }
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     log::error("Cannot find AvdtScb entry: ccb_idx:{} tcid:{}", p_tbl->ccb_idx,
382                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     log::error("Cannot find AvdtScb entry: ccb_idx:{} tcid:{}", p_tbl->ccb_idx,
425                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     log::error("Cannot find AvdtScb entry: ccb_idx:{} tcid:{}", p_tbl->ccb_idx,
462                p_tbl->tcid);
463     osi_free(p_buf);
464     log::error("buffer freed");
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     log::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   log::verbose("avdt_ad_open_req: type: {}, role: {}, tcid:{}", 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 = kAvdtpMtu;
531   } else {
532     /* otherwise get mtu from scb */
533     p_tbl->my_mtu = kAvdtpMtu;
534 
535     /* also set scb_hdl in rt_tbl */
536     avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl =
537         avdt_scb_to_hdl(p_scb);
538     log::verbose("avdtp_cb.ad.rt_tbl[{}][{}].scb_hdl = {}",
539                  avdt_ccb_to_idx(p_ccb), p_tbl->tcid, avdt_scb_to_hdl(p_scb));
540   }
541 
542   /* if we're acceptor, we're done; just sit back and listen */
543   if (role == AVDT_ACP) {
544     p_tbl->state = AVDT_AD_ST_ACP;
545   }
546   /* else we're inititator, start the L2CAP connection */
547   else {
548     p_tbl->state = AVDT_AD_ST_CONN;
549 
550     /* call l2cap connect req */
551     lcid = L2CA_ConnectReqWithSecurity(AVDT_PSM, p_ccb->peer_addr,
552                                        BTM_SEC_OUT_AUTHENTICATE);
553     if (lcid != 0) {
554       /* if connect req ok, store tcid in lcid table  */
555       avdtp_cb.ad.lcid_tbl[lcid] = avdt_ad_tc_tbl_to_idx(p_tbl);
556       log::verbose("avdtp_cb.ad.lcid_tbl[{}] = {}", lcid,
557                    avdt_ad_tc_tbl_to_idx(p_tbl));
558 
559       avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
560       log::verbose("avdtp_cb.ad.rt_tbl[{}][{}].lcid = 0x{:x}",
561                    avdt_ccb_to_idx(p_ccb), p_tbl->tcid, lcid);
562     } else {
563       /* if connect req failed, call avdt_ad_tc_close_ind() */
564       avdt_ad_tc_close_ind(p_tbl);
565     }
566   }
567 }
568 
569 /*******************************************************************************
570  *
571  * Function         avdt_ad_close_req
572  *
573  * Description      This function is called by a CCB or SCB to close a
574  *                  transport channel.  The function looks up the LCID for the
575  *                  channel and calls L2CA_DisconnectReq().
576  *
577  *
578  * Returns          Nothing.
579  *
580  ******************************************************************************/
avdt_ad_close_req(uint8_t type,AvdtpCcb * p_ccb,AvdtpScb * p_scb)581 void avdt_ad_close_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb) {
582   uint8_t tcid;
583   AvdtpTransportChannel* p_tbl;
584 
585   p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
586   log::verbose("avdt_ad_close_req state: {}", p_tbl->state);
587 
588   switch (p_tbl->state) {
589     case AVDT_AD_ST_UNUSED:
590       /* probably for reporting */
591       break;
592     case AVDT_AD_ST_ACP:
593       /* if we're listening on this channel, send ourselves a close ind */
594       avdt_ad_tc_close_ind(p_tbl);
595       break;
596     default:
597       /* get tcid from type, scb */
598       tcid = avdt_ad_type_to_tcid(type, p_scb);
599 
600       /* call l2cap disconnect req */
601       avdt_l2c_disconnect(
602           avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
603   }
604 }
605