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