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