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