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