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