1 /******************************************************************************
2 *
3 * Copyright 2006-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 action functions associated with the channel
22 * control block state machine.
23 *
24 ******************************************************************************/
25
26 #define LOG_TAG "bluetooth-a2dp"
27
28 #include <bluetooth/log.h>
29 #include <string.h>
30
31 #include <cstdint>
32
33 #include "avdt_api.h"
34 #include "avdt_defs.h"
35 #include "avdt_int.h"
36 #include "avdtc_api.h"
37 #include "internal_include/bt_target.h"
38 #include "osi/include/alarm.h"
39 #include "osi/include/allocator.h"
40 #include "osi/include/fixed_queue.h"
41 #include "stack/include/bt_hdr.h"
42 #include "types/raw_address.h"
43
44 using namespace bluetooth;
45
46 /*******************************************************************************
47 *
48 * Function avdt_ccb_clear_ccb
49 *
50 * Description This function clears out certain buffers, queues, and
51 * other data elements of a ccb.
52 *
53 *
54 * Returns void.
55 *
56 ******************************************************************************/
avdt_ccb_clear_ccb(AvdtpCcb * p_ccb)57 static void avdt_ccb_clear_ccb(AvdtpCcb* p_ccb) {
58 BT_HDR* p_buf;
59
60 /* clear certain ccb variables */
61 p_ccb->cong = false;
62 p_ccb->ret_count = 0;
63
64 /* free message being fragmented */
65 osi_free_and_reset((void**)&p_ccb->p_curr_msg);
66
67 /* free message being reassembled */
68 osi_free_and_reset((void**)&p_ccb->p_rx_msg);
69
70 /* clear out response queue */
71 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL) {
72 osi_free(p_buf);
73 }
74 }
75
76 /*******************************************************************************
77 *
78 * Function avdt_ccb_chan_open
79 *
80 * Description This function calls avdt_ad_open_req() to
81 * initiate a signaling channel connection.
82 *
83 *
84 * Returns void.
85 *
86 ******************************************************************************/
avdt_ccb_chan_open(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)87 void avdt_ccb_chan_open(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
88 avdt_ad_open_req(AVDT_CHAN_SIG, p_ccb, NULL, tAVDT_ROLE::AVDT_INT);
89 }
90
91 /*******************************************************************************
92 *
93 * Function avdt_ccb_chan_close
94 *
95 * Description This function calls avdt_ad_close_req() to close a
96 * signaling channel connection.
97 *
98 *
99 * Returns void.
100 *
101 ******************************************************************************/
avdt_ccb_chan_close(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)102 void avdt_ccb_chan_close(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
103 /* close the transport channel used by this CCB */
104 avdt_ad_close_req(AVDT_CHAN_SIG, p_ccb, NULL);
105 }
106
107 /*******************************************************************************
108 *
109 * Function avdt_ccb_chk_close
110 *
111 * Description This function checks for active streams on this CCB.
112 * If there are none, it starts an idle timer.
113 *
114 *
115 * Returns void.
116 *
117 ******************************************************************************/
avdt_ccb_chk_close(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)118 void avdt_ccb_chk_close(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
119 int i;
120 AvdtpScb* p_scb = &(p_ccb->scb[0]);
121
122 /* see if there are any active scbs associated with this ccb */
123 for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
124 if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb)) {
125 break;
126 }
127 }
128
129 /* if no active scbs start idle timer */
130 if (i == AVDT_NUM_SEPS) {
131 alarm_cancel(p_ccb->ret_ccb_timer);
132 alarm_cancel(p_ccb->rsp_ccb_timer);
133 uint64_t interval_ms = avdtp_cb.rcb.idle_tout * 1000;
134 alarm_set_on_mloop(p_ccb->idle_ccb_timer, interval_ms, avdt_ccb_idle_ccb_timer_timeout, p_ccb);
135 }
136 }
137
138 /*******************************************************************************
139 *
140 * Function avdt_ccb_hdl_discover_cmd
141 *
142 * Description This function is called when a discover command is
143 * received from the peer. It gathers up the stream
144 * information for all allocated streams and initiates
145 * sending of a discover response.
146 *
147 *
148 * Returns void.
149 *
150 ******************************************************************************/
avdt_ccb_hdl_discover_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)151 void avdt_ccb_hdl_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
152 tAVDT_SEP_INFO sep_info[AVDT_NUM_SEPS];
153 AvdtpScb* p_scb = &(p_ccb->scb[0]);
154
155 log::verbose("p_ccb index={}", avdt_ccb_to_idx(p_ccb));
156
157 p_data->msg.discover_rsp.p_sep_info = sep_info;
158 p_data->msg.discover_rsp.num_seps = 0;
159
160 /* for all allocated scbs */
161 for (int i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
162 if (p_scb->allocated) {
163 /* copy sep info */
164 sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
165 sep_info[p_data->msg.discover_rsp.num_seps].seid = p_scb->ScbHandle();
166 sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->stream_config.media_type;
167 sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->stream_config.tsep;
168
169 p_data->msg.discover_rsp.num_seps++;
170 }
171 }
172
173 /* send response */
174 avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_RSP_EVT, p_data);
175 }
176
177 /*******************************************************************************
178 *
179 * Function avdt_ccb_hdl_discover_rsp
180 *
181 * Description This function is called when a discover response or
182 * reject is received from the peer. It calls the application
183 * callback function with the results.
184 *
185 *
186 * Returns void.
187 *
188 ******************************************************************************/
avdt_ccb_hdl_discover_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)189 void avdt_ccb_hdl_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
190 /* we're done with procedure */
191 p_ccb->proc_busy = false;
192
193 /* call app callback with results */
194 (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_DISCOVER_CFM_EVT,
195 (tAVDT_CTRL*)(&p_data->msg.discover_rsp), p_ccb->BtaAvScbIndex());
196 }
197
198 /*******************************************************************************
199 *
200 * Function avdt_ccb_hdl_getcap_cmd
201 *
202 * Description This function is called when a get capabilities command
203 * is received from the peer. It retrieves the stream
204 * configuration for the requested stream and initiates
205 * sending of a get capabilities response.
206 *
207 *
208 * Returns void.
209 *
210 ******************************************************************************/
avdt_ccb_hdl_getcap_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)211 void avdt_ccb_hdl_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
212 /* look up scb for seid sent to us */
213 AvdtpScb* p_scb = avdt_scb_by_hdl(p_data->msg.single.seid);
214
215 if (p_scb == nullptr) {
216 /* not ok, send reject */
217 p_data->msg.hdr.err_code = AVDT_ERR_BAD_STATE;
218 p_data->msg.hdr.err_param = p_data->msg.single.seid;
219 avdt_msg_send_rej(p_ccb, AVDT_SIG_START, &p_data->msg);
220 return;
221 }
222
223 p_data->msg.svccap.p_cfg = &p_scb->stream_config.cfg;
224
225 avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data);
226 }
227
228 /*******************************************************************************
229 *
230 * Function avdt_ccb_hdl_getcap_rsp
231 *
232 * Description This function is called with a get capabilities response
233 * or reject is received from the peer. It calls the
234 * application callback function with the results.
235 *
236 *
237 * Returns void.
238 *
239 ******************************************************************************/
avdt_ccb_hdl_getcap_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)240 void avdt_ccb_hdl_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
241 /* we're done with procedure */
242 p_ccb->proc_busy = false;
243
244 /* call app callback with results */
245 (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_GETCAP_CFM_EVT, (tAVDT_CTRL*)(&p_data->msg.svccap),
246 p_ccb->BtaAvScbIndex());
247 }
248
249 /*******************************************************************************
250 *
251 * Function avdt_ccb_hdl_start_cmd
252 *
253 * Description This function is called when a start command is received
254 * from the peer. It verifies that all requested streams
255 * are in the proper state. If so, it initiates sending of
256 * a start response. Otherwise it sends a start reject.
257 *
258 *
259 * Returns void.
260 *
261 ******************************************************************************/
avdt_ccb_hdl_start_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)262 void avdt_ccb_hdl_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
263 uint8_t err_code = 0;
264
265 /* verify all streams in the right state */
266 uint8_t seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_START, p_data->msg.multi.seid_list,
267 p_data->msg.multi.num_seps, &err_code);
268 if (seid == 0 && err_code == 0) {
269 /* we're ok, send response */
270 avdt_ccb_event(p_ccb, AVDT_CCB_API_START_RSP_EVT, p_data);
271 } else {
272 /* not ok, send reject */
273 p_data->msg.hdr.err_code = err_code;
274 p_data->msg.hdr.err_param = seid;
275 avdt_msg_send_rej(p_ccb, AVDT_SIG_START, &p_data->msg);
276 }
277 }
278
279 /*******************************************************************************
280 *
281 * Function avdt_ccb_hdl_start_rsp
282 *
283 * Description This function is called when a start response or reject
284 * is received from the peer. Using the SEIDs stored in the
285 * current command message, it sends a start response or start
286 * reject event to each SCB associated with the command.
287 *
288 *
289 * Returns void.
290 *
291 ******************************************************************************/
avdt_ccb_hdl_start_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)292 void avdt_ccb_hdl_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
293 uint8_t event;
294 int i;
295 uint8_t* p;
296 AvdtpScb* p_scb;
297
298 /* determine rsp or rej event */
299 event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_START_RSP_EVT : AVDT_SCB_MSG_START_REJ_EVT;
300
301 /* get to where seid's are stashed in current cmd */
302 p = (uint8_t*)(p_ccb->p_curr_cmd + 1);
303
304 /* little trick here; length of current command equals number of streams */
305 for (i = 0; i < p_ccb->p_curr_cmd->len; i++) {
306 p_scb = avdt_scb_by_hdl(p[i]);
307 if (p_scb != NULL) {
308 avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT*)&p_data->msg);
309 }
310 }
311 }
312
313 /*******************************************************************************
314 *
315 * Function avdt_ccb_hdl_suspend_cmd
316 *
317 * Description This function is called when a suspend command is received
318 * from the peer. It verifies that all requested streams are
319 * in the proper state. If so, it initiates sending of a
320 * suspend response. Otherwise it sends a suspend reject.
321
322 *
323 *
324 * Returns void.
325 *
326 ******************************************************************************/
avdt_ccb_hdl_suspend_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)327 void avdt_ccb_hdl_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
328 uint8_t seid;
329 uint8_t err_code = 0;
330
331 /* verify all streams in the right state */
332 if ((seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_SUSPEND, p_data->msg.multi.seid_list,
333 p_data->msg.multi.num_seps, &err_code)) == 0 &&
334 err_code == 0) {
335 /* we're ok, send response */
336 avdt_ccb_event(p_ccb, AVDT_CCB_API_SUSPEND_RSP_EVT, p_data);
337 } else {
338 /* not ok, send reject */
339 p_data->msg.hdr.err_code = err_code;
340 p_data->msg.hdr.err_param = seid;
341 avdt_msg_send_rej(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
342 }
343 }
344
345 /*******************************************************************************
346 *
347 * Function avdt_ccb_hdl_suspend_rsp
348 *
349 * Description This function is called when a suspend response or reject
350 * is received from the peer. Using the SEIDs stored in the
351 * current command message, it sends a suspend response or
352 * suspend reject event to each SCB associated with the
353 * command.
354 *
355 *
356 *
357 * Returns void.
358 *
359 ******************************************************************************/
avdt_ccb_hdl_suspend_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)360 void avdt_ccb_hdl_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
361 uint8_t event;
362 int i;
363 uint8_t* p;
364 AvdtpScb* p_scb;
365
366 /* determine rsp or rej event */
367 event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_SUSPEND_RSP_EVT
368 : AVDT_SCB_MSG_SUSPEND_REJ_EVT;
369
370 /* get to where seid's are stashed in current cmd */
371 p = (uint8_t*)(p_ccb->p_curr_cmd + 1);
372
373 /* little trick here; length of current command equals number of streams */
374 for (i = 0; i < p_ccb->p_curr_cmd->len; i++) {
375 p_scb = avdt_scb_by_hdl(p[i]);
376 if (p_scb != NULL) {
377 avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT*)&p_data->msg);
378 }
379 }
380 }
381
382 /*******************************************************************************
383 *
384 * Function avdt_ccb_snd_discover_cmd
385 *
386 * Description This function is called to send a discover command to the
387 * peer. It copies variables needed for the procedure from
388 * the event to the CCB. It marks the CCB as busy and then
389 * sends a discover command.
390 *
391 *
392 * Returns void.
393 *
394 ******************************************************************************/
avdt_ccb_snd_discover_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)395 void avdt_ccb_snd_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
396 /* store info in ccb struct */
397 p_ccb->p_proc_data = p_data->discover.p_sep_info;
398 p_ccb->proc_cback = p_data->discover.p_cback;
399 p_ccb->proc_param = p_data->discover.num_seps;
400
401 /* we're busy */
402 p_ccb->proc_busy = true;
403
404 /* build and queue discover req */
405 avdt_msg_send_cmd(p_ccb, NULL, AVDT_SIG_DISCOVER, NULL);
406 }
407
408 /*******************************************************************************
409 *
410 * Function avdt_ccb_snd_discover_rsp
411 *
412 * Description This function is called to send a discover response to
413 * the peer. It takes the stream information passed in the
414 * event and sends a discover response.
415 *
416 *
417 * Returns void.
418 *
419 ******************************************************************************/
avdt_ccb_snd_discover_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)420 void avdt_ccb_snd_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
421 /* send response */
422 avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg);
423 }
424
425 /*******************************************************************************
426 *
427 * Function avdt_ccb_snd_getcap_cmd
428 *
429 * Description This function is called to send a get capabilities command
430 * to the peer. It copies variables needed for the procedure
431 * from the event to the CCB. It marks the CCB as busy and
432 * then sends a get capabilities command.
433 *
434 *
435 * Returns void.
436 *
437 ******************************************************************************/
avdt_ccb_snd_getcap_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)438 void avdt_ccb_snd_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
439 uint8_t sig_id = AVDT_SIG_GETCAP;
440
441 /* store info in ccb struct */
442 p_ccb->p_proc_data = p_data->getcap.p_cfg;
443 p_ccb->proc_cback = p_data->getcap.p_cback;
444
445 /* we're busy */
446 p_ccb->proc_busy = true;
447
448 /* build and queue discover req */
449 if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP) {
450 sig_id = AVDT_SIG_GET_ALLCAP;
451 }
452
453 avdt_msg_send_cmd(p_ccb, NULL, sig_id, (tAVDT_MSG*)&p_data->getcap.single);
454 }
455
456 /*******************************************************************************
457 *
458 * Function avdt_ccb_snd_getcap_rsp
459 *
460 * Description This function is called to send a get capabilities response
461 * to the peer. It takes the stream information passed in the
462 * event and sends a get capabilities response.
463 *
464 *
465 * Returns void.
466 *
467 ******************************************************************************/
avdt_ccb_snd_getcap_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)468 void avdt_ccb_snd_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
469 uint8_t sig_id = AVDT_SIG_GETCAP;
470
471 if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP) {
472 sig_id = AVDT_SIG_GET_ALLCAP;
473 }
474
475 /* send response */
476 avdt_msg_send_rsp(p_ccb, sig_id, &p_data->msg);
477 }
478
479 /*******************************************************************************
480 *
481 * Function avdt_ccb_snd_start_cmd
482 *
483 * Description This function is called to send a start command to the
484 * peer. It verifies that all requested streams are in the
485 * proper state. If so, it sends a start command. Otherwise
486 * send ourselves back a start reject.
487 *
488 *
489 * Returns void.
490 *
491 ******************************************************************************/
avdt_ccb_snd_start_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)492 void avdt_ccb_snd_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
493 int i;
494 AvdtpScb* p_scb;
495 tAVDT_MSG avdt_msg;
496 uint8_t seid_list[AVDT_NUM_SEPS];
497
498 log::verbose("");
499
500 /* make copy of our seid list */
501 memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
502
503 /* verify all streams in the right state */
504 avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_OPEN, p_data->msg.multi.seid_list,
505 p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code);
506 if (avdt_msg.hdr.err_param == 0) {
507 log::verbose("AVDT_SIG_START");
508
509 /* set peer seid list in messsage */
510 avdt_scb_peer_seid_list(&p_data->msg.multi);
511
512 /* send command */
513 avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_START, &p_data->msg);
514 } else {
515 /* failed; send ourselves a reject for each stream */
516 for (i = 0; i < p_data->msg.multi.num_seps; i++) {
517 p_scb = avdt_scb_by_hdl(seid_list[i]);
518 if (p_scb != NULL) {
519 log::verbose("AVDT_SCB_MSG_START_REJ_EVT: i={}", i);
520 tAVDT_SCB_EVT avdt_scb_evt;
521 avdt_scb_evt.msg.hdr = avdt_msg.hdr;
522 avdt_scb_event(p_scb, AVDT_SCB_MSG_START_REJ_EVT, &avdt_scb_evt);
523 }
524 }
525 }
526 }
527
528 /*******************************************************************************
529 *
530 * Function avdt_ccb_snd_start_rsp
531 *
532 * Description This function is called to send a start response to the
533 * peer. It takes the stream information passed in the event
534 * and sends a start response. Then it sends a start event
535 * to the SCB for each stream.
536 *
537 *
538 * Returns void.
539 *
540 ******************************************************************************/
avdt_ccb_snd_start_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)541 void avdt_ccb_snd_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
542 AvdtpScb* p_scb;
543 int i;
544
545 /* send response message */
546 avdt_msg_send_rsp(p_ccb, AVDT_SIG_START, &p_data->msg);
547
548 /* send start event to each scb */
549 for (i = 0; i < p_data->msg.multi.num_seps; i++) {
550 p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i]);
551 if (p_scb != NULL) {
552 avdt_scb_event(p_scb, AVDT_SCB_MSG_START_CMD_EVT, NULL);
553 }
554 }
555 }
556
557 /*******************************************************************************
558 *
559 * Function avdt_ccb_snd_suspend_cmd
560 *
561 * Description This function is called to send a suspend command to the
562 * peer. It verifies that all requested streams are in the
563 * proper state. If so, it sends a suspend command.
564 * Otherwise it calls the callback function for each requested
565 * stream and sends a suspend confirmation with failure.
566 *
567 *
568 * Returns void.
569 *
570 ******************************************************************************/
avdt_ccb_snd_suspend_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)571 void avdt_ccb_snd_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
572 int i;
573 AvdtpScb* p_scb;
574 tAVDT_MSG avdt_msg;
575 uint8_t seid_list[AVDT_NUM_SEPS];
576
577 /* make copy of our seid list */
578 memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
579
580 /* verify all streams in the right state */
581 avdt_msg.hdr.err_param =
582 avdt_scb_verify(p_ccb, AVDT_VERIFY_STREAMING, p_data->msg.multi.seid_list,
583 p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code);
584 if (avdt_msg.hdr.err_param == 0) {
585 /* set peer seid list in messsage */
586 avdt_scb_peer_seid_list(&p_data->msg.multi);
587
588 /* send command */
589 avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_SUSPEND, &p_data->msg);
590 } else {
591 /* failed; send ourselves a reject for each stream */
592 for (i = 0; i < p_data->msg.multi.num_seps; i++) {
593 p_scb = avdt_scb_by_hdl(seid_list[i]);
594 if (p_scb != NULL) {
595 tAVDT_SCB_EVT avdt_scb_evt;
596 avdt_scb_evt.msg.hdr = avdt_msg.hdr;
597 avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_REJ_EVT, &avdt_scb_evt);
598 }
599 }
600 }
601 }
602
603 /*******************************************************************************
604 *
605 * Function avdt_ccb_snd_suspend_rsp
606 *
607 * Description This function is called to send a suspend response to the
608 * peer. It takes the stream information passed in the event
609 * and sends a suspend response. Then it sends a suspend event
610 * to the SCB for each stream.
611 *
612 *
613 * Returns void.
614 *
615 ******************************************************************************/
avdt_ccb_snd_suspend_rsp(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)616 void avdt_ccb_snd_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
617 AvdtpScb* p_scb;
618 int i;
619
620 /* send response message */
621 avdt_msg_send_rsp(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
622
623 /* send start event to each scb */
624 for (i = 0; i < p_data->msg.multi.num_seps; i++) {
625 p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i]);
626 if (p_scb != NULL) {
627 avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_CMD_EVT, NULL);
628 }
629 }
630 }
631
632 /*******************************************************************************
633 *
634 * Function avdt_ccb_clear_cmds
635 *
636 * Description This function is called when the signaling channel is
637 * closed to clean up any pending commands. For each pending
638 * command in the command queue, it frees the command and
639 * calls the application callback function indicating failure.
640 * Certain CCB variables are also initialized.
641 *
642 *
643 * Returns void.
644 *
645 ******************************************************************************/
avdt_ccb_clear_cmds(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)646 void avdt_ccb_clear_cmds(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
647 int i;
648 AvdtpScb* p_scb = &(p_ccb->scb[0]);
649 uint8_t err_code = AVDT_ERR_CONNECT;
650
651 /* clear the ccb */
652 avdt_ccb_clear_ccb(p_ccb);
653
654 /* clear out command queue; this is a little tricky here; we need
655 ** to handle the case where there is a command on deck in p_curr_cmd,
656 ** plus we need to clear out the queue
657 */
658 do {
659 /* we know p_curr_cmd = NULL after this */
660 tAVDT_CCB_EVT avdt_ccb_evt;
661 avdt_ccb_evt.err_code = err_code;
662 avdt_ccb_cmd_fail(p_ccb, &avdt_ccb_evt);
663
664 /* set up next message */
665 p_ccb->p_curr_cmd = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->cmd_q);
666 } while (p_ccb->p_curr_cmd != NULL);
667
668 /* send a CC_CLOSE_EVT any active scbs associated with this ccb */
669 for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
670 if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb)) {
671 avdt_scb_event(p_scb, AVDT_SCB_CC_CLOSE_EVT, NULL);
672 }
673 }
674 }
675
676 /*******************************************************************************
677 *
678 * Function avdt_ccb_cmd_fail
679 *
680 * Description This function is called when there is a response timeout.
681 * The currently pending command is freed and we fake a
682 * reject message back to ourselves.
683 *
684 *
685 * Returns void.
686 *
687 ******************************************************************************/
avdt_ccb_cmd_fail(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)688 void avdt_ccb_cmd_fail(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
689 tAVDT_MSG msg;
690 uint8_t evt;
691 AvdtpScb* p_scb;
692
693 if (p_ccb->p_curr_cmd != NULL) {
694 /* set up data */
695 msg.hdr.err_code = p_data->err_code;
696 msg.hdr.err_param = 0;
697 msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
698
699 /* pretend that we received a rej message */
700 evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1];
701
702 if (evt & AVDT_CCB_MKR) {
703 tAVDT_CCB_EVT avdt_ccb_evt;
704 avdt_ccb_evt.msg = msg;
705 avdt_ccb_event(p_ccb, (uint8_t)(evt & ~AVDT_CCB_MKR), &avdt_ccb_evt);
706 } else {
707 /* we get the scb out of the current cmd */
708 p_scb = avdt_scb_by_hdl(*((uint8_t*)(p_ccb->p_curr_cmd + 1)));
709 if (p_scb != NULL) {
710 tAVDT_SCB_EVT avdt_scb_evt;
711 avdt_scb_evt.msg = msg;
712 avdt_scb_event(p_scb, evt, &avdt_scb_evt);
713 }
714 }
715
716 osi_free_and_reset((void**)&p_ccb->p_curr_cmd);
717 }
718 }
719
720 /*******************************************************************************
721 *
722 * Function avdt_ccb_free_cmd
723 *
724 * Description This function is called when a response is received for a
725 * currently pending command. The command is freed.
726 *
727 *
728 * Returns void.
729 *
730 ******************************************************************************/
avdt_ccb_free_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)731 void avdt_ccb_free_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
732 osi_free_and_reset((void**)&p_ccb->p_curr_cmd);
733 }
734
735 /*******************************************************************************
736 *
737 * Function avdt_ccb_cong_state
738 *
739 * Description This function is called to set the congestion state for
740 * the CCB.
741 *
742 *
743 * Returns void.
744 *
745 ******************************************************************************/
avdt_ccb_cong_state(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)746 void avdt_ccb_cong_state(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) { p_ccb->cong = p_data->llcong; }
747
748 /*******************************************************************************
749 *
750 * Function avdt_ccb_ret_cmd
751 *
752 * Description This function is called to retransmit the currently
753 * pending command. The retransmission count is incremented.
754 * If the count reaches the maximum number of retransmissions,
755 * the event is treated as a response timeout.
756 *
757 *
758 * Returns void.
759 *
760 ******************************************************************************/
avdt_ccb_ret_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)761 void avdt_ccb_ret_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
762 p_ccb->ret_count++;
763 if (p_ccb->ret_count == AVDT_RET_MAX) {
764 /* command failed */
765 p_ccb->ret_count = 0;
766 tAVDT_CCB_EVT avdt_ccb_evt;
767 avdt_ccb_evt.err_code = AVDT_ERR_TIMEOUT;
768 avdt_ccb_cmd_fail(p_ccb, &avdt_ccb_evt);
769
770 /* go to next queued command */
771 avdt_ccb_snd_cmd(p_ccb, p_data);
772 } else {
773 /* if command pending and we're not congested and not sending a fragment */
774 if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL)) {
775 /* make copy of message in p_curr_cmd and send it */
776 BT_HDR* p_msg = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
777 memcpy(p_msg, p_ccb->p_curr_cmd,
778 (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len));
779 avdt_msg_send(p_ccb, p_msg);
780 }
781
782 /* restart ret timer */
783 alarm_cancel(p_ccb->idle_ccb_timer);
784 alarm_cancel(p_ccb->rsp_ccb_timer);
785 uint64_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
786 alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms, avdt_ccb_ret_ccb_timer_timeout, p_ccb);
787 }
788 }
789
790 /*******************************************************************************
791 *
792 * Function avdt_ccb_snd_cmd
793 *
794 * Description This function is called the send the next command,
795 * if any, in the command queue.
796 *
797 *
798 * Returns void.
799 *
800 ******************************************************************************/
avdt_ccb_snd_cmd(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)801 void avdt_ccb_snd_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
802 BT_HDR* p_msg;
803
804 /* do we have commands to send? send next command; make sure we're clear;
805 ** not congested, not sending fragment, not waiting for response
806 */
807 if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd == NULL)) {
808 p_msg = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->cmd_q);
809 if (p_msg != NULL) {
810 /* make a copy of buffer in p_curr_cmd */
811 p_ccb->p_curr_cmd = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
812 memcpy(p_ccb->p_curr_cmd, p_msg, (sizeof(BT_HDR) + p_msg->offset + p_msg->len));
813 avdt_msg_send(p_ccb, p_msg);
814 }
815 }
816 }
817
818 /*******************************************************************************
819 *
820 * Function avdt_ccb_snd_msg
821 *
822 * Description
823 *
824 *
825 * Returns void.
826 *
827 ******************************************************************************/
avdt_ccb_snd_msg(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)828 void avdt_ccb_snd_msg(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
829 BT_HDR* p_msg;
830
831 /* if not congested */
832 if (!p_ccb->cong) {
833 /* are we sending a fragmented message? continue sending fragment */
834 if (p_ccb->p_curr_msg != NULL) {
835 avdt_msg_send(p_ccb, NULL);
836 } else if (!fixed_queue_is_empty(p_ccb->rsp_q)) {
837 /* do we have responses to send? send them */
838 while ((p_msg = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL) {
839 if (avdt_msg_send(p_ccb, p_msg)) {
840 /* break out if congested */
841 break;
842 }
843 }
844 }
845
846 /* do we have commands to send? send next command */
847 avdt_ccb_snd_cmd(p_ccb, NULL);
848 }
849 }
850
851 /*******************************************************************************
852 *
853 * Function avdt_ccb_set_reconn
854 *
855 * Description This function is called to enable a reconnect attempt when
856 * a channel transitions from closing to idle state. It sets
857 * the reconn variable to true.
858 *
859 *
860 * Returns void.
861 *
862 ******************************************************************************/
avdt_ccb_set_reconn(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)863 void avdt_ccb_set_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) { p_ccb->reconn = true; }
864
865 /*******************************************************************************
866 *
867 * Function avdt_ccb_clr_reconn
868 *
869 * Description This function is called to clear the reconn variable.
870 *
871 *
872 * Returns void.
873 *
874 ******************************************************************************/
avdt_ccb_clr_reconn(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)875 void avdt_ccb_clr_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) { p_ccb->reconn = false; }
876
877 /*******************************************************************************
878 *
879 * Function avdt_ccb_chk_reconn
880 *
881 * Description This function is called to check if a reconnect attempt
882 * is enabled. If enabled, it sends an AVDT_CCB_UL_OPEN_EVT
883 * to the CCB. If disabled, the CCB is deallocated.
884 *
885 *
886 * Returns void.
887 *
888 ******************************************************************************/
avdt_ccb_chk_reconn(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)889 void avdt_ccb_chk_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
890 if (p_ccb->reconn) {
891 p_ccb->reconn = false;
892
893 /* clear out ccb */
894 avdt_ccb_clear_ccb(p_ccb);
895
896 /* clear out current command, if any */
897 uint8_t err_code = AVDT_ERR_CONNECT;
898 tAVDT_CCB_EVT avdt_ccb_evt;
899 avdt_ccb_evt.err_code = err_code;
900 avdt_ccb_cmd_fail(p_ccb, &avdt_ccb_evt);
901
902 /* reopen the signaling channel */
903 avdt_ccb_event(p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL);
904 } else {
905 avdt_ccb_ll_closed(p_ccb, NULL);
906 }
907 }
908
909 /*******************************************************************************
910 *
911 * Function avdt_ccb_chk_timer
912 *
913 * Description This function stops the CCB timer if the idle timer is
914 * running.
915 *
916 *
917 * Returns void.
918 *
919 ******************************************************************************/
avdt_ccb_chk_timer(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)920 void avdt_ccb_chk_timer(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
921 alarm_cancel(p_ccb->idle_ccb_timer);
922 }
923
924 /*******************************************************************************
925 *
926 * Function avdt_ccb_set_conn
927 *
928 * Description Set CCB variables associated with AVDT_ConnectReq().
929 *
930 *
931 * Returns void.
932 *
933 ******************************************************************************/
avdt_ccb_set_conn(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)934 void avdt_ccb_set_conn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
935 /* save callback */
936 p_ccb->p_conn_cback = p_data->connect.p_cback;
937 }
938
939 /*******************************************************************************
940 *
941 * Function avdt_ccb_set_disconn
942 *
943 * Description Set CCB variables associated with AVDT_DisconnectReq().
944 *
945 *
946 * Returns void.
947 *
948 ******************************************************************************/
avdt_ccb_set_disconn(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)949 void avdt_ccb_set_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
950 /*
951 log::verbose("avdt_ccb_set_disconn:conn:x{:x}, api:x{:x}",
952 p_ccb->p_conn_cback, p_data->disconnect.p_cback);
953 */
954 /* save callback */
955 if (p_data->disconnect.p_cback) {
956 p_ccb->p_conn_cback = p_data->disconnect.p_cback;
957 }
958 }
959
960 /*******************************************************************************
961 *
962 * Function avdt_ccb_do_disconn
963 *
964 * Description Do action associated with AVDT_DisconnectReq().
965 *
966 *
967 * Returns void.
968 *
969 ******************************************************************************/
avdt_ccb_do_disconn(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)970 void avdt_ccb_do_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
971 /* clear any pending commands */
972 avdt_ccb_clear_cmds(p_ccb, NULL);
973
974 /* close channel */
975 avdt_ccb_chan_close(p_ccb, NULL);
976 }
977
978 /*******************************************************************************
979 *
980 * Function avdt_ccb_ll_closed
981 *
982 * Description Clear commands from and deallocate CCB.
983 *
984 *
985 * Returns void.
986 *
987 ******************************************************************************/
avdt_ccb_ll_closed(AvdtpCcb * p_ccb,tAVDT_CCB_EVT *)988 void avdt_ccb_ll_closed(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* /* p_data */) {
989 tAVDT_CTRL_CBACK* p_cback;
990 tAVDT_CTRL avdt_ctrl;
991
992 log::verbose("peer {}", p_ccb->peer_addr);
993
994 /* clear any pending commands */
995 avdt_ccb_clear_cmds(p_ccb, NULL);
996
997 /* save callback pointer, bd addr */
998 p_cback = p_ccb->p_conn_cback;
999 if (!p_cback) {
1000 p_cback = avdtp_cb.p_conn_cback;
1001 }
1002 RawAddress bd_addr = p_ccb->peer_addr;
1003 uint8_t bta_av_scb_index = p_ccb->BtaAvScbIndex();
1004
1005 /* dealloc ccb */
1006 avdt_ccb_dealloc(p_ccb, NULL);
1007
1008 /* call callback */
1009 if (p_cback) {
1010 avdt_ctrl.hdr.err_code = 0;
1011 (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl, bta_av_scb_index);
1012 }
1013 }
1014
1015 /*******************************************************************************
1016 *
1017 * Function avdt_ccb_ll_opened
1018 *
1019 * Description Call callback on open.
1020 *
1021 *
1022 * Returns void.
1023 *
1024 ******************************************************************************/
avdt_ccb_ll_opened(AvdtpCcb * p_ccb,tAVDT_CCB_EVT * p_data)1025 void avdt_ccb_ll_opened(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
1026 tAVDT_CTRL avdt_ctrl;
1027
1028 log::verbose("peer {} BtaAvScbIndex={} p_ccb={}", p_ccb->peer_addr, p_ccb->BtaAvScbIndex(),
1029 std::format_ptr(p_ccb));
1030 p_ccb->ll_opened = true;
1031
1032 if (!p_ccb->p_conn_cback) {
1033 p_ccb->p_conn_cback = avdtp_cb.p_conn_cback;
1034 }
1035
1036 /* call callback */
1037 if (p_ccb->p_conn_cback) {
1038 avdt_ctrl.hdr.err_code = 0;
1039 avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param;
1040 (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl,
1041 p_ccb->BtaAvScbIndex());
1042 }
1043 }
1044