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