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 "data_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 seid;
274 UINT8 err_code;
275
276 /* verify all streams in the right state */
277 if ((seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_START, p_data->msg.multi.seid_list,
278 p_data->msg.multi.num_seps, &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 }
283 else
284 {
285 /* not ok, send reject */
286 p_data->msg.hdr.err_code = err_code;
287 p_data->msg.hdr.err_param = seid;
288 avdt_msg_send_rej(p_ccb, AVDT_SIG_START, &p_data->msg);
289 }
290 }
291
292 /*******************************************************************************
293 **
294 ** Function avdt_ccb_hdl_start_rsp
295 **
296 ** Description This function is called when a start response or reject
297 ** is received from the peer. Using the SEIDs stored in the
298 ** current command message, it sends a start response or start
299 ** reject event to each SCB associated with the command.
300 **
301 **
302 ** Returns void.
303 **
304 *******************************************************************************/
avdt_ccb_hdl_start_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)305 void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
306 {
307 UINT8 event;
308 int i;
309 UINT8 *p;
310 tAVDT_SCB *p_scb;
311
312 /* determine rsp or rej event */
313 event = (p_data->msg.hdr.err_code == 0) ?
314 AVDT_SCB_MSG_START_RSP_EVT : AVDT_SCB_MSG_START_REJ_EVT;
315
316 /* get to where seid's are stashed in current cmd */
317 p = (UINT8 *)(p_ccb->p_curr_cmd + 1);
318
319 /* little trick here; length of current command equals number of streams */
320 for (i = 0; i < p_ccb->p_curr_cmd->len; i++)
321 {
322 if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL)
323 {
324 avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
325 }
326 }
327 }
328
329 /*******************************************************************************
330 **
331 ** Function avdt_ccb_hdl_suspend_cmd
332 **
333 ** Description This function is called when a suspend command is received
334 ** from the peer. It verifies that all requested streams are
335 ** in the proper state. If so, it initiates sending of a
336 ** suspend response. Otherwise it sends a suspend reject.
337
338 **
339 **
340 ** Returns void.
341 **
342 *******************************************************************************/
avdt_ccb_hdl_suspend_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)343 void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
344 {
345 UINT8 seid;
346 UINT8 err_code;
347
348 /* verify all streams in the right state */
349 if ((seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_SUSPEND, p_data->msg.multi.seid_list,
350 p_data->msg.multi.num_seps, &err_code)) == 0)
351 {
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 *******************************************************************************/
avdt_ccb_hdl_suspend_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)378 void 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 *******************************************************************************/
avdt_ccb_snd_discover_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)415 void 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 *******************************************************************************/
avdt_ccb_snd_discover_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)441 void 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 *******************************************************************************/
avdt_ccb_snd_getcap_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)460 void 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 *******************************************************************************/
avdt_ccb_snd_getcap_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)490 void 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 *******************************************************************************/
avdt_ccb_snd_start_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)514 void 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 *******************************************************************************/
avdt_ccb_snd_start_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)560 void 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 *******************************************************************************/
avdt_ccb_snd_suspend_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)592 void 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 *******************************************************************************/
avdt_ccb_snd_suspend_rsp(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)638 void 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 *******************************************************************************/
avdt_ccb_clear_cmds(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)670 void 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;
675 UNUSED(p_data);
676
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 */
690 p_ccb->p_curr_cmd = (BT_HDR *) GKI_dequeue(&p_ccb->cmd_q);
691
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 *******************************************************************************/
avdt_ccb_cmd_fail(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)716 void 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
746 GKI_freebuf(p_ccb->p_curr_cmd);
747 p_ccb->p_curr_cmd = NULL;
748 }
749 }
750
751 /*******************************************************************************
752 **
753 ** Function avdt_ccb_free_cmd
754 **
755 ** Description This function is called when a response is received for a
756 ** currently pending command. The command is freed.
757 **
758 **
759 ** Returns void.
760 **
761 *******************************************************************************/
avdt_ccb_free_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)762 void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
763 {
764 UNUSED(p_data);
765
766 if (p_ccb->p_curr_cmd != NULL)
767 {
768 GKI_freebuf(p_ccb->p_curr_cmd);
769 p_ccb->p_curr_cmd = NULL;
770 }
771 }
772
773 /*******************************************************************************
774 **
775 ** Function avdt_ccb_cong_state
776 **
777 ** Description This function is called to set the congestion state for
778 ** the CCB.
779 **
780 **
781 ** Returns void.
782 **
783 *******************************************************************************/
avdt_ccb_cong_state(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)784 void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
785 {
786 p_ccb->cong = p_data->llcong;
787 }
788
789 /*******************************************************************************
790 **
791 ** Function avdt_ccb_ret_cmd
792 **
793 ** Description This function is called to retransmit the currently
794 ** pending command. The retransmission count is incremented.
795 ** If the count reaches the maximum number of retransmissions,
796 ** the event is treated as a response timeout.
797 **
798 **
799 ** Returns void.
800 **
801 *******************************************************************************/
avdt_ccb_ret_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)802 void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
803 {
804 UINT8 err_code = AVDT_ERR_TIMEOUT;
805 BT_HDR *p_msg;
806
807 p_ccb->ret_count++;
808 if (p_ccb->ret_count == AVDT_RET_MAX)
809 {
810 /* command failed */
811 p_ccb->ret_count = 0;
812 avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
813
814 /* go to next queued command */
815 avdt_ccb_snd_cmd(p_ccb, p_data);
816 }
817 else
818 {
819 /* if command pending and we're not congested and not sending a fragment */
820 if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL))
821 {
822 /* make copy of message in p_curr_cmd and send it */
823 if ((p_msg = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) != NULL)
824 {
825 memcpy(p_msg, p_ccb->p_curr_cmd,
826 (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len));
827 avdt_msg_send(p_ccb, p_msg);
828 }
829 }
830
831 /* restart timer */
832 btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RET, avdt_cb.rcb.ret_tout);
833 }
834 }
835
836 /*******************************************************************************
837 **
838 ** Function avdt_ccb_snd_cmd
839 **
840 ** Description This function is called the send the next command,
841 ** if any, in the command queue.
842 **
843 **
844 ** Returns void.
845 **
846 *******************************************************************************/
avdt_ccb_snd_cmd(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)847 void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
848 {
849 BT_HDR *p_msg;
850 UNUSED(p_data);
851
852 /* do we have commands to send? send next command; make sure we're clear;
853 ** not congested, not sending fragment, not waiting for response
854 */
855 if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd == NULL))
856 {
857 if ((p_msg = (BT_HDR *) GKI_dequeue(&p_ccb->cmd_q)) != NULL)
858 {
859 /* make a copy of buffer in p_curr_cmd */
860 if ((p_ccb->p_curr_cmd = (BT_HDR *) GKI_getpoolbuf(AVDT_CMD_POOL_ID)) != NULL)
861 {
862 memcpy(p_ccb->p_curr_cmd, p_msg, (sizeof(BT_HDR) + p_msg->offset + p_msg->len));
863
864 avdt_msg_send(p_ccb, p_msg);
865 }
866 }
867 }
868 }
869
870 /*******************************************************************************
871 **
872 ** Function avdt_ccb_snd_msg
873 **
874 ** Description
875 **
876 **
877 ** Returns void.
878 **
879 *******************************************************************************/
avdt_ccb_snd_msg(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)880 void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
881 {
882 BT_HDR *p_msg;
883 UNUSED(p_data);
884
885 /* if not congested */
886 if (!p_ccb->cong)
887 {
888 /* are we sending a fragmented message? continue sending fragment */
889 if (p_ccb->p_curr_msg != NULL)
890 {
891 avdt_msg_send(p_ccb, NULL);
892 }
893 /* do we have responses to send? send them */
894 else if (!GKI_queue_is_empty(&p_ccb->rsp_q))
895 {
896 while ((p_msg = (BT_HDR *) GKI_dequeue(&p_ccb->rsp_q)) != NULL)
897 {
898 if (avdt_msg_send(p_ccb, p_msg) == TRUE)
899 {
900 /* break out if congested */
901 break;
902 }
903 }
904 }
905
906 /* do we have commands to send? send next command */
907 avdt_ccb_snd_cmd(p_ccb, NULL);
908 }
909 }
910
911 /*******************************************************************************
912 **
913 ** Function avdt_ccb_set_reconn
914 **
915 ** Description This function is called to enable a reconnect attempt when
916 ** a channel transitions from closing to idle state. It sets
917 ** the reconn variable to TRUE.
918 **
919 **
920 ** Returns void.
921 **
922 *******************************************************************************/
avdt_ccb_set_reconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)923 void avdt_ccb_set_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
924 {
925 UNUSED(p_data);
926
927 p_ccb->reconn = TRUE;
928 }
929
930 /*******************************************************************************
931 **
932 ** Function avdt_ccb_clr_reconn
933 **
934 ** Description This function is called to clear the reconn variable.
935 **
936 **
937 ** Returns void.
938 **
939 *******************************************************************************/
avdt_ccb_clr_reconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)940 void avdt_ccb_clr_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
941 {
942 UNUSED(p_data);
943
944 p_ccb->reconn = FALSE;
945 }
946
947 /*******************************************************************************
948 **
949 ** Function avdt_ccb_chk_reconn
950 **
951 ** Description This function is called to check if a reconnect attempt
952 ** is enabled. If enabled, it sends an AVDT_CCB_UL_OPEN_EVT
953 ** to the CCB. If disabled, the CCB is deallocated.
954 **
955 **
956 ** Returns void.
957 **
958 *******************************************************************************/
avdt_ccb_chk_reconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)959 void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
960 {
961 UINT8 err_code = AVDT_ERR_CONNECT;
962 UNUSED(p_data);
963
964 if (p_ccb->reconn)
965 {
966 p_ccb->reconn = FALSE;
967
968 /* clear out ccb */
969 avdt_ccb_clear_ccb(p_ccb);
970
971 /* clear out current command, if any */
972 avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);
973
974 /* reopen the signaling channel */
975 avdt_ccb_event(p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL);
976 }
977 else
978 {
979 avdt_ccb_ll_closed(p_ccb, NULL);
980 }
981 }
982
983 /*******************************************************************************
984 **
985 ** Function avdt_ccb_chk_timer
986 **
987 ** Description This function stops the CCB timer if the idle timer is
988 ** running.
989 **
990 **
991 ** Returns void.
992 **
993 *******************************************************************************/
avdt_ccb_chk_timer(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)994 void avdt_ccb_chk_timer(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
995 {
996 UNUSED(p_data);
997
998 if (p_ccb->timer_entry.event == BTU_TTYPE_AVDT_CCB_IDLE)
999 {
1000 btu_stop_timer(&p_ccb->timer_entry);
1001 }
1002 }
1003
1004 /*******************************************************************************
1005 **
1006 ** Function avdt_ccb_set_conn
1007 **
1008 ** Description Set CCB variables associated with AVDT_ConnectReq().
1009 **
1010 **
1011 ** Returns void.
1012 **
1013 *******************************************************************************/
avdt_ccb_set_conn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1014 void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1015 {
1016 /* save callback */
1017 p_ccb->p_conn_cback = p_data->connect.p_cback;
1018
1019 /* set security level */
1020 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask,
1021 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
1022 }
1023
1024 /*******************************************************************************
1025 **
1026 ** Function avdt_ccb_set_disconn
1027 **
1028 ** Description Set CCB variables associated with AVDT_DisconnectReq().
1029 **
1030 **
1031 ** Returns void.
1032 **
1033 *******************************************************************************/
avdt_ccb_set_disconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1034 void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1035 {
1036 /*
1037 AVDT_TRACE_EVENT("avdt_ccb_set_disconn:conn:x%x, api:x%x",
1038 p_ccb->p_conn_cback, p_data->disconnect.p_cback);
1039 */
1040 /* save callback */
1041 if (p_data->disconnect.p_cback)
1042 p_ccb->p_conn_cback = p_data->disconnect.p_cback;
1043 }
1044
1045 /*******************************************************************************
1046 **
1047 ** Function avdt_ccb_do_disconn
1048 **
1049 ** Description Do action associated with AVDT_DisconnectReq().
1050 **
1051 **
1052 ** Returns void.
1053 **
1054 *******************************************************************************/
avdt_ccb_do_disconn(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1055 void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1056 {
1057 UNUSED(p_data);
1058
1059 /* clear any pending commands */
1060 avdt_ccb_clear_cmds(p_ccb, NULL);
1061
1062 /* close channel */
1063 avdt_ccb_chan_close(p_ccb, NULL);
1064 }
1065
1066 /*******************************************************************************
1067 **
1068 ** Function avdt_ccb_ll_closed
1069 **
1070 ** Description Clear commands from and deallocate CCB.
1071 **
1072 **
1073 ** Returns void.
1074 **
1075 *******************************************************************************/
avdt_ccb_ll_closed(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1076 void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1077 {
1078 tAVDT_CTRL_CBACK *p_cback;
1079 BD_ADDR bd_addr;
1080 tAVDT_CTRL avdt_ctrl;
1081 UNUSED(p_data);
1082
1083 /* clear any pending commands */
1084 avdt_ccb_clear_cmds(p_ccb, NULL);
1085
1086 /* save callback pointer, bd addr */
1087 p_cback = p_ccb->p_conn_cback;
1088 if (!p_cback)
1089 p_cback = avdt_cb.p_conn_cback;
1090 memcpy(bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
1091
1092 /* dealloc ccb */
1093 avdt_ccb_dealloc(p_ccb, NULL);
1094
1095 /* call callback */
1096 if (p_cback)
1097 {
1098 avdt_ctrl.hdr.err_code = 0;
1099 (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
1100 }
1101 }
1102
1103 /*******************************************************************************
1104 **
1105 ** Function avdt_ccb_ll_opened
1106 **
1107 ** Description Call callback on open.
1108 **
1109 **
1110 ** Returns void.
1111 **
1112 *******************************************************************************/
avdt_ccb_ll_opened(tAVDT_CCB * p_ccb,tAVDT_CCB_EVT * p_data)1113 void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
1114 {
1115 tAVDT_CTRL avdt_ctrl;
1116
1117 p_ccb->ll_opened = TRUE;
1118
1119 if (!p_ccb->p_conn_cback)
1120 p_ccb->p_conn_cback = avdt_cb.p_conn_cback;
1121
1122 /* call callback */
1123 if (p_ccb->p_conn_cback)
1124 {
1125 avdt_ctrl.hdr.err_code = 0;
1126 avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param;
1127 (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl);
1128 }
1129 }
1130