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