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