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