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