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