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