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