blob: b3cd30f702dbd3e2a314d017e4dbe7cdeae31a9c [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)
The Android Open Source Project5738f832012-12-12 16:00:35 -080066 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080067 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -080068 }
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -070069 fixed_queue_free(p_ccb->rsp_q, NULL);
70 p_ccb->rsp_q = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -080071}
72
73/*******************************************************************************
74**
75** Function avdt_ccb_chan_open
76**
77** Description This function calls avdt_ad_open_req() to
78** initiate a signaling channel connection.
79**
80**
81** Returns void.
82**
83*******************************************************************************/
84void avdt_ccb_chan_open(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
85{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080086 UNUSED(p_data);
87
The Android Open Source Project5738f832012-12-12 16:00:35 -080088 BTM_SetOutService(p_ccb->peer_addr, BTM_SEC_SERVICE_AVDTP, AVDT_CHAN_SIG);
89 avdt_ad_open_req(AVDT_CHAN_SIG, p_ccb, NULL, AVDT_INT);
90}
91
92/*******************************************************************************
93**
94** Function avdt_ccb_chan_close
95**
96** Description This function calls avdt_ad_close_req() to close a
97** signaling channel connection.
98**
99**
100** Returns void.
101**
102*******************************************************************************/
103void avdt_ccb_chan_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
104{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800105 UNUSED(p_data);
106
The Android Open Source Project5738f832012-12-12 16:00:35 -0800107 /* close the transport channel used by this CCB */
108 avdt_ad_close_req(AVDT_CHAN_SIG, p_ccb, NULL);
109}
110
111/*******************************************************************************
112**
113** Function avdt_ccb_chk_close
114**
115** Description This function checks for active streams on this CCB.
116** If there are none, it starts an idle timer.
117**
118**
119** Returns void.
120**
121*******************************************************************************/
122void avdt_ccb_chk_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
123{
124 int i;
125 tAVDT_SCB *p_scb = &avdt_cb.scb[0];
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800126 UNUSED(p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800127
128 /* see if there are any active scbs associated with this ccb */
129 for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
130 {
131 if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb))
132 {
133 break;
134 }
135 }
136
137 /* if no active scbs start idle timer */
138 if (i == AVDT_NUM_SEPS)
139 {
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800140 alarm_cancel(p_ccb->ret_ccb_timer);
141 alarm_cancel(p_ccb->rsp_ccb_timer);
142 period_ms_t interval_ms = avdt_cb.rcb.idle_tout * 1000;
143 alarm_set_on_queue(p_ccb->idle_ccb_timer, interval_ms,
144 avdt_ccb_idle_ccb_timer_timeout, p_ccb,
145 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800146 }
147}
148
149/*******************************************************************************
150**
151** Function avdt_ccb_hdl_discover_cmd
152**
153** Description This function is called when a discover command is
154** received from the peer. It gathers up the stream
155** information for all allocated streams and initiates
156** sending of a discover response.
157**
158**
159** Returns void.
160**
161*******************************************************************************/
162void avdt_ccb_hdl_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
163{
164 tAVDT_SEP_INFO sep_info[AVDT_NUM_SEPS];
165 tAVDT_SCB *p_scb = &avdt_cb.scb[0];
166 int i;
167
168 p_data->msg.discover_rsp.p_sep_info = sep_info;
169 p_data->msg.discover_rsp.num_seps = 0;
170
171 /* for all allocated scbs */
172 for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
173 {
174 if (p_scb->allocated)
175 {
176 /* copy sep info */
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800177 sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
178 sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
179 sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->cs.media_type;
180 sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800181
182 p_data->msg.discover_rsp.num_seps++;
183 }
184 }
185
186 /* send response */
187 avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_RSP_EVT, p_data);
188}
189
190/*******************************************************************************
191**
192** Function avdt_ccb_hdl_discover_rsp
193**
194** Description This function is called when a discover response or
195** reject is received from the peer. It calls the application
196** callback function with the results.
197**
198**
199** Returns void.
200**
201*******************************************************************************/
202void avdt_ccb_hdl_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
203{
204 /* we're done with procedure */
205 p_ccb->proc_busy = FALSE;
206
207 /* call app callback with results */
208 (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_DISCOVER_CFM_EVT,
209 (tAVDT_CTRL *)(&p_data->msg.discover_rsp));
210}
211
212/*******************************************************************************
213**
214** Function avdt_ccb_hdl_getcap_cmd
215**
216** Description This function is called when a get capabilities command
217** is received from the peer. It retrieves the stream
218** configuration for the requested stream and initiates
219** sending of a get capabilities response.
220**
221**
222** Returns void.
223**
224*******************************************************************************/
225void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
226{
227 tAVDT_SCB *p_scb;
228
229 /* look up scb for seid sent to us */
230 p_scb = avdt_scb_by_hdl(p_data->msg.single.seid);
231
232 p_data->msg.svccap.p_cfg = &p_scb->cs.cfg;
233
234 avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data);
235}
236
237/*******************************************************************************
238**
239** Function avdt_ccb_hdl_getcap_rsp
240**
241** Description This function is called with a get capabilities response
242** or reject is received from the peer. It calls the
243** application callback function with the results.
244**
245**
246** Returns void.
247**
248*******************************************************************************/
249void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
250{
251 /* we're done with procedure */
252 p_ccb->proc_busy = FALSE;
253
254 /* call app callback with results */
255 (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_GETCAP_CFM_EVT,
256 (tAVDT_CTRL *)(&p_data->msg.svccap));
257}
258
259/*******************************************************************************
260**
261** Function avdt_ccb_hdl_start_cmd
262**
263** Description This function is called when a start command is received
264** from the peer. It verifies that all requested streams
265** are in the proper state. If so, it initiates sending of
266** a start response. Otherwise it sends a start reject.
267**
268**
269** Returns void.
270**
271*******************************************************************************/
272void avdt_ccb_hdl_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
273{
Anubhav Gupta19165cb2015-05-06 16:24:10 +0530274 UINT8 err_code = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800275
276 /* verify all streams in the right state */
Anubhav Gupta19165cb2015-05-06 16:24:10 +0530277 UINT8 seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_START, p_data->msg.multi.seid_list,
278 p_data->msg.multi.num_seps, &err_code);
279 if (seid == 0 && err_code == 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800280 {
281 /* we're ok, send response */
282 avdt_ccb_event(p_ccb, AVDT_CCB_API_START_RSP_EVT, p_data);
Anubhav Gupta19165cb2015-05-06 16:24:10 +0530283 } else {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800284 /* not ok, send reject */
285 p_data->msg.hdr.err_code = err_code;
286 p_data->msg.hdr.err_param = seid;
287 avdt_msg_send_rej(p_ccb, AVDT_SIG_START, &p_data->msg);
288 }
289}
290
291/*******************************************************************************
292**
293** Function avdt_ccb_hdl_start_rsp
294**
295** Description This function is called when a start response or reject
296** is received from the peer. Using the SEIDs stored in the
297** current command message, it sends a start response or start
298** reject event to each SCB associated with the command.
299**
300**
301** Returns void.
302**
303*******************************************************************************/
304void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
305{
306 UINT8 event;
307 int i;
308 UINT8 *p;
309 tAVDT_SCB *p_scb;
310
311 /* determine rsp or rej event */
312 event = (p_data->msg.hdr.err_code == 0) ?
313 AVDT_SCB_MSG_START_RSP_EVT : AVDT_SCB_MSG_START_REJ_EVT;
314
315 /* get to where seid's are stashed in current cmd */
316 p = (UINT8 *)(p_ccb->p_curr_cmd + 1);
317
318 /* little trick here; length of current command equals number of streams */
319 for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
320 {
321 if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL)
322 {
323 avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
324 }
325 }
326}
327
328/*******************************************************************************
329**
330** Function avdt_ccb_hdl_suspend_cmd
331**
332** Description This function is called when a suspend command is received
333** from the peer. It verifies that all requested streams are
334** in the proper state. If so, it initiates sending of a
335** suspend response. Otherwise it sends a suspend reject.
336
337**
338**
339** Returns void.
340**
341*******************************************************************************/
342void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
343{
344 UINT8 seid;
Anubhav Gupta19165cb2015-05-06 16:24:10 +0530345 UINT8 err_code = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800346
347 /* verify all streams in the right state */
348 if ((seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_SUSPEND, p_data->msg.multi.seid_list,
Anubhav Gupta19165cb2015-05-06 16:24:10 +0530349 p_data->msg.multi.num_seps, &err_code)) == 0 &&
350 err_code == 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800351 {
352 /* we're ok, send response */
353 avdt_ccb_event(p_ccb, AVDT_CCB_API_SUSPEND_RSP_EVT, p_data);
354 }
355 else
356 {
357 /* not ok, send reject */
358 p_data->msg.hdr.err_code = err_code;
359 p_data->msg.hdr.err_param = seid;
360 avdt_msg_send_rej(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
361 }
362}
363
364/*******************************************************************************
365**
366** Function avdt_ccb_hdl_suspend_rsp
367**
368** Description This function is called when a suspend response or reject
369** is received from the peer. Using the SEIDs stored in the
370** current command message, it sends a suspend response or
371** suspend reject event to each SCB associated with the command.
372**
373**
374**
375** Returns void.
376**
377*******************************************************************************/
378void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
379{
380 UINT8 event;
381 int i;
382 UINT8 *p;
383 tAVDT_SCB *p_scb;
384
385 /* determine rsp or rej event */
386 event = (p_data->msg.hdr.err_code == 0) ?
387 AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT;
388
389 /* get to where seid's are stashed in current cmd */
390 p = (UINT8 *)(p_ccb->p_curr_cmd + 1);
391
392 /* little trick here; length of current command equals number of streams */
393 for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
394 {
395 if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL)
396 {
397 avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
398 }
399 }
400}
401
402/*******************************************************************************
403**
404** Function avdt_ccb_snd_discover_cmd
405**
406** Description This function is called to send a discover command to the
407** peer. It copies variables needed for the procedure from
408** the event to the CCB. It marks the CCB as busy and then
409** sends a discover command.
410**
411**
412** Returns void.
413**
414*******************************************************************************/
415void avdt_ccb_snd_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
416{
417 /* store info in ccb struct */
418 p_ccb->p_proc_data = p_data->discover.p_sep_info;
419 p_ccb->proc_cback = p_data->discover.p_cback;
420 p_ccb->proc_param = p_data->discover.num_seps;
421
422 /* we're busy */
423 p_ccb->proc_busy = TRUE;
424
425 /* build and queue discover req */
426 avdt_msg_send_cmd(p_ccb, NULL, AVDT_SIG_DISCOVER, NULL);
427}
428
429/*******************************************************************************
430**
431** Function avdt_ccb_snd_discover_rsp
432**
433** Description This function is called to send a discover response to
434** the peer. It takes the stream information passed in the
435** event and sends a discover response.
436**
437**
438** Returns void.
439**
440*******************************************************************************/
441void avdt_ccb_snd_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
442{
443 /* send response */
444 avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg);
445}
446
447/*******************************************************************************
448**
449** Function avdt_ccb_snd_getcap_cmd
450**
451** Description This function is called to send a get capabilities command
452** to the peer. It copies variables needed for the procedure
453** from the event to the CCB. It marks the CCB as busy and
454** then sends a get capabilities command.
455**
456**
457** Returns void.
458**
459*******************************************************************************/
460void avdt_ccb_snd_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
461{
462 UINT8 sig_id = AVDT_SIG_GETCAP;
463
464 /* store info in ccb struct */
465 p_ccb->p_proc_data = p_data->getcap.p_cfg;
466 p_ccb->proc_cback = p_data->getcap.p_cback;
467
468 /* we're busy */
469 p_ccb->proc_busy = TRUE;
470
471 /* build and queue discover req */
472 if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
473 sig_id = AVDT_SIG_GET_ALLCAP;
474
475 avdt_msg_send_cmd(p_ccb, NULL, sig_id, (tAVDT_MSG *) &p_data->getcap.single);
476}
477
478/*******************************************************************************
479**
480** Function avdt_ccb_snd_getcap_rsp
481**
482** Description This function is called to send a get capabilities response
483** to the peer. It takes the stream information passed in the
484** event and sends a get capabilities response.
485**
486**
487** Returns void.
488**
489*******************************************************************************/
490void avdt_ccb_snd_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
491{
492 UINT8 sig_id = AVDT_SIG_GETCAP;
493
494 if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
495 sig_id = AVDT_SIG_GET_ALLCAP;
496
497 /* send response */
498 avdt_msg_send_rsp(p_ccb, sig_id, &p_data->msg);
499}
500
501/*******************************************************************************
502**
503** Function avdt_ccb_snd_start_cmd
504**
505** Description This function is called to send a start command to the
506** peer. It verifies that all requested streams are in the
507** proper state. If so, it sends a start command. Otherwise
508** send ourselves back a start reject.
509**
510**
511** Returns void.
512**
513*******************************************************************************/
514void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
515{
516 int i;
517 tAVDT_SCB *p_scb;
518 tAVDT_MSG avdt_msg;
519 UINT8 seid_list[AVDT_NUM_SEPS];
520
521 /* make copy of our seid list */
522 memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
523
524 /* verify all streams in the right state */
525 if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_OPEN, p_data->msg.multi.seid_list,
526 p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0)
527 {
528 /* set peer seid list in messsage */
529 avdt_scb_peer_seid_list(&p_data->msg.multi);
530
531 /* send command */
532 avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_START, &p_data->msg);
533 }
534 else
535 {
536 /* failed; send ourselves a reject for each stream */
537 for (i = 0; i < p_data->msg.multi.num_seps; i++)
538 {
539 if ((p_scb = avdt_scb_by_hdl(seid_list[i])) != NULL)
540 {
541 avdt_scb_event(p_scb, AVDT_SCB_MSG_START_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
542 }
543 }
544 }
545}
546
547/*******************************************************************************
548**
549** Function avdt_ccb_snd_start_rsp
550**
551** Description This function is called to send a start response to the
552** peer. It takes the stream information passed in the event
553** and sends a start response. Then it sends a start event
554** to the SCB for each stream.
555**
556**
557** Returns void.
558**
559*******************************************************************************/
560void avdt_ccb_snd_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
561{
562 tAVDT_SCB *p_scb;
563 int i;
564
565 /* send response message */
566 avdt_msg_send_rsp(p_ccb, AVDT_SIG_START, &p_data->msg);
567
568 /* send start event to each scb */
569 for (i = 0; i < p_data->msg.multi.num_seps; i++)
570 {
571 if ((p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i])) != NULL)
572 {
573 avdt_scb_event(p_scb, AVDT_SCB_MSG_START_CMD_EVT, NULL);
574 }
575 }
576}
577
578/*******************************************************************************
579**
580** Function avdt_ccb_snd_suspend_cmd
581**
582** Description This function is called to send a suspend command to the
583** peer. It verifies that all requested streams are in the
584** proper state. If so, it sends a suspend command.
585** Otherwise it calls the callback function for each requested
586** stream and sends a suspend confirmation with failure.
587**
588**
589** Returns void.
590**
591*******************************************************************************/
592void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
593{
594 int i;
595 tAVDT_SCB *p_scb;
596 tAVDT_MSG avdt_msg;
597 UINT8 seid_list[AVDT_NUM_SEPS];
598
599 /* make copy of our seid list */
600 memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);
601
602 /* verify all streams in the right state */
603 if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_STREAMING, p_data->msg.multi.seid_list,
604 p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0)
605 {
606 /* set peer seid list in messsage */
607 avdt_scb_peer_seid_list(&p_data->msg.multi);
608
609 /* send command */
610 avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_SUSPEND, &p_data->msg);
611 }
612 else
613 {
614 /* failed; send ourselves a reject for each stream */
615 for (i = 0; i < p_data->msg.multi.num_seps; i++)
616 {
617 if ((p_scb = avdt_scb_by_hdl(seid_list[i])) != NULL)
618 {
619 avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
620 }
621 }
622 }
623}
624
625/*******************************************************************************
626**
627** Function avdt_ccb_snd_suspend_rsp
628**
629** Description This function is called to send a suspend response to the
630** peer. It takes the stream information passed in the event
631** and sends a suspend response. Then it sends a suspend event
632** to the SCB for each stream.
633**
634**
635** Returns void.
636**
637*******************************************************************************/
638void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
639{
640 tAVDT_SCB *p_scb;
641 int i;
642
643 /* send response message */
644 avdt_msg_send_rsp(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);
645
646 /* send start event to each scb */
647 for (i = 0; i < p_data->msg.multi.num_seps; i++)
648 {
649 if ((p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i])) != NULL)
650 {
651 avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_CMD_EVT, NULL);
652 }
653 }
654}
655
656/*******************************************************************************
657**
658** Function avdt_ccb_clear_cmds
659**
660** Description This function is called when the signaling channel is
661** closed to clean up any pending commands. For each pending
662** command in the command queue, it frees the command and
663** calls the application callback function indicating failure.
664** Certain CCB variables are also initialized.
665**
666**
667** Returns void.
668**
669*******************************************************************************/
670void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
671{
672 int i;
673 tAVDT_SCB *p_scb = &avdt_cb.scb[0];
674 UINT8 err_code = AVDT_ERR_CONNECT;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800675 UNUSED(p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800676
677 /* clear the ccb */
678 avdt_ccb_clear_ccb(p_ccb);
679
680 /* clear out command queue; this is a little tricky here; we need
681 ** to handle the case where there is a command on deck in p_curr_cmd,
682 ** plus we need to clear out the queue
683 */
684 do
685 {
686 /* we know p_curr_cmd = NULL after this */
687 avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
688
689 /* set up next message */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700690 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 -0800691
692 } while (p_ccb->p_curr_cmd != NULL);
693
694 /* send a CC_CLOSE_EVT any active scbs associated with this ccb */
695 for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
696 {
697 if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb))
698 {
699 avdt_scb_event(p_scb, AVDT_SCB_CC_CLOSE_EVT, NULL);
700 }
701 }
702}
703
704/*******************************************************************************
705**
706** Function avdt_ccb_cmd_fail
707**
708** Description This function is called when there is a response timeout.
709** The currently pending command is freed and we fake a
710** reject message back to ourselves.
711**
712**
713** Returns void.
714**
715*******************************************************************************/
716void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
717{
718 tAVDT_MSG msg;
719 UINT8 evt;
720 tAVDT_SCB *p_scb;
721
722 if (p_ccb->p_curr_cmd != NULL)
723 {
724 /* set up data */
725 msg.hdr.err_code = p_data->err_code;
726 msg.hdr.err_param = 0;
727 msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
728
729 /* pretend that we received a rej message */
730 evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1];
731
732 if (evt & AVDT_CCB_MKR)
733 {
734 avdt_ccb_event(p_ccb, (UINT8) (evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg);
735 }
736 else
737 {
738 /* we get the scb out of the current cmd */
739 p_scb = avdt_scb_by_hdl(*((UINT8 *)(p_ccb->p_curr_cmd + 1)));
740 if (p_scb != NULL)
741 {
742 avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg);
743 }
744 }
745
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800746 osi_free_and_reset((void **)&p_ccb->p_curr_cmd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800747 }
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);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800764 osi_free_and_reset((void **)&p_ccb->p_curr_cmd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800765}
766
767/*******************************************************************************
768**
769** Function avdt_ccb_cong_state
770**
771** Description This function is called to set the congestion state for
772** the CCB.
773**
774**
775** Returns void.
776**
777*******************************************************************************/
778void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
779{
780 p_ccb->cong = p_data->llcong;
781}
782
783/*******************************************************************************
784**
785** Function avdt_ccb_ret_cmd
786**
787** Description This function is called to retransmit the currently
788** pending command. The retransmission count is incremented.
789** If the count reaches the maximum number of retransmissions,
790** the event is treated as a response timeout.
791**
792**
793** Returns void.
794**
795*******************************************************************************/
796void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
797{
798 UINT8 err_code = AVDT_ERR_TIMEOUT;
799 BT_HDR *p_msg;
800
801 p_ccb->ret_count++;
802 if (p_ccb->ret_count == AVDT_RET_MAX)
803 {
804 /* command failed */
805 p_ccb->ret_count = 0;
806 avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
807
808 /* go to next queued command */
809 avdt_ccb_snd_cmd(p_ccb, p_data);
810 }
811 else
812 {
813 /* if command pending and we're not congested and not sending a fragment */
814 if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL))
815 {
816 /* make copy of message in p_curr_cmd and send it */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800817 p_msg = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
Pavlin Radoslavov2e3d0062015-09-18 10:51:31 -0700818 if (p_msg != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800819 {
820 memcpy(p_msg, p_ccb->p_curr_cmd,
821 (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len));
822 avdt_msg_send(p_ccb, p_msg);
823 }
824 }
825
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800826 /* restart ret timer */
827 alarm_cancel(p_ccb->idle_ccb_timer);
828 alarm_cancel(p_ccb->rsp_ccb_timer);
829 period_ms_t interval_ms = avdt_cb.rcb.ret_tout * 1000;
830 alarm_set_on_queue(p_ccb->ret_ccb_timer, interval_ms,
831 avdt_ccb_ret_ccb_timer_timeout, p_ccb,
832 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800833 }
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 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700857 if ((p_msg = (BT_HDR *) fixed_queue_try_dequeue(p_ccb->cmd_q)) != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800858 {
859 /* make a copy of buffer in p_curr_cmd */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800860 p_ccb->p_curr_cmd = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
Pavlin Radoslavov2e3d0062015-09-18 10:51:31 -0700861 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 */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700895 else if (!fixed_queue_is_empty(p_ccb->rsp_q))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800896 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700897 while ((p_msg = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800898 {
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
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800999 alarm_cancel(p_ccb->idle_ccb_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001000}
1001
1002/*******************************************************************************
1003**
1004** Function avdt_ccb_set_conn
1005**
1006** Description Set CCB variables associated with AVDT_ConnectReq().
1007**
1008**
1009** Returns void.
1010**
1011*******************************************************************************/
1012void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1013{
1014 /* save callback */
1015 p_ccb->p_conn_cback = p_data->connect.p_cback;
1016
1017 /* set security level */
1018 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask,
1019 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
1020}
1021
1022/*******************************************************************************
1023**
1024** Function avdt_ccb_set_disconn
1025**
1026** Description Set CCB variables associated with AVDT_DisconnectReq().
1027**
1028**
1029** Returns void.
1030**
1031*******************************************************************************/
1032void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1033{
1034 /*
Sharvil Nanavati158084e2014-05-04 09:53:44 -07001035 AVDT_TRACE_EVENT("avdt_ccb_set_disconn:conn:x%x, api:x%x",
The Android Open Source Project5738f832012-12-12 16:00:35 -08001036 p_ccb->p_conn_cback, p_data->disconnect.p_cback);
1037 */
1038 /* save callback */
1039 if (p_data->disconnect.p_cback)
1040 p_ccb->p_conn_cback = p_data->disconnect.p_cback;
1041}
1042
1043/*******************************************************************************
1044**
1045** Function avdt_ccb_do_disconn
1046**
1047** Description Do action associated with AVDT_DisconnectReq().
1048**
1049**
1050** Returns void.
1051**
1052*******************************************************************************/
1053void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1054{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001055 UNUSED(p_data);
1056
The Android Open Source Project5738f832012-12-12 16:00:35 -08001057 /* clear any pending commands */
1058 avdt_ccb_clear_cmds(p_ccb, NULL);
1059
1060 /* close channel */
1061 avdt_ccb_chan_close(p_ccb, NULL);
1062}
1063
1064/*******************************************************************************
1065**
1066** Function avdt_ccb_ll_closed
1067**
1068** Description Clear commands from and deallocate CCB.
1069**
1070**
1071** Returns void.
1072**
1073*******************************************************************************/
1074void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1075{
1076 tAVDT_CTRL_CBACK *p_cback;
1077 BD_ADDR bd_addr;
1078 tAVDT_CTRL avdt_ctrl;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001079 UNUSED(p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001080
1081 /* clear any pending commands */
1082 avdt_ccb_clear_cmds(p_ccb, NULL);
1083
1084 /* save callback pointer, bd addr */
1085 p_cback = p_ccb->p_conn_cback;
1086 if (!p_cback)
1087 p_cback = avdt_cb.p_conn_cback;
1088 memcpy(bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
1089
1090 /* dealloc ccb */
1091 avdt_ccb_dealloc(p_ccb, NULL);
1092
1093 /* call callback */
1094 if (p_cback)
1095 {
1096 avdt_ctrl.hdr.err_code = 0;
1097 (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
1098 }
1099}
1100
1101/*******************************************************************************
1102**
1103** Function avdt_ccb_ll_opened
1104**
1105** Description Call callback on open.
1106**
1107**
1108** Returns void.
1109**
1110*******************************************************************************/
1111void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1112{
1113 tAVDT_CTRL avdt_ctrl;
1114
1115 p_ccb->ll_opened = TRUE;
1116
1117 if (!p_ccb->p_conn_cback)
1118 p_ccb->p_conn_cback = avdt_cb.p_conn_cback;
1119
1120 /* call callback */
1121 if (p_ccb->p_conn_cback)
1122 {
1123 avdt_ctrl.hdr.err_code = 0;
1124 avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param;
1125 (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl);
1126 }
1127}