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