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