avdt_ccb_act.cc revision a484a888196ddf8bcbf1ad3226d6451bc735a94b
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 38extern 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 ******************************************************************************/ 51static 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 ******************************************************************************/ 80void 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 ******************************************************************************/ 96void 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 ******************************************************************************/ 112void 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 ******************************************************************************/ 147void 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 ******************************************************************************/ 185void 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 ******************************************************************************/ 207void 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 ******************************************************************************/ 230void 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 ******************************************************************************/ 252void 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 ******************************************************************************/ 283void 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 ******************************************************************************/ 319void 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 ******************************************************************************/ 353void 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 ******************************************************************************/ 388void 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 ******************************************************************************/ 413void 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 ******************************************************************************/ 431void 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 ******************************************************************************/ 460void 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 ******************************************************************************/ 483void 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 ******************************************************************************/ 527void 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 ******************************************************************************/ 557void 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 ******************************************************************************/ 601void 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 ******************************************************************************/ 631void 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 ******************************************************************************/ 672void 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 ******************************************************************************/ 712void 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 ******************************************************************************/ 727void 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 ******************************************************************************/ 744void 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 ******************************************************************************/ 788void 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 ******************************************************************************/ 817void 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 ******************************************************************************/ 853void 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 ******************************************************************************/ 867void 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 ******************************************************************************/ 883void 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 ******************************************************************************/ 913void 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 ******************************************************************************/ 927void 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 ******************************************************************************/ 947void 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 ******************************************************************************/ 967void 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 ******************************************************************************/ 985void avdt_ccb_ll_closed(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) { 986 tAVDT_CTRL_CBACK* p_cback; 987 tAVDT_CTRL avdt_ctrl; 988 989 /* clear any pending commands */ 990 avdt_ccb_clear_cmds(p_ccb, NULL); 991 992 /* save callback pointer, bd addr */ 993 p_cback = p_ccb->p_conn_cback; 994 if (!p_cback) p_cback = avdt_cb.p_conn_cback; 995 RawAddress bd_addr = p_ccb->peer_addr; 996 997 /* dealloc ccb */ 998 avdt_ccb_dealloc(p_ccb, NULL); 999 1000 /* call callback */ 1001 if (p_cback) { 1002 avdt_ctrl.hdr.err_code = 0; 1003 (*p_cback)(0, &bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl); 1004 } 1005} 1006 1007/******************************************************************************* 1008 * 1009 * Function avdt_ccb_ll_opened 1010 * 1011 * Description Call callback on open. 1012 * 1013 * 1014 * Returns void. 1015 * 1016 ******************************************************************************/ 1017void avdt_ccb_ll_opened(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) { 1018 tAVDT_CTRL avdt_ctrl; 1019 1020 p_ccb->ll_opened = true; 1021 1022 if (!p_ccb->p_conn_cback) p_ccb->p_conn_cback = avdt_cb.p_conn_cback; 1023 1024 /* call callback */ 1025 if (p_ccb->p_conn_cback) { 1026 avdt_ctrl.hdr.err_code = 0; 1027 avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param; 1028 (*p_ccb->p_conn_cback)(0, &p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, 1029 &avdt_ctrl); 1030 } 1031} 1032