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