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