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