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