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