avdt_ccb_act.cc revision 9ca07091a1f07ea201cee0504dab6a1d7073d429
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
368 *                  command.
369 *
370 *
371 *
372 * Returns          void.
373 *
374 ******************************************************************************/
375void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
376{
377    uint8_t     event;
378    int         i;
379    uint8_t     *p;
380    tAVDT_SCB   *p_scb;
381
382    /* determine rsp or rej event */
383    event = (p_data->msg.hdr.err_code == 0) ?
384            AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT;
385
386    /* get to where seid's are stashed in current cmd */
387    p = (uint8_t *)(p_ccb->p_curr_cmd + 1);
388
389    /* little trick here; length of current command equals number of streams */
390    for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
391    {
392        p_scb = avdt_scb_by_hdl(p[i]);
393        if (p_scb != NULL)
394        {
395            avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
396        }
397    }
398}
399
400/*******************************************************************************
401 *
402 * Function         avdt_ccb_snd_discover_cmd
403 *
404 * Description      This function is called to send a discover command to the
405 *                  peer.  It copies variables needed for the procedure from
406 *                  the event to the CCB.  It marks the CCB as busy and then
407 *                  sends a discover command.
408 *
409 *
410 * Returns          void.
411 *
412 ******************************************************************************/
413void avdt_ccb_snd_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
414{
415    /* store info in ccb struct */
416    p_ccb->p_proc_data = p_data->discover.p_sep_info;
417    p_ccb->proc_cback = p_data->discover.p_cback;
418    p_ccb->proc_param = p_data->discover.num_seps;
419
420    /* we're busy */
421    p_ccb->proc_busy = true;
422
423    /* build and queue discover req */
424    avdt_msg_send_cmd(p_ccb, NULL, AVDT_SIG_DISCOVER, NULL);
425}
426
427/*******************************************************************************
428 *
429 * Function         avdt_ccb_snd_discover_rsp
430 *
431 * Description      This function is called to send a discover response to
432 *                  the peer.  It takes the stream information passed in the
433 *                  event and sends a discover response.
434 *
435 *
436 * Returns          void.
437 *
438 ******************************************************************************/
439void avdt_ccb_snd_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
440{
441    /* send response */
442    avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg);
443}
444
445/*******************************************************************************
446 *
447 * Function         avdt_ccb_snd_getcap_cmd
448 *
449 * Description      This function is called to send a get capabilities command
450 *                  to the peer.  It copies variables needed for the procedure
451 *                  from the event to the CCB.  It marks the CCB as busy and
452 *                  then sends a get capabilities command.
453 *
454 *
455 * Returns          void.
456 *
457 ******************************************************************************/
458void avdt_ccb_snd_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
459{
460    uint8_t sig_id = AVDT_SIG_GETCAP;
461
462    /* store info in ccb struct */
463    p_ccb->p_proc_data = p_data->getcap.p_cfg;
464    p_ccb->proc_cback = p_data->getcap.p_cback;
465
466    /* we're busy */
467    p_ccb->proc_busy = true;
468
469    /* build and queue discover req */
470    if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
471        sig_id = AVDT_SIG_GET_ALLCAP;
472
473    avdt_msg_send_cmd(p_ccb, NULL, sig_id, (tAVDT_MSG *) &p_data->getcap.single);
474}
475
476/*******************************************************************************
477 *
478 * Function         avdt_ccb_snd_getcap_rsp
479 *
480 * Description      This function is called to send a get capabilities response
481 *                  to the peer.  It takes the stream information passed in the
482 *                  event and sends a get capabilities response.
483 *
484 *
485 * Returns          void.
486 *
487 ******************************************************************************/
488void avdt_ccb_snd_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
489{
490    uint8_t sig_id = AVDT_SIG_GETCAP;
491
492    if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
493        sig_id = AVDT_SIG_GET_ALLCAP;
494
495    /* send response */
496    avdt_msg_send_rsp(p_ccb, sig_id, &p_data->msg);
497}
498
499/*******************************************************************************
500 *
501 * Function         avdt_ccb_snd_start_cmd
502 *
503 * Description      This function is called to send a start command to the
504 *                  peer.  It verifies that all requested streams are in the
505 *                  proper state.  If so, it sends a start command.  Otherwise
506 *                  send ourselves back a start reject.
507 *
508 *
509 * Returns          void.
510 *
511 ******************************************************************************/
512void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
513{
514    int             i;
515    tAVDT_SCB       *p_scb;
516    tAVDT_MSG       avdt_msg;
517    uint8_t         seid_list[AVDT_NUM_SEPS];
518
519    /* make copy of our seid list */
520    memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
521
522    /* verify all streams in the right state */
523    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);
524    if (avdt_msg.hdr.err_param == 0)
525    {
526        /* set peer seid list in messsage */
527        avdt_scb_peer_seid_list(&p_data->msg.multi);
528
529        /* send command */
530        avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_START, &p_data->msg);
531    }
532    else
533    {
534        /* failed; send ourselves a reject for each stream */
535        for (i = 0; i < p_data->msg.multi.num_seps; i++)
536        {
537            p_scb = avdt_scb_by_hdl(seid_list[i]);
538            if (p_scb != NULL)
539            {
540                avdt_scb_event(p_scb, AVDT_SCB_MSG_START_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
541            }
542        }
543    }
544}
545
546/*******************************************************************************
547 *
548 * Function         avdt_ccb_snd_start_rsp
549 *
550 * Description      This function is called to send a start response to the
551 *                  peer.  It takes the stream information passed in the event
552 *                  and sends a start response.  Then it sends a start event
553 *                  to the SCB for each stream.
554 *
555 *
556 * Returns          void.
557 *
558 ******************************************************************************/
559void avdt_ccb_snd_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
560{
561    tAVDT_SCB *p_scb;
562    int i;
563
564    /* send response message */
565    avdt_msg_send_rsp(p_ccb, AVDT_SIG_START, &p_data->msg);
566
567    /* send start event to each scb */
568    for (i = 0; i < p_data->msg.multi.num_seps; i++)
569    {
570        p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i]);
571        if (p_scb != NULL)
572        {
573            avdt_scb_event(p_scb, AVDT_SCB_MSG_START_CMD_EVT, NULL);
574        }
575    }
576}
577
578/*******************************************************************************
579 *
580 * Function         avdt_ccb_snd_suspend_cmd
581 *
582 * Description      This function is called to send a suspend command to the
583 *                  peer.  It verifies that all requested streams are in the
584 *                  proper state.  If so, it sends a suspend command.
585 *                  Otherwise it calls the callback function for each requested
586 *                  stream and sends a suspend confirmation with failure.
587 *
588 *
589 * Returns          void.
590 *
591 ******************************************************************************/
592void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
593{
594    int             i;
595    tAVDT_SCB       *p_scb;
596    tAVDT_MSG       avdt_msg;
597    uint8_t         seid_list[AVDT_NUM_SEPS];
598
599    /* make copy of our seid list */
600    memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
601
602    /* verify all streams in the right state */
603    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);
604    if (avdt_msg.hdr.err_param == 0)
605    {
606        /* set peer seid list in messsage */
607        avdt_scb_peer_seid_list(&p_data->msg.multi);
608
609        /* send command */
610        avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_SUSPEND, &p_data->msg);
611    }
612    else
613    {
614        /* failed; send ourselves a reject for each stream */
615        for (i = 0; i < p_data->msg.multi.num_seps; i++)
616        {
617            p_scb = avdt_scb_by_hdl(seid_list[i]);
618            if (p_scb != NULL)
619            {
620                avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
621            }
622        }
623    }
624}
625
626/*******************************************************************************
627 *
628 * Function         avdt_ccb_snd_suspend_rsp
629 *
630 * Description      This function is called to send a suspend response to the
631 *                  peer.  It takes the stream information passed in the event
632 *                  and sends a suspend response.  Then it sends a suspend event
633 *                  to the SCB for each stream.
634 *
635 *
636 * Returns          void.
637 *
638 ******************************************************************************/
639void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
640{
641    tAVDT_SCB *p_scb;
642    int i;
643
644    /* send response message */
645    avdt_msg_send_rsp(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
646
647    /* send start event to each scb */
648    for (i = 0; i < p_data->msg.multi.num_seps; i++)
649    {
650        p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i]);
651        if (p_scb != NULL)
652        {
653            avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_CMD_EVT, NULL);
654        }
655    }
656}
657
658/*******************************************************************************
659 *
660 * Function         avdt_ccb_clear_cmds
661 *
662 * Description      This function is called when the signaling channel is
663 *                  closed to clean up any pending commands.  For each pending
664 *                  command in the command queue, it frees the command and
665 *                  calls the application callback function indicating failure.
666 *                  Certain CCB variables are also initialized.
667 *
668 *
669 * Returns          void.
670 *
671 ******************************************************************************/
672void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb,
673                         UNUSED_ATTR tAVDT_CCB_EVT *p_data)
674{
675    int             i;
676    tAVDT_SCB       *p_scb = &avdt_cb.scb[0];
677    uint8_t         err_code = AVDT_ERR_CONNECT;
678
679    /* clear the ccb */
680    avdt_ccb_clear_ccb(p_ccb);
681
682    /* clear out command queue; this is a little tricky here; we need
683    ** to handle the case where there is a command on deck in p_curr_cmd,
684    ** plus we need to clear out the queue
685    */
686    do
687    {
688        /* we know p_curr_cmd = NULL after this */
689        avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
690
691        /* set up next message */
692        p_ccb->p_curr_cmd = (BT_HDR *) fixed_queue_try_dequeue(p_ccb->cmd_q);
693
694    } while (p_ccb->p_curr_cmd != NULL);
695
696    /* send a CC_CLOSE_EVT any active scbs associated with this ccb */
697    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
698    {
699        if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb))
700        {
701            avdt_scb_event(p_scb, AVDT_SCB_CC_CLOSE_EVT, NULL);
702        }
703    }
704}
705
706/*******************************************************************************
707 *
708 * Function         avdt_ccb_cmd_fail
709 *
710 * Description      This function is called when there is a response timeout.
711 *                  The currently pending command is freed and we fake a
712 *                  reject message back to ourselves.
713 *
714 *
715 * Returns          void.
716 *
717 ******************************************************************************/
718void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
719{
720    tAVDT_MSG       msg;
721    uint8_t         evt;
722    tAVDT_SCB       *p_scb;
723
724    if (p_ccb->p_curr_cmd != NULL)
725    {
726        /* set up data */
727        msg.hdr.err_code = p_data->err_code;
728        msg.hdr.err_param = 0;
729        msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
730
731        /* pretend that we received a rej message */
732        evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1];
733
734        if (evt & AVDT_CCB_MKR)
735        {
736            avdt_ccb_event(p_ccb, (uint8_t) (evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg);
737        }
738        else
739        {
740            /* we get the scb out of the current cmd */
741            p_scb = avdt_scb_by_hdl(*((uint8_t *)(p_ccb->p_curr_cmd + 1)));
742            if (p_scb != NULL)
743            {
744                avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg);
745            }
746        }
747
748        osi_free_and_reset((void **)&p_ccb->p_curr_cmd);
749    }
750}
751
752/*******************************************************************************
753 *
754 * Function         avdt_ccb_free_cmd
755 *
756 * Description      This function is called when a response is received for a
757 *                  currently pending command.  The command is freed.
758 *
759 *
760 * Returns          void.
761 *
762 ******************************************************************************/
763void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb,
764                       UNUSED_ATTR tAVDT_CCB_EVT *p_data)
765{
766    osi_free_and_reset((void **)&p_ccb->p_curr_cmd);
767}
768
769/*******************************************************************************
770 *
771 * Function         avdt_ccb_cong_state
772 *
773 * Description      This function is called to set the congestion state for
774 *                  the CCB.
775 *
776 *
777 * Returns          void.
778 *
779 ******************************************************************************/
780void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
781{
782    p_ccb->cong = p_data->llcong;
783}
784
785/*******************************************************************************
786 *
787 * Function         avdt_ccb_ret_cmd
788 *
789 * Description      This function is called to retransmit the currently
790 *                  pending command.  The retransmission count is incremented.
791 *                  If the count reaches the maximum number of retransmissions,
792 *                  the event is treated as a response timeout.
793 *
794 *
795 * Returns          void.
796 *
797 ******************************************************************************/
798void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
799{
800    uint8_t err_code = AVDT_ERR_TIMEOUT;
801
802    p_ccb->ret_count++;
803    if (p_ccb->ret_count == AVDT_RET_MAX)
804    {
805        /* command failed */
806        p_ccb->ret_count = 0;
807        avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
808
809        /* go to next queued command */
810        avdt_ccb_snd_cmd(p_ccb, p_data);
811    }
812    else
813    {
814        /* if command pending and we're not congested and not sending a fragment */
815        if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL))
816        {
817            /* make copy of message in p_curr_cmd and send it */
818            BT_HDR *p_msg = (BT_HDR *)osi_malloc(AVDT_CMD_BUF_SIZE);
819            memcpy(p_msg, p_ccb->p_curr_cmd,
820                   (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len));
821            avdt_msg_send(p_ccb, p_msg);
822        }
823
824        /* restart ret timer */
825        alarm_cancel(p_ccb->idle_ccb_timer);
826        alarm_cancel(p_ccb->rsp_ccb_timer);
827        period_ms_t interval_ms = avdt_cb.rcb.ret_tout * 1000;
828        alarm_set_on_queue(p_ccb->ret_ccb_timer, interval_ms,
829                           avdt_ccb_ret_ccb_timer_timeout, p_ccb,
830                           btu_general_alarm_queue);
831    }
832}
833
834/*******************************************************************************
835 *
836 * Function         avdt_ccb_snd_cmd
837 *
838 * Description      This function is called the send the next command,
839 *                  if any, in the command queue.
840 *
841 *
842 * Returns          void.
843 *
844 ******************************************************************************/
845void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb,
846                      UNUSED_ATTR tAVDT_CCB_EVT *p_data)
847{
848    BT_HDR  *p_msg;
849
850    /* do we have commands to send?  send next command;  make sure we're clear;
851    ** not congested, not sending fragment, not waiting for response
852    */
853    if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd == NULL))
854    {
855        p_msg = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->cmd_q);
856        if (p_msg != NULL)
857        {
858            /* make a copy of buffer in p_curr_cmd */
859            p_ccb->p_curr_cmd = (BT_HDR *)osi_malloc(AVDT_CMD_BUF_SIZE);
860            memcpy(p_ccb->p_curr_cmd, p_msg,
861                   (sizeof(BT_HDR) + p_msg->offset + p_msg->len));
862            avdt_msg_send(p_ccb, p_msg);
863        }
864    }
865}
866
867/*******************************************************************************
868 *
869 * Function         avdt_ccb_snd_msg
870 *
871 * Description
872 *
873 *
874 * Returns          void.
875 *
876 ******************************************************************************/
877void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb,
878                      UNUSED_ATTR tAVDT_CCB_EVT *p_data)
879{
880    BT_HDR      *p_msg;
881
882    /* if not congested */
883    if (!p_ccb->cong)
884    {
885        /* are we sending a fragmented message? continue sending fragment */
886        if (p_ccb->p_curr_msg != NULL)
887        {
888            avdt_msg_send(p_ccb, NULL);
889        }
890        /* do we have responses to send?  send them */
891        else if (!fixed_queue_is_empty(p_ccb->rsp_q))
892        {
893            while ((p_msg = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL)
894            {
895                if (avdt_msg_send(p_ccb, p_msg) == true)
896                {
897                    /* break out if congested */
898                    break;
899                }
900            }
901        }
902
903        /* do we have commands to send?  send next command */
904        avdt_ccb_snd_cmd(p_ccb, NULL);
905    }
906}
907
908/*******************************************************************************
909 *
910 * Function         avdt_ccb_set_reconn
911 *
912 * Description      This function is called to enable a reconnect attempt when
913 *                  a channel transitions from closing to idle state.  It sets
914 *                  the reconn variable to true.
915 *
916 *
917 * Returns          void.
918 *
919 ******************************************************************************/
920void avdt_ccb_set_reconn(tAVDT_CCB *p_ccb,
921                         UNUSED_ATTR tAVDT_CCB_EVT *p_data)
922{
923    p_ccb->reconn = true;
924}
925
926/*******************************************************************************
927 *
928 * Function         avdt_ccb_clr_reconn
929 *
930 * Description      This function is called to clear the reconn variable.
931 *
932 *
933 * Returns          void.
934 *
935 ******************************************************************************/
936void avdt_ccb_clr_reconn(tAVDT_CCB *p_ccb,
937                         UNUSED_ATTR tAVDT_CCB_EVT *p_data)
938{
939    p_ccb->reconn = false;
940}
941
942/*******************************************************************************
943 *
944 * Function         avdt_ccb_chk_reconn
945 *
946 * Description      This function is called to check if a reconnect attempt
947 *                  is enabled.  If enabled, it sends an AVDT_CCB_UL_OPEN_EVT
948 *                  to the CCB.  If disabled, the CCB is deallocated.
949 *
950 *
951 * Returns          void.
952 *
953 ******************************************************************************/
954void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb,
955                         UNUSED_ATTR tAVDT_CCB_EVT *p_data)
956{
957    uint8_t err_code = AVDT_ERR_CONNECT;
958
959    if (p_ccb->reconn)
960    {
961        p_ccb->reconn = false;
962
963        /* clear out ccb */
964        avdt_ccb_clear_ccb(p_ccb);
965
966        /* clear out current command, if any */
967        avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
968
969        /* reopen the signaling channel */
970        avdt_ccb_event(p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL);
971    }
972    else
973    {
974        avdt_ccb_ll_closed(p_ccb, NULL);
975    }
976}
977
978/*******************************************************************************
979 *
980 * Function         avdt_ccb_chk_timer
981 *
982 * Description      This function stops the CCB timer if the idle timer is
983 *                  running.
984 *
985 *
986 * Returns          void.
987 *
988 ******************************************************************************/
989void avdt_ccb_chk_timer(tAVDT_CCB *p_ccb,
990                        UNUSED_ATTR tAVDT_CCB_EVT *p_data)
991{
992    alarm_cancel(p_ccb->idle_ccb_timer);
993}
994
995/*******************************************************************************
996 *
997 * Function         avdt_ccb_set_conn
998 *
999 * Description      Set CCB variables associated with AVDT_ConnectReq().
1000 *
1001 *
1002 * Returns          void.
1003 *
1004 ******************************************************************************/
1005void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1006{
1007    /* save callback */
1008    p_ccb->p_conn_cback = p_data->connect.p_cback;
1009
1010    /* set security level */
1011    BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask,
1012                         AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
1013}
1014
1015/*******************************************************************************
1016 *
1017 * Function         avdt_ccb_set_disconn
1018 *
1019 * Description      Set CCB variables associated with AVDT_DisconnectReq().
1020 *
1021 *
1022 * Returns          void.
1023 *
1024 ******************************************************************************/
1025void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1026{
1027    /*
1028    AVDT_TRACE_EVENT("avdt_ccb_set_disconn:conn:x%x, api:x%x",
1029        p_ccb->p_conn_cback, p_data->disconnect.p_cback);
1030        */
1031    /* save callback */
1032    if (p_data->disconnect.p_cback)
1033        p_ccb->p_conn_cback = p_data->disconnect.p_cback;
1034}
1035
1036/*******************************************************************************
1037 *
1038 * Function         avdt_ccb_do_disconn
1039 *
1040 * Description      Do action associated with AVDT_DisconnectReq().
1041 *
1042 *
1043 * Returns          void.
1044 *
1045 ******************************************************************************/
1046void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb,
1047                         UNUSED_ATTR tAVDT_CCB_EVT *p_data)
1048{
1049    /* clear any pending commands */
1050    avdt_ccb_clear_cmds(p_ccb, NULL);
1051
1052    /* close channel */
1053    avdt_ccb_chan_close(p_ccb, NULL);
1054}
1055
1056/*******************************************************************************
1057 *
1058 * Function         avdt_ccb_ll_closed
1059 *
1060 * Description      Clear commands from and deallocate CCB.
1061 *
1062 *
1063 * Returns          void.
1064 *
1065 ******************************************************************************/
1066void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb,
1067                        UNUSED_ATTR tAVDT_CCB_EVT *p_data)
1068{
1069    tAVDT_CTRL_CBACK    *p_cback;
1070    BD_ADDR             bd_addr;
1071    tAVDT_CTRL          avdt_ctrl;
1072
1073    /* clear any pending commands */
1074    avdt_ccb_clear_cmds(p_ccb, NULL);
1075
1076    /* save callback pointer, bd addr */
1077    p_cback = p_ccb->p_conn_cback;
1078    if (!p_cback)
1079        p_cback = avdt_cb.p_conn_cback;
1080    memcpy(bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
1081
1082    /* dealloc ccb */
1083    avdt_ccb_dealloc(p_ccb, NULL);
1084
1085    /* call callback */
1086    if (p_cback)
1087    {
1088        avdt_ctrl.hdr.err_code = 0;
1089        (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
1090    }
1091}
1092
1093/*******************************************************************************
1094 *
1095 * Function         avdt_ccb_ll_opened
1096 *
1097 * Description      Call callback on open.
1098 *
1099 *
1100 * Returns          void.
1101 *
1102 ******************************************************************************/
1103void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1104{
1105    tAVDT_CTRL          avdt_ctrl;
1106
1107    p_ccb->ll_opened = true;
1108
1109    if (!p_ccb->p_conn_cback)
1110        p_ccb->p_conn_cback = avdt_cb.p_conn_cback;
1111
1112    /* call callback */
1113    if (p_ccb->p_conn_cback)
1114    {
1115        avdt_ctrl.hdr.err_code = 0;
1116        avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param;
1117        (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl);
1118    }
1119}
1120