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