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