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