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