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