• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2006-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This module contains the action functions associated with the channel
22  *  control block state machine.
23  *
24  ******************************************************************************/
25 
26 #include <string.h>
27 #include "bt_types.h"
28 #include "bt_target.h"
29 #include "bt_utils.h"
30 #include "avdt_api.h"
31 #include "avdtc_api.h"
32 #include "avdt_int.h"
33 #include "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   err_code = 0;
274 
275     /* verify all streams in the right state */
276     UINT8 seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_START, p_data->msg.multi.seid_list,
277                                  p_data->msg.multi.num_seps, &err_code);
278     if (seid == 0 && 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     } else {
283         /* not ok, send reject */
284         p_data->msg.hdr.err_code = err_code;
285         p_data->msg.hdr.err_param = seid;
286         avdt_msg_send_rej(p_ccb, AVDT_SIG_START, &p_data->msg);
287     }
288 }
289 
290 /*******************************************************************************
291 **
292 ** Function         avdt_ccb_hdl_start_rsp
293 **
294 ** Description      This function is called when a start response or reject
295 **                  is received from the peer.  Using the SEIDs stored in the
296 **                  current command message, it sends a start response or start
297 **                  reject event to each SCB associated with the command.
298 **
299 **
300 ** Returns          void.
301 **
302 *******************************************************************************/
avdt_ccb_hdl_start_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)303 void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
304 {
305     UINT8       event;
306     int         i;
307     UINT8       *p;
308     tAVDT_SCB   *p_scb;
309 
310     /* determine rsp or rej event */
311     event = (p_data->msg.hdr.err_code == 0) ?
312             AVDT_SCB_MSG_START_RSP_EVT : AVDT_SCB_MSG_START_REJ_EVT;
313 
314     /* get to where seid's are stashed in current cmd */
315     p = (UINT8 *)(p_ccb->p_curr_cmd + 1);
316 
317     /* little trick here; length of current command equals number of streams */
318     for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
319     {
320         if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL)
321         {
322             avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
323         }
324     }
325 }
326 
327 /*******************************************************************************
328 **
329 ** Function         avdt_ccb_hdl_suspend_cmd
330 **
331 ** Description      This function is called when a suspend command is received
332 **                  from the peer.  It verifies that all requested streams are
333 **                  in the proper state.  If so, it initiates sending of a
334 **                  suspend response.  Otherwise it sends a suspend reject.
335 
336 **
337 **
338 ** Returns          void.
339 **
340 *******************************************************************************/
avdt_ccb_hdl_suspend_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)341 void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
342 {
343     UINT8   seid;
344     UINT8   err_code = 0;
345 
346     /* verify all streams in the right state */
347     if ((seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_SUSPEND, p_data->msg.multi.seid_list,
348                                 p_data->msg.multi.num_seps, &err_code)) == 0 &&
349                                 err_code == 0)
350     {
351         /* we're ok, send response */
352         avdt_ccb_event(p_ccb, AVDT_CCB_API_SUSPEND_RSP_EVT, p_data);
353     }
354     else
355     {
356         /* not ok, send reject */
357         p_data->msg.hdr.err_code = err_code;
358         p_data->msg.hdr.err_param = seid;
359         avdt_msg_send_rej(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
360     }
361 }
362 
363 /*******************************************************************************
364 **
365 ** Function         avdt_ccb_hdl_suspend_rsp
366 **
367 ** Description      This function is called when a suspend response or reject
368 **                  is received from the peer.  Using the SEIDs stored in the
369 **                  current command message, it sends a suspend response or
370 **                  suspend reject event to each SCB associated with the command.
371 **
372 **
373 **
374 ** Returns          void.
375 **
376 *******************************************************************************/
avdt_ccb_hdl_suspend_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)377 void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
378 {
379     UINT8       event;
380     int         i;
381     UINT8       *p;
382     tAVDT_SCB   *p_scb;
383 
384     /* determine rsp or rej event */
385     event = (p_data->msg.hdr.err_code == 0) ?
386             AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT;
387 
388     /* get to where seid's are stashed in current cmd */
389     p = (UINT8 *)(p_ccb->p_curr_cmd + 1);
390 
391     /* little trick here; length of current command equals number of streams */
392     for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
393     {
394         if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL)
395         {
396             avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
397         }
398     }
399 }
400 
401 /*******************************************************************************
402 **
403 ** Function         avdt_ccb_snd_discover_cmd
404 **
405 ** Description      This function is called to send a discover command to the
406 **                  peer.  It copies variables needed for the procedure from
407 **                  the event to the CCB.  It marks the CCB as busy and then
408 **                  sends a discover command.
409 **
410 **
411 ** Returns          void.
412 **
413 *******************************************************************************/
avdt_ccb_snd_discover_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)414 void avdt_ccb_snd_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
415 {
416     /* store info in ccb struct */
417     p_ccb->p_proc_data = p_data->discover.p_sep_info;
418     p_ccb->proc_cback = p_data->discover.p_cback;
419     p_ccb->proc_param = p_data->discover.num_seps;
420 
421     /* we're busy */
422     p_ccb->proc_busy = TRUE;
423 
424     /* build and queue discover req */
425     avdt_msg_send_cmd(p_ccb, NULL, AVDT_SIG_DISCOVER, NULL);
426 }
427 
428 /*******************************************************************************
429 **
430 ** Function         avdt_ccb_snd_discover_rsp
431 **
432 ** Description      This function is called to send a discover response to
433 **                  the peer.  It takes the stream information passed in the
434 **                  event and sends a discover response.
435 **
436 **
437 ** Returns          void.
438 **
439 *******************************************************************************/
avdt_ccb_snd_discover_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)440 void avdt_ccb_snd_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
441 {
442     /* send response */
443     avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg);
444 }
445 
446 /*******************************************************************************
447 **
448 ** Function         avdt_ccb_snd_getcap_cmd
449 **
450 ** Description      This function is called to send a get capabilities command
451 **                  to the peer.  It copies variables needed for the procedure
452 **                  from the event to the CCB.  It marks the CCB as busy and
453 **                  then sends a get capabilities command.
454 **
455 **
456 ** Returns          void.
457 **
458 *******************************************************************************/
avdt_ccb_snd_getcap_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)459 void avdt_ccb_snd_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
460 {
461     UINT8 sig_id = AVDT_SIG_GETCAP;
462 
463     /* store info in ccb struct */
464     p_ccb->p_proc_data = p_data->getcap.p_cfg;
465     p_ccb->proc_cback = p_data->getcap.p_cback;
466 
467     /* we're busy */
468     p_ccb->proc_busy = TRUE;
469 
470     /* build and queue discover req */
471     if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
472         sig_id = AVDT_SIG_GET_ALLCAP;
473 
474     avdt_msg_send_cmd(p_ccb, NULL, sig_id, (tAVDT_MSG *) &p_data->getcap.single);
475 }
476 
477 /*******************************************************************************
478 **
479 ** Function         avdt_ccb_snd_getcap_rsp
480 **
481 ** Description      This function is called to send a get capabilities response
482 **                  to the peer.  It takes the stream information passed in the
483 **                  event and sends a get capabilities response.
484 **
485 **
486 ** Returns          void.
487 **
488 *******************************************************************************/
avdt_ccb_snd_getcap_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)489 void avdt_ccb_snd_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
490 {
491     UINT8 sig_id = AVDT_SIG_GETCAP;
492 
493     if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
494         sig_id = AVDT_SIG_GET_ALLCAP;
495 
496     /* send response */
497     avdt_msg_send_rsp(p_ccb, sig_id, &p_data->msg);
498 }
499 
500 /*******************************************************************************
501 **
502 ** Function         avdt_ccb_snd_start_cmd
503 **
504 ** Description      This function is called to send a start command to the
505 **                  peer.  It verifies that all requested streams are in the
506 **                  proper state.  If so, it sends a start command.  Otherwise
507 **                  send ourselves back a start reject.
508 **
509 **
510 ** Returns          void.
511 **
512 *******************************************************************************/
avdt_ccb_snd_start_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)513 void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
514 {
515     int             i;
516     tAVDT_SCB       *p_scb;
517     tAVDT_MSG       avdt_msg;
518     UINT8           seid_list[AVDT_NUM_SEPS];
519 
520     /* make copy of our seid list */
521     memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
522 
523     /* verify all streams in the right state */
524     if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_OPEN, p_data->msg.multi.seid_list,
525                                          p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0)
526     {
527         /* set peer seid list in messsage */
528         avdt_scb_peer_seid_list(&p_data->msg.multi);
529 
530         /* send command */
531         avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_START, &p_data->msg);
532     }
533     else
534     {
535         /* failed; send ourselves a reject for each stream */
536         for (i = 0; i < p_data->msg.multi.num_seps; i++)
537         {
538             if ((p_scb = avdt_scb_by_hdl(seid_list[i])) != 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 *******************************************************************************/
avdt_ccb_snd_start_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)559 void 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         if ((p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i])) != NULL)
571         {
572             avdt_scb_event(p_scb, AVDT_SCB_MSG_START_CMD_EVT, NULL);
573         }
574     }
575 }
576 
577 /*******************************************************************************
578 **
579 ** Function         avdt_ccb_snd_suspend_cmd
580 **
581 ** Description      This function is called to send a suspend command to the
582 **                  peer.  It verifies that all requested streams are in the
583 **                  proper state.  If so, it sends a suspend command.
584 **                  Otherwise it calls the callback function for each requested
585 **                  stream and sends a suspend confirmation with failure.
586 **
587 **
588 ** Returns          void.
589 **
590 *******************************************************************************/
avdt_ccb_snd_suspend_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)591 void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
592 {
593     int             i;
594     tAVDT_SCB       *p_scb;
595     tAVDT_MSG       avdt_msg;
596     UINT8           seid_list[AVDT_NUM_SEPS];
597 
598     /* make copy of our seid list */
599     memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
600 
601     /* verify all streams in the right state */
602     if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_STREAMING, p_data->msg.multi.seid_list,
603                                          p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0)
604     {
605         /* set peer seid list in messsage */
606         avdt_scb_peer_seid_list(&p_data->msg.multi);
607 
608         /* send command */
609         avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_SUSPEND, &p_data->msg);
610     }
611     else
612     {
613         /* failed; send ourselves a reject for each stream */
614         for (i = 0; i < p_data->msg.multi.num_seps; i++)
615         {
616             if ((p_scb = avdt_scb_by_hdl(seid_list[i])) != NULL)
617             {
618                 avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
619             }
620         }
621     }
622 }
623 
624 /*******************************************************************************
625 **
626 ** Function         avdt_ccb_snd_suspend_rsp
627 **
628 ** Description      This function is called to send a suspend response to the
629 **                  peer.  It takes the stream information passed in the event
630 **                  and sends a suspend response.  Then it sends a suspend event
631 **                  to the SCB for each stream.
632 **
633 **
634 ** Returns          void.
635 **
636 *******************************************************************************/
avdt_ccb_snd_suspend_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)637 void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
638 {
639     tAVDT_SCB *p_scb;
640     int i;
641 
642     /* send response message */
643     avdt_msg_send_rsp(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
644 
645     /* send start event to each scb */
646     for (i = 0; i < p_data->msg.multi.num_seps; i++)
647     {
648         if ((p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i])) != NULL)
649         {
650             avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_CMD_EVT, NULL);
651         }
652     }
653 }
654 
655 /*******************************************************************************
656 **
657 ** Function         avdt_ccb_clear_cmds
658 **
659 ** Description      This function is called when the signaling channel is
660 **                  closed to clean up any pending commands.  For each pending
661 **                  command in the command queue, it frees the command and
662 **                  calls the application callback function indicating failure.
663 **                  Certain CCB variables are also initialized.
664 **
665 **
666 ** Returns          void.
667 **
668 *******************************************************************************/
avdt_ccb_clear_cmds(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)669 void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
670 {
671     int             i;
672     tAVDT_SCB       *p_scb = &avdt_cb.scb[0];
673     UINT8           err_code = AVDT_ERR_CONNECT;
674     UNUSED(p_data);
675 
676     /* clear the ccb */
677     avdt_ccb_clear_ccb(p_ccb);
678 
679     /* clear out command queue; this is a little tricky here; we need
680     ** to handle the case where there is a command on deck in p_curr_cmd,
681     ** plus we need to clear out the queue
682     */
683     do
684     {
685         /* we know p_curr_cmd = NULL after this */
686         avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
687 
688         /* set up next message */
689         p_ccb->p_curr_cmd = (BT_HDR *) GKI_dequeue(&p_ccb->cmd_q);
690 
691     } while (p_ccb->p_curr_cmd != NULL);
692 
693     /* send a CC_CLOSE_EVT any active scbs associated with this ccb */
694     for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
695     {
696         if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb))
697         {
698             avdt_scb_event(p_scb, AVDT_SCB_CC_CLOSE_EVT, NULL);
699         }
700     }
701 }
702 
703 /*******************************************************************************
704 **
705 ** Function         avdt_ccb_cmd_fail
706 **
707 ** Description      This function is called when there is a response timeout.
708 **                  The currently pending command is freed and we fake a
709 **                  reject message back to ourselves.
710 **
711 **
712 ** Returns          void.
713 **
714 *******************************************************************************/
avdt_ccb_cmd_fail(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)715 void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
716 {
717     tAVDT_MSG       msg;
718     UINT8           evt;
719     tAVDT_SCB       *p_scb;
720 
721     if (p_ccb->p_curr_cmd != NULL)
722     {
723         /* set up data */
724         msg.hdr.err_code = p_data->err_code;
725         msg.hdr.err_param = 0;
726         msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
727 
728         /* pretend that we received a rej message */
729         evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1];
730 
731         if (evt & AVDT_CCB_MKR)
732         {
733             avdt_ccb_event(p_ccb, (UINT8) (evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg);
734         }
735         else
736         {
737             /* we get the scb out of the current cmd */
738             p_scb = avdt_scb_by_hdl(*((UINT8 *)(p_ccb->p_curr_cmd + 1)));
739             if (p_scb != NULL)
740             {
741                 avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg);
742             }
743         }
744 
745         GKI_freebuf(p_ccb->p_curr_cmd);
746         p_ccb->p_curr_cmd = NULL;
747     }
748 }
749 
750 /*******************************************************************************
751 **
752 ** Function         avdt_ccb_free_cmd
753 **
754 ** Description      This function is called when a response is received for a
755 **                  currently pending command.  The command is freed.
756 **
757 **
758 ** Returns          void.
759 **
760 *******************************************************************************/
avdt_ccb_free_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)761 void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
762 {
763     UNUSED(p_data);
764 
765     if (p_ccb->p_curr_cmd != NULL)
766     {
767         GKI_freebuf(p_ccb->p_curr_cmd);
768         p_ccb->p_curr_cmd = NULL;
769     }
770 }
771 
772 /*******************************************************************************
773 **
774 ** Function         avdt_ccb_cong_state
775 **
776 ** Description      This function is called to set the congestion state for
777 **                  the CCB.
778 **
779 **
780 ** Returns          void.
781 **
782 *******************************************************************************/
avdt_ccb_cong_state(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)783 void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
784 {
785     p_ccb->cong = p_data->llcong;
786 }
787 
788 /*******************************************************************************
789 **
790 ** Function         avdt_ccb_ret_cmd
791 **
792 ** Description      This function is called to retransmit the currently
793 **                  pending command.  The retransmission count is incremented.
794 **                  If the count reaches the maximum number of retransmissions,
795 **                  the event is treated as a response timeout.
796 **
797 **
798 ** Returns          void.
799 **
800 *******************************************************************************/
avdt_ccb_ret_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)801 void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
802 {
803     UINT8   err_code = AVDT_ERR_TIMEOUT;
804     BT_HDR  *p_msg;
805 
806     p_ccb->ret_count++;
807     if (p_ccb->ret_count == AVDT_RET_MAX)
808     {
809         /* command failed */
810         p_ccb->ret_count = 0;
811         avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
812 
813         /* go to next queued command */
814         avdt_ccb_snd_cmd(p_ccb, p_data);
815     }
816     else
817     {
818         /* if command pending and we're not congested and not sending a fragment */
819         if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL))
820         {
821             /* make copy of message in p_curr_cmd and send it */
822             if ((p_msg = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) != NULL)
823             {
824                 memcpy(p_msg, p_ccb->p_curr_cmd,
825                        (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len));
826                 avdt_msg_send(p_ccb, p_msg);
827             }
828         }
829 
830         /* restart timer */
831         btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RET, avdt_cb.rcb.ret_tout);
832     }
833 }
834 
835 /*******************************************************************************
836 **
837 ** Function         avdt_ccb_snd_cmd
838 **
839 ** Description      This function is called the send the next command,
840 **                  if any, in the command queue.
841 **
842 **
843 ** Returns          void.
844 **
845 *******************************************************************************/
avdt_ccb_snd_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)846 void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
847 {
848     BT_HDR  *p_msg;
849     UNUSED(p_data);
850 
851     /* do we have commands to send?  send next command;  make sure we're clear;
852     ** not congested, not sending fragment, not waiting for response
853     */
854     if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd == NULL))
855     {
856         if ((p_msg = (BT_HDR *) GKI_dequeue(&p_ccb->cmd_q)) != NULL)
857         {
858             /* make a copy of buffer in p_curr_cmd */
859             if ((p_ccb->p_curr_cmd = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) != NULL)
860             {
861                 memcpy(p_ccb->p_curr_cmd, p_msg, (sizeof(BT_HDR) + p_msg->offset + p_msg->len));
862 
863                 avdt_msg_send(p_ccb, p_msg);
864             }
865         }
866     }
867 }
868 
869 /*******************************************************************************
870 **
871 ** Function         avdt_ccb_snd_msg
872 **
873 ** Description
874 **
875 **
876 ** Returns          void.
877 **
878 *******************************************************************************/
avdt_ccb_snd_msg(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)879 void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
880 {
881     BT_HDR      *p_msg;
882     UNUSED(p_data);
883 
884     /* if not congested */
885     if (!p_ccb->cong)
886     {
887         /* are we sending a fragmented message? continue sending fragment */
888         if (p_ccb->p_curr_msg != NULL)
889         {
890             avdt_msg_send(p_ccb, NULL);
891         }
892         /* do we have responses to send?  send them */
893         else if (!GKI_queue_is_empty(&p_ccb->rsp_q))
894         {
895             while ((p_msg = (BT_HDR *) GKI_dequeue(&p_ccb->rsp_q)) != NULL)
896             {
897                 if (avdt_msg_send(p_ccb, p_msg) == TRUE)
898                 {
899                     /* break out if congested */
900                     break;
901                 }
902             }
903         }
904 
905         /* do we have commands to send?  send next command */
906         avdt_ccb_snd_cmd(p_ccb, NULL);
907     }
908 }
909 
910 /*******************************************************************************
911 **
912 ** Function         avdt_ccb_set_reconn
913 **
914 ** Description      This function is called to enable a reconnect attempt when
915 **                  a channel transitions from closing to idle state.  It sets
916 **                  the reconn variable to TRUE.
917 **
918 **
919 ** Returns          void.
920 **
921 *******************************************************************************/
avdt_ccb_set_reconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)922 void avdt_ccb_set_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
923 {
924     UNUSED(p_data);
925 
926     p_ccb->reconn = TRUE;
927 }
928 
929 /*******************************************************************************
930 **
931 ** Function         avdt_ccb_clr_reconn
932 **
933 ** Description      This function is called to clear the reconn variable.
934 **
935 **
936 ** Returns          void.
937 **
938 *******************************************************************************/
avdt_ccb_clr_reconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)939 void avdt_ccb_clr_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
940 {
941     UNUSED(p_data);
942 
943     p_ccb->reconn = FALSE;
944 }
945 
946 /*******************************************************************************
947 **
948 ** Function         avdt_ccb_chk_reconn
949 **
950 ** Description      This function is called to check if a reconnect attempt
951 **                  is enabled.  If enabled, it sends an AVDT_CCB_UL_OPEN_EVT
952 **                  to the CCB.  If disabled, the CCB is deallocated.
953 **
954 **
955 ** Returns          void.
956 **
957 *******************************************************************************/
avdt_ccb_chk_reconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)958 void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
959 {
960     UINT8   err_code = AVDT_ERR_CONNECT;
961     UNUSED(p_data);
962 
963     if (p_ccb->reconn)
964     {
965         p_ccb->reconn = FALSE;
966 
967         /* clear out ccb */
968         avdt_ccb_clear_ccb(p_ccb);
969 
970         /* clear out current command, if any */
971         avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
972 
973         /* reopen the signaling channel */
974         avdt_ccb_event(p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL);
975     }
976     else
977     {
978         avdt_ccb_ll_closed(p_ccb, NULL);
979     }
980 }
981 
982 /*******************************************************************************
983 **
984 ** Function         avdt_ccb_chk_timer
985 **
986 ** Description      This function stops the CCB timer if the idle timer is
987 **                  running.
988 **
989 **
990 ** Returns          void.
991 **
992 *******************************************************************************/
avdt_ccb_chk_timer(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)993 void avdt_ccb_chk_timer(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
994 {
995     UNUSED(p_data);
996 
997     if (p_ccb->timer_entry.event == BTU_TTYPE_AVDT_CCB_IDLE)
998     {
999         btu_stop_timer(&p_ccb->timer_entry);
1000     }
1001 }
1002 
1003 /*******************************************************************************
1004 **
1005 ** Function         avdt_ccb_set_conn
1006 **
1007 ** Description      Set CCB variables associated with AVDT_ConnectReq().
1008 **
1009 **
1010 ** Returns          void.
1011 **
1012 *******************************************************************************/
avdt_ccb_set_conn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1013 void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1014 {
1015     /* save callback */
1016     p_ccb->p_conn_cback = p_data->connect.p_cback;
1017 
1018     /* set security level */
1019     BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask,
1020                          AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
1021 }
1022 
1023 /*******************************************************************************
1024 **
1025 ** Function         avdt_ccb_set_disconn
1026 **
1027 ** Description      Set CCB variables associated with AVDT_DisconnectReq().
1028 **
1029 **
1030 ** Returns          void.
1031 **
1032 *******************************************************************************/
avdt_ccb_set_disconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1033 void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1034 {
1035     /*
1036     AVDT_TRACE_EVENT("avdt_ccb_set_disconn:conn:x%x, api:x%x",
1037         p_ccb->p_conn_cback, p_data->disconnect.p_cback);
1038         */
1039     /* save callback */
1040     if (p_data->disconnect.p_cback)
1041         p_ccb->p_conn_cback = p_data->disconnect.p_cback;
1042 }
1043 
1044 /*******************************************************************************
1045 **
1046 ** Function         avdt_ccb_do_disconn
1047 **
1048 ** Description      Do action associated with AVDT_DisconnectReq().
1049 **
1050 **
1051 ** Returns          void.
1052 **
1053 *******************************************************************************/
avdt_ccb_do_disconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1054 void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1055 {
1056     UNUSED(p_data);
1057 
1058     /* clear any pending commands */
1059     avdt_ccb_clear_cmds(p_ccb, NULL);
1060 
1061     /* close channel */
1062     avdt_ccb_chan_close(p_ccb, NULL);
1063 }
1064 
1065 /*******************************************************************************
1066 **
1067 ** Function         avdt_ccb_ll_closed
1068 **
1069 ** Description      Clear commands from and deallocate CCB.
1070 **
1071 **
1072 ** Returns          void.
1073 **
1074 *******************************************************************************/
avdt_ccb_ll_closed(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1075 void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1076 {
1077     tAVDT_CTRL_CBACK    *p_cback;
1078     BD_ADDR             bd_addr;
1079     tAVDT_CTRL          avdt_ctrl;
1080     UNUSED(p_data);
1081 
1082     /* clear any pending commands */
1083     avdt_ccb_clear_cmds(p_ccb, NULL);
1084 
1085     /* save callback pointer, bd addr */
1086     p_cback = p_ccb->p_conn_cback;
1087     if (!p_cback)
1088         p_cback = avdt_cb.p_conn_cback;
1089     memcpy(bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
1090 
1091     /* dealloc ccb */
1092     avdt_ccb_dealloc(p_ccb, NULL);
1093 
1094     /* call callback */
1095     if (p_cback)
1096     {
1097         avdt_ctrl.hdr.err_code = 0;
1098         (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
1099     }
1100 }
1101 
1102 /*******************************************************************************
1103 **
1104 ** Function         avdt_ccb_ll_opened
1105 **
1106 ** Description      Call callback on open.
1107 **
1108 **
1109 ** Returns          void.
1110 **
1111 *******************************************************************************/
avdt_ccb_ll_opened(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1112 void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1113 {
1114     tAVDT_CTRL          avdt_ctrl;
1115 
1116     p_ccb->ll_opened = TRUE;
1117 
1118     if (!p_ccb->p_conn_cback)
1119         p_ccb->p_conn_cback = avdt_cb.p_conn_cback;
1120 
1121     /* call callback */
1122     if (p_ccb->p_conn_cback)
1123     {
1124         avdt_ctrl.hdr.err_code = 0;
1125         avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param;
1126         (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl);
1127     }
1128 }
1129