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