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