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