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