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