avdt_ccb_act.cc revision ee96a3c60fca590d38025925c072d264e06493c4
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 command. 368 * 369 * 370 * 371 * Returns void. 372 * 373 ******************************************************************************/ 374void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 375{ 376 uint8_t event; 377 int i; 378 uint8_t *p; 379 tAVDT_SCB *p_scb; 380 381 /* determine rsp or rej event */ 382 event = (p_data->msg.hdr.err_code == 0) ? 383 AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT; 384 385 /* get to where seid's are stashed in current cmd */ 386 p = (uint8_t *)(p_ccb->p_curr_cmd + 1); 387 388 /* little trick here; length of current command equals number of streams */ 389 for (i = 0; i < p_ccb->p_curr_cmd->len; i++) 390 { 391 p_scb = avdt_scb_by_hdl(p[i]); 392 if (p_scb != NULL) 393 { 394 avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg); 395 } 396 } 397} 398 399/******************************************************************************* 400 * 401 * Function avdt_ccb_snd_discover_cmd 402 * 403 * Description This function is called to send a discover command to the 404 * peer. It copies variables needed for the procedure from 405 * the event to the CCB. It marks the CCB as busy and then 406 * sends a discover command. 407 * 408 * 409 * Returns void. 410 * 411 ******************************************************************************/ 412void avdt_ccb_snd_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 413{ 414 /* store info in ccb struct */ 415 p_ccb->p_proc_data = p_data->discover.p_sep_info; 416 p_ccb->proc_cback = p_data->discover.p_cback; 417 p_ccb->proc_param = p_data->discover.num_seps; 418 419 /* we're busy */ 420 p_ccb->proc_busy = true; 421 422 /* build and queue discover req */ 423 avdt_msg_send_cmd(p_ccb, NULL, AVDT_SIG_DISCOVER, NULL); 424} 425 426/******************************************************************************* 427 * 428 * Function avdt_ccb_snd_discover_rsp 429 * 430 * Description This function is called to send a discover response to 431 * the peer. It takes the stream information passed in the 432 * event and sends a discover response. 433 * 434 * 435 * Returns void. 436 * 437 ******************************************************************************/ 438void avdt_ccb_snd_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 439{ 440 /* send response */ 441 avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg); 442} 443 444/******************************************************************************* 445 * 446 * Function avdt_ccb_snd_getcap_cmd 447 * 448 * Description This function is called to send a get capabilities command 449 * to the peer. It copies variables needed for the procedure 450 * from the event to the CCB. It marks the CCB as busy and 451 * then sends a get capabilities command. 452 * 453 * 454 * Returns void. 455 * 456 ******************************************************************************/ 457void avdt_ccb_snd_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 458{ 459 uint8_t sig_id = AVDT_SIG_GETCAP; 460 461 /* store info in ccb struct */ 462 p_ccb->p_proc_data = p_data->getcap.p_cfg; 463 p_ccb->proc_cback = p_data->getcap.p_cback; 464 465 /* we're busy */ 466 p_ccb->proc_busy = true; 467 468 /* build and queue discover req */ 469 if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP) 470 sig_id = AVDT_SIG_GET_ALLCAP; 471 472 avdt_msg_send_cmd(p_ccb, NULL, sig_id, (tAVDT_MSG *) &p_data->getcap.single); 473} 474 475/******************************************************************************* 476 * 477 * Function avdt_ccb_snd_getcap_rsp 478 * 479 * Description This function is called to send a get capabilities response 480 * to the peer. It takes the stream information passed in the 481 * event and sends a get capabilities response. 482 * 483 * 484 * Returns void. 485 * 486 ******************************************************************************/ 487void avdt_ccb_snd_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 488{ 489 uint8_t sig_id = AVDT_SIG_GETCAP; 490 491 if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP) 492 sig_id = AVDT_SIG_GET_ALLCAP; 493 494 /* send response */ 495 avdt_msg_send_rsp(p_ccb, sig_id, &p_data->msg); 496} 497 498/******************************************************************************* 499 * 500 * Function avdt_ccb_snd_start_cmd 501 * 502 * Description This function is called to send a start command to the 503 * peer. It verifies that all requested streams are in the 504 * proper state. If so, it sends a start command. Otherwise 505 * send ourselves back a start reject. 506 * 507 * 508 * Returns void. 509 * 510 ******************************************************************************/ 511void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 512{ 513 int i; 514 tAVDT_SCB *p_scb; 515 tAVDT_MSG avdt_msg; 516 uint8_t seid_list[AVDT_NUM_SEPS]; 517 518 /* make copy of our seid list */ 519 memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps); 520 521 /* verify all streams in the right state */ 522 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); 523 if (avdt_msg.hdr.err_param == 0) 524 { 525 /* set peer seid list in messsage */ 526 avdt_scb_peer_seid_list(&p_data->msg.multi); 527 528 /* send command */ 529 avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_START, &p_data->msg); 530 } 531 else 532 { 533 /* failed; send ourselves a reject for each stream */ 534 for (i = 0; i < p_data->msg.multi.num_seps; i++) 535 { 536 p_scb = avdt_scb_by_hdl(seid_list[i]); 537 if (p_scb != NULL) 538 { 539 avdt_scb_event(p_scb, AVDT_SCB_MSG_START_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr); 540 } 541 } 542 } 543} 544 545/******************************************************************************* 546 * 547 * Function avdt_ccb_snd_start_rsp 548 * 549 * Description This function is called to send a start response to the 550 * peer. It takes the stream information passed in the event 551 * and sends a start response. Then it sends a start event 552 * to the SCB for each stream. 553 * 554 * 555 * Returns void. 556 * 557 ******************************************************************************/ 558void avdt_ccb_snd_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 559{ 560 tAVDT_SCB *p_scb; 561 int i; 562 563 /* send response message */ 564 avdt_msg_send_rsp(p_ccb, AVDT_SIG_START, &p_data->msg); 565 566 /* send start event to each scb */ 567 for (i = 0; i < p_data->msg.multi.num_seps; i++) 568 { 569 p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i]); 570 if (p_scb != NULL) 571 { 572 avdt_scb_event(p_scb, AVDT_SCB_MSG_START_CMD_EVT, NULL); 573 } 574 } 575} 576 577/******************************************************************************* 578 * 579 * Function avdt_ccb_snd_suspend_cmd 580 * 581 * Description This function is called to send a suspend command to the 582 * peer. It verifies that all requested streams are in the 583 * proper state. If so, it sends a suspend command. 584 * Otherwise it calls the callback function for each requested 585 * stream and sends a suspend confirmation with failure. 586 * 587 * 588 * Returns void. 589 * 590 ******************************************************************************/ 591void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 592{ 593 int i; 594 tAVDT_SCB *p_scb; 595 tAVDT_MSG avdt_msg; 596 uint8_t seid_list[AVDT_NUM_SEPS]; 597 598 /* make copy of our seid list */ 599 memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps); 600 601 /* verify all streams in the right state */ 602 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); 603 if (avdt_msg.hdr.err_param == 0) 604 { 605 /* set peer seid list in messsage */ 606 avdt_scb_peer_seid_list(&p_data->msg.multi); 607 608 /* send command */ 609 avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_SUSPEND, &p_data->msg); 610 } 611 else 612 { 613 /* failed; send ourselves a reject for each stream */ 614 for (i = 0; i < p_data->msg.multi.num_seps; i++) 615 { 616 p_scb = avdt_scb_by_hdl(seid_list[i]); 617 if (p_scb != NULL) 618 { 619 avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr); 620 } 621 } 622 } 623} 624 625/******************************************************************************* 626 * 627 * Function avdt_ccb_snd_suspend_rsp 628 * 629 * Description This function is called to send a suspend response to the 630 * peer. It takes the stream information passed in the event 631 * and sends a suspend response. Then it sends a suspend event 632 * to the SCB for each stream. 633 * 634 * 635 * Returns void. 636 * 637 ******************************************************************************/ 638void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 639{ 640 tAVDT_SCB *p_scb; 641 int i; 642 643 /* send response message */ 644 avdt_msg_send_rsp(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg); 645 646 /* send start event to each scb */ 647 for (i = 0; i < p_data->msg.multi.num_seps; i++) 648 { 649 p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i]); 650 if (p_scb != NULL) 651 { 652 avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_CMD_EVT, NULL); 653 } 654 } 655} 656 657/******************************************************************************* 658 * 659 * Function avdt_ccb_clear_cmds 660 * 661 * Description This function is called when the signaling channel is 662 * closed to clean up any pending commands. For each pending 663 * command in the command queue, it frees the command and 664 * calls the application callback function indicating failure. 665 * Certain CCB variables are also initialized. 666 * 667 * 668 * Returns void. 669 * 670 ******************************************************************************/ 671void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb, 672 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 673{ 674 int i; 675 tAVDT_SCB *p_scb = &avdt_cb.scb[0]; 676 uint8_t err_code = AVDT_ERR_CONNECT; 677 678 /* clear the ccb */ 679 avdt_ccb_clear_ccb(p_ccb); 680 681 /* clear out command queue; this is a little tricky here; we need 682 ** to handle the case where there is a command on deck in p_curr_cmd, 683 ** plus we need to clear out the queue 684 */ 685 do 686 { 687 /* we know p_curr_cmd = NULL after this */ 688 avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code); 689 690 /* set up next message */ 691 p_ccb->p_curr_cmd = (BT_HDR *) fixed_queue_try_dequeue(p_ccb->cmd_q); 692 693 } while (p_ccb->p_curr_cmd != NULL); 694 695 /* send a CC_CLOSE_EVT any active scbs associated with this ccb */ 696 for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) 697 { 698 if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb)) 699 { 700 avdt_scb_event(p_scb, AVDT_SCB_CC_CLOSE_EVT, NULL); 701 } 702 } 703} 704 705/******************************************************************************* 706 * 707 * Function avdt_ccb_cmd_fail 708 * 709 * Description This function is called when there is a response timeout. 710 * The currently pending command is freed and we fake a 711 * reject message back to ourselves. 712 * 713 * 714 * Returns void. 715 * 716 ******************************************************************************/ 717void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 718{ 719 tAVDT_MSG msg; 720 uint8_t evt; 721 tAVDT_SCB *p_scb; 722 723 if (p_ccb->p_curr_cmd != NULL) 724 { 725 /* set up data */ 726 msg.hdr.err_code = p_data->err_code; 727 msg.hdr.err_param = 0; 728 msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb); 729 730 /* pretend that we received a rej message */ 731 evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1]; 732 733 if (evt & AVDT_CCB_MKR) 734 { 735 avdt_ccb_event(p_ccb, (uint8_t) (evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg); 736 } 737 else 738 { 739 /* we get the scb out of the current cmd */ 740 p_scb = avdt_scb_by_hdl(*((uint8_t *)(p_ccb->p_curr_cmd + 1))); 741 if (p_scb != NULL) 742 { 743 avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg); 744 } 745 } 746 747 osi_free_and_reset((void **)&p_ccb->p_curr_cmd); 748 } 749} 750 751/******************************************************************************* 752 * 753 * Function avdt_ccb_free_cmd 754 * 755 * Description This function is called when a response is received for a 756 * currently pending command. The command is freed. 757 * 758 * 759 * Returns void. 760 * 761 ******************************************************************************/ 762void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb, 763 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 764{ 765 osi_free_and_reset((void **)&p_ccb->p_curr_cmd); 766} 767 768/******************************************************************************* 769 * 770 * Function avdt_ccb_cong_state 771 * 772 * Description This function is called to set the congestion state for 773 * the CCB. 774 * 775 * 776 * Returns void. 777 * 778 ******************************************************************************/ 779void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 780{ 781 p_ccb->cong = p_data->llcong; 782} 783 784/******************************************************************************* 785 * 786 * Function avdt_ccb_ret_cmd 787 * 788 * Description This function is called to retransmit the currently 789 * pending command. The retransmission count is incremented. 790 * If the count reaches the maximum number of retransmissions, 791 * the event is treated as a response timeout. 792 * 793 * 794 * Returns void. 795 * 796 ******************************************************************************/ 797void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 798{ 799 uint8_t err_code = AVDT_ERR_TIMEOUT; 800 801 p_ccb->ret_count++; 802 if (p_ccb->ret_count == AVDT_RET_MAX) 803 { 804 /* command failed */ 805 p_ccb->ret_count = 0; 806 avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code); 807 808 /* go to next queued command */ 809 avdt_ccb_snd_cmd(p_ccb, p_data); 810 } 811 else 812 { 813 /* if command pending and we're not congested and not sending a fragment */ 814 if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd != NULL)) 815 { 816 /* make copy of message in p_curr_cmd and send it */ 817 BT_HDR *p_msg = (BT_HDR *)osi_malloc(AVDT_CMD_BUF_SIZE); 818 memcpy(p_msg, p_ccb->p_curr_cmd, 819 (sizeof(BT_HDR) + p_ccb->p_curr_cmd->offset + p_ccb->p_curr_cmd->len)); 820 avdt_msg_send(p_ccb, p_msg); 821 } 822 823 /* restart ret timer */ 824 alarm_cancel(p_ccb->idle_ccb_timer); 825 alarm_cancel(p_ccb->rsp_ccb_timer); 826 period_ms_t interval_ms = avdt_cb.rcb.ret_tout * 1000; 827 alarm_set_on_queue(p_ccb->ret_ccb_timer, interval_ms, 828 avdt_ccb_ret_ccb_timer_timeout, p_ccb, 829 btu_general_alarm_queue); 830 } 831} 832 833/******************************************************************************* 834 * 835 * Function avdt_ccb_snd_cmd 836 * 837 * Description This function is called the send the next command, 838 * if any, in the command queue. 839 * 840 * 841 * Returns void. 842 * 843 ******************************************************************************/ 844void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb, 845 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 846{ 847 BT_HDR *p_msg; 848 849 /* do we have commands to send? send next command; make sure we're clear; 850 ** not congested, not sending fragment, not waiting for response 851 */ 852 if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd == NULL)) 853 { 854 p_msg = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->cmd_q); 855 if (p_msg != NULL) 856 { 857 /* make a copy of buffer in p_curr_cmd */ 858 p_ccb->p_curr_cmd = (BT_HDR *)osi_malloc(AVDT_CMD_BUF_SIZE); 859 memcpy(p_ccb->p_curr_cmd, p_msg, 860 (sizeof(BT_HDR) + p_msg->offset + p_msg->len)); 861 avdt_msg_send(p_ccb, p_msg); 862 } 863 } 864} 865 866/******************************************************************************* 867 * 868 * Function avdt_ccb_snd_msg 869 * 870 * Description 871 * 872 * 873 * Returns void. 874 * 875 ******************************************************************************/ 876void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, 877 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 878{ 879 BT_HDR *p_msg; 880 881 /* if not congested */ 882 if (!p_ccb->cong) 883 { 884 /* are we sending a fragmented message? continue sending fragment */ 885 if (p_ccb->p_curr_msg != NULL) 886 { 887 avdt_msg_send(p_ccb, NULL); 888 } 889 /* do we have responses to send? send them */ 890 else if (!fixed_queue_is_empty(p_ccb->rsp_q)) 891 { 892 while ((p_msg = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL) 893 { 894 if (avdt_msg_send(p_ccb, p_msg) == true) 895 { 896 /* break out if congested */ 897 break; 898 } 899 } 900 } 901 902 /* do we have commands to send? send next command */ 903 avdt_ccb_snd_cmd(p_ccb, NULL); 904 } 905} 906 907/******************************************************************************* 908 * 909 * Function avdt_ccb_set_reconn 910 * 911 * Description This function is called to enable a reconnect attempt when 912 * a channel transitions from closing to idle state. It sets 913 * the reconn variable to true. 914 * 915 * 916 * Returns void. 917 * 918 ******************************************************************************/ 919void avdt_ccb_set_reconn(tAVDT_CCB *p_ccb, 920 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 921{ 922 p_ccb->reconn = true; 923} 924 925/******************************************************************************* 926 * 927 * Function avdt_ccb_clr_reconn 928 * 929 * Description This function is called to clear the reconn variable. 930 * 931 * 932 * Returns void. 933 * 934 ******************************************************************************/ 935void avdt_ccb_clr_reconn(tAVDT_CCB *p_ccb, 936 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 937{ 938 p_ccb->reconn = false; 939} 940 941/******************************************************************************* 942 * 943 * Function avdt_ccb_chk_reconn 944 * 945 * Description This function is called to check if a reconnect attempt 946 * is enabled. If enabled, it sends an AVDT_CCB_UL_OPEN_EVT 947 * to the CCB. If disabled, the CCB is deallocated. 948 * 949 * 950 * Returns void. 951 * 952 ******************************************************************************/ 953void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb, 954 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 955{ 956 uint8_t err_code = AVDT_ERR_CONNECT; 957 958 if (p_ccb->reconn) 959 { 960 p_ccb->reconn = false; 961 962 /* clear out ccb */ 963 avdt_ccb_clear_ccb(p_ccb); 964 965 /* clear out current command, if any */ 966 avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code); 967 968 /* reopen the signaling channel */ 969 avdt_ccb_event(p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL); 970 } 971 else 972 { 973 avdt_ccb_ll_closed(p_ccb, NULL); 974 } 975} 976 977/******************************************************************************* 978 * 979 * Function avdt_ccb_chk_timer 980 * 981 * Description This function stops the CCB timer if the idle timer is 982 * running. 983 * 984 * 985 * Returns void. 986 * 987 ******************************************************************************/ 988void avdt_ccb_chk_timer(tAVDT_CCB *p_ccb, 989 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 990{ 991 alarm_cancel(p_ccb->idle_ccb_timer); 992} 993 994/******************************************************************************* 995 * 996 * Function avdt_ccb_set_conn 997 * 998 * Description Set CCB variables associated with AVDT_ConnectReq(). 999 * 1000 * 1001 * Returns void. 1002 * 1003 ******************************************************************************/ 1004void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 1005{ 1006 /* save callback */ 1007 p_ccb->p_conn_cback = p_data->connect.p_cback; 1008 1009 /* set security level */ 1010 BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask, 1011 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG); 1012} 1013 1014/******************************************************************************* 1015 * 1016 * Function avdt_ccb_set_disconn 1017 * 1018 * Description Set CCB variables associated with AVDT_DisconnectReq(). 1019 * 1020 * 1021 * Returns void. 1022 * 1023 ******************************************************************************/ 1024void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 1025{ 1026 /* 1027 AVDT_TRACE_EVENT("avdt_ccb_set_disconn:conn:x%x, api:x%x", 1028 p_ccb->p_conn_cback, p_data->disconnect.p_cback); 1029 */ 1030 /* save callback */ 1031 if (p_data->disconnect.p_cback) 1032 p_ccb->p_conn_cback = p_data->disconnect.p_cback; 1033} 1034 1035/******************************************************************************* 1036 * 1037 * Function avdt_ccb_do_disconn 1038 * 1039 * Description Do action associated with AVDT_DisconnectReq(). 1040 * 1041 * 1042 * Returns void. 1043 * 1044 ******************************************************************************/ 1045void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb, 1046 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 1047{ 1048 /* clear any pending commands */ 1049 avdt_ccb_clear_cmds(p_ccb, NULL); 1050 1051 /* close channel */ 1052 avdt_ccb_chan_close(p_ccb, NULL); 1053} 1054 1055/******************************************************************************* 1056 * 1057 * Function avdt_ccb_ll_closed 1058 * 1059 * Description Clear commands from and deallocate CCB. 1060 * 1061 * 1062 * Returns void. 1063 * 1064 ******************************************************************************/ 1065void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, 1066 UNUSED_ATTR tAVDT_CCB_EVT *p_data) 1067{ 1068 tAVDT_CTRL_CBACK *p_cback; 1069 BD_ADDR bd_addr; 1070 tAVDT_CTRL avdt_ctrl; 1071 1072 /* clear any pending commands */ 1073 avdt_ccb_clear_cmds(p_ccb, NULL); 1074 1075 /* save callback pointer, bd addr */ 1076 p_cback = p_ccb->p_conn_cback; 1077 if (!p_cback) 1078 p_cback = avdt_cb.p_conn_cback; 1079 memcpy(bd_addr, p_ccb->peer_addr, BD_ADDR_LEN); 1080 1081 /* dealloc ccb */ 1082 avdt_ccb_dealloc(p_ccb, NULL); 1083 1084 /* call callback */ 1085 if (p_cback) 1086 { 1087 avdt_ctrl.hdr.err_code = 0; 1088 (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl); 1089 } 1090} 1091 1092/******************************************************************************* 1093 * 1094 * Function avdt_ccb_ll_opened 1095 * 1096 * Description Call callback on open. 1097 * 1098 * 1099 * Returns void. 1100 * 1101 ******************************************************************************/ 1102void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) 1103{ 1104 tAVDT_CTRL avdt_ctrl; 1105 1106 p_ccb->ll_opened = true; 1107 1108 if (!p_ccb->p_conn_cback) 1109 p_ccb->p_conn_cback = avdt_cb.p_conn_cback; 1110 1111 /* call callback */ 1112 if (p_ccb->p_conn_cback) 1113 { 1114 avdt_ctrl.hdr.err_code = 0; 1115 avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param; 1116 (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl); 1117 } 1118} 1119