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