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