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