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