1 /****************************************************************************** 2 * 3 * Copyright (C) 2002-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 API of the audio/video distribution transport 22 * protocol. 23 * 24 ******************************************************************************/ 25 26 #include "avdt_api.h" 27 #include <string.h> 28 #include "avdt_int.h" 29 #include "avdtc_api.h" 30 #include "bt_target.h" 31 #include "bt_types.h" 32 #include "btm_api.h" 33 #include "btu.h" 34 #include "l2c_api.h" 35 #include "stack/include/a2dp_codec_api.h" 36 37 /* Control block for AVDT */ 38 tAVDT_CB avdt_cb; 39 40 void avdt_ccb_idle_ccb_timer_timeout(void* data) { 41 tAVDT_CCB* p_ccb = (tAVDT_CCB*)data; 42 uint8_t avdt_event = AVDT_CCB_IDLE_TOUT_EVT; 43 uint8_t err_code = AVDT_ERR_TIMEOUT; 44 45 tAVDT_CCB_EVT avdt_ccb_evt; 46 avdt_ccb_evt.err_code = err_code; 47 avdt_ccb_event(p_ccb, avdt_event, &avdt_ccb_evt); 48 } 49 50 void avdt_ccb_ret_ccb_timer_timeout(void* data) { 51 tAVDT_CCB* p_ccb = (tAVDT_CCB*)data; 52 uint8_t avdt_event = AVDT_CCB_RET_TOUT_EVT; 53 uint8_t err_code = AVDT_ERR_TIMEOUT; 54 55 tAVDT_CCB_EVT avdt_ccb_evt; 56 avdt_ccb_evt.err_code = err_code; 57 avdt_ccb_event(p_ccb, avdt_event, &avdt_ccb_evt); 58 } 59 60 void avdt_ccb_rsp_ccb_timer_timeout(void* data) { 61 tAVDT_CCB* p_ccb = (tAVDT_CCB*)data; 62 uint8_t avdt_event = AVDT_CCB_RSP_TOUT_EVT; 63 uint8_t err_code = AVDT_ERR_TIMEOUT; 64 65 tAVDT_CCB_EVT avdt_ccb_evt; 66 avdt_ccb_evt.err_code = err_code; 67 avdt_ccb_event(p_ccb, avdt_event, &avdt_ccb_evt); 68 } 69 70 void avdt_scb_transport_channel_timer_timeout(void* data) { 71 tAVDT_SCB* p_scb = (tAVDT_SCB*)data; 72 uint8_t avdt_event = AVDT_SCB_TC_TOUT_EVT; 73 74 avdt_scb_event(p_scb, avdt_event, NULL); 75 } 76 77 /******************************************************************************* 78 * 79 * Function AVDT_Register 80 * 81 * Description This is the system level registration function for the 82 * AVDTP protocol. This function initializes AVDTP and 83 * prepares the protocol stack for its use. This function 84 * must be called once by the system or platform using AVDTP 85 * before the other functions of the API an be used. 86 * 87 * 88 * Returns void 89 * 90 ******************************************************************************/ 91 void AVDT_Register(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback) { 92 /* register PSM with L2CAP */ 93 L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl); 94 95 /* set security level */ 96 BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask, 97 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG); 98 BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask, 99 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG); 100 101 /* do not use security on the media channel */ 102 BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, 103 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA); 104 BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, 105 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA); 106 107 #if (AVDT_REPORTING == TRUE) 108 /* do not use security on the reporting channel */ 109 BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, 110 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT); 111 BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, 112 AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT); 113 #endif 114 115 /* initialize AVDTP data structures */ 116 avdt_scb_init(); 117 avdt_ccb_init(); 118 avdt_ad_init(); 119 120 /* copy registration struct */ 121 memcpy(&avdt_cb.rcb, p_reg, sizeof(tAVDT_REG)); 122 avdt_cb.p_conn_cback = p_cback; 123 } 124 125 /******************************************************************************* 126 * 127 * Function AVDT_Deregister 128 * 129 * Description This function is called to deregister use AVDTP protocol. 130 * It is called when AVDTP is no longer being used by any 131 * application in the system. Before this function can be 132 * called, all streams must be removed with 133 * AVDT_RemoveStream(). 134 * 135 * 136 * Returns void 137 * 138 ******************************************************************************/ 139 void AVDT_Deregister(void) { 140 /* deregister PSM with L2CAP */ 141 L2CA_Deregister(AVDT_PSM); 142 } 143 144 void AVDT_AbortReq(uint8_t handle) { 145 AVDT_TRACE_WARNING("%s: handle=%d", __func__, handle); 146 147 tAVDT_SCB* p_scb = avdt_scb_by_hdl(handle); 148 if (p_scb != NULL) { 149 avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_REQ_EVT, NULL); 150 } else { 151 AVDT_TRACE_ERROR("%s Improper SCB, can not abort the stream", __func__); 152 } 153 } 154 155 /******************************************************************************* 156 * 157 * Function AVDT_CreateStream 158 * 159 * Description Create a stream endpoint. After a stream endpoint is 160 * created an application can initiate a connection between 161 * this endpoint and an endpoint on a peer device. In 162 * addition, a peer device can discover, get the capabilities, 163 * and connect to this endpoint. 164 * 165 * 166 * Returns AVDT_SUCCESS if successful, otherwise error. 167 * 168 ******************************************************************************/ 169 uint16_t AVDT_CreateStream(uint8_t* p_handle, tAVDT_CS* p_cs) { 170 uint16_t result = AVDT_SUCCESS; 171 tAVDT_SCB* p_scb; 172 173 AVDT_TRACE_DEBUG("%s", __func__); 174 175 /* Verify parameters; if invalid, return failure */ 176 if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || 177 (p_cs->p_ctrl_cback == NULL)) { 178 result = AVDT_BAD_PARAMS; 179 } 180 /* Allocate scb; if no scbs, return failure */ 181 else { 182 p_scb = avdt_scb_alloc(p_cs); 183 if (p_scb == NULL) { 184 result = AVDT_NO_RESOURCES; 185 } else { 186 *p_handle = avdt_scb_to_hdl(p_scb); 187 } 188 } 189 190 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 191 192 return result; 193 } 194 195 /******************************************************************************* 196 * 197 * Function AVDT_RemoveStream 198 * 199 * Description Remove a stream endpoint. This function is called when 200 * the application is no longer using a stream endpoint. 201 * If this function is called when the endpoint is connected 202 * the connection is closed and then the stream endpoint 203 * is removed. 204 * 205 * 206 * Returns AVDT_SUCCESS if successful, otherwise error. 207 * 208 ******************************************************************************/ 209 uint16_t AVDT_RemoveStream(uint8_t handle) { 210 uint16_t result = AVDT_SUCCESS; 211 tAVDT_SCB* p_scb; 212 213 AVDT_TRACE_DEBUG("%s: handle=%d", __func__, handle); 214 215 /* look up scb */ 216 p_scb = avdt_scb_by_hdl(handle); 217 if (p_scb == NULL) { 218 result = AVDT_BAD_HANDLE; 219 } else { 220 /* send remove event to scb */ 221 avdt_scb_event(p_scb, AVDT_SCB_API_REMOVE_EVT, NULL); 222 } 223 224 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 225 226 return result; 227 } 228 229 /******************************************************************************* 230 * 231 * Function AVDT_DiscoverReq 232 * 233 * Description This function initiates a connection to the AVDTP service 234 * on the peer device, if not already present, and discovers 235 * the stream endpoints on the peer device. (Please note 236 * that AVDTP discovery is unrelated to SDP discovery). 237 * This function can be called at any time regardless of 238 * whether there is an AVDTP connection to the peer device. 239 * 240 * When discovery is complete, an AVDT_DISCOVER_CFM_EVT 241 * is sent to the application via its callback function. 242 * The application must not call AVDT_GetCapReq() or 243 * AVDT_DiscoverReq() again to the same device until 244 * discovery is complete. 245 * 246 * The memory addressed by sep_info is allocated by the 247 * application. This memory is written to by AVDTP as part 248 * of the discovery procedure. This memory must remain 249 * accessible until the application receives the 250 * AVDT_DISCOVER_CFM_EVT. 251 * 252 * Returns AVDT_SUCCESS if successful, otherwise error. 253 * 254 ******************************************************************************/ 255 uint16_t AVDT_DiscoverReq(const RawAddress& bd_addr, tAVDT_SEP_INFO* p_sep_info, 256 uint8_t max_seps, tAVDT_CTRL_CBACK* p_cback) { 257 tAVDT_CCB* p_ccb; 258 uint16_t result = AVDT_SUCCESS; 259 tAVDT_CCB_EVT evt; 260 261 AVDT_TRACE_DEBUG("%s", __func__); 262 263 /* find channel control block for this bd addr; if none, allocate one */ 264 p_ccb = avdt_ccb_by_bd(bd_addr); 265 if (p_ccb == NULL) { 266 p_ccb = avdt_ccb_alloc(bd_addr); 267 if (p_ccb == NULL) { 268 /* could not allocate channel control block */ 269 result = AVDT_NO_RESOURCES; 270 } 271 } 272 273 if (result == AVDT_SUCCESS) { 274 /* make sure no discovery or get capabilities req already in progress */ 275 if (p_ccb->proc_busy) { 276 result = AVDT_BUSY; 277 } 278 /* send event to ccb */ 279 else { 280 evt.discover.p_sep_info = p_sep_info; 281 evt.discover.num_seps = max_seps; 282 evt.discover.p_cback = p_cback; 283 avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_REQ_EVT, &evt); 284 } 285 } 286 287 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 288 289 return result; 290 } 291 292 /******************************************************************************* 293 * 294 * Function avdt_get_cap_req 295 * 296 * Description internal function to serve both AVDT_GetCapReq and 297 * AVDT_GetAllCapReq 298 * 299 * Returns AVDT_SUCCESS if successful, otherwise error. 300 * 301 ******************************************************************************/ 302 static uint16_t avdt_get_cap_req(const RawAddress& bd_addr, 303 tAVDT_CCB_API_GETCAP* p_evt) { 304 tAVDT_CCB* p_ccb = NULL; 305 uint16_t result = AVDT_SUCCESS; 306 307 AVDT_TRACE_DEBUG("%s", __func__); 308 309 /* verify SEID */ 310 if ((p_evt->single.seid < AVDT_SEID_MIN) || 311 (p_evt->single.seid > AVDT_SEID_MAX)) { 312 AVDT_TRACE_ERROR("seid: %d", p_evt->single.seid); 313 result = AVDT_BAD_PARAMS; 314 } 315 /* find channel control block for this bd addr; if none, allocate one */ 316 else { 317 p_ccb = avdt_ccb_by_bd(bd_addr); 318 if (p_ccb == NULL) { 319 p_ccb = avdt_ccb_alloc(bd_addr); 320 if (p_ccb == NULL) { 321 /* could not allocate channel control block */ 322 result = AVDT_NO_RESOURCES; 323 } 324 } 325 } 326 327 if (result == AVDT_SUCCESS) { 328 /* make sure no discovery or get capabilities req already in progress */ 329 if (p_ccb->proc_busy) { 330 result = AVDT_BUSY; 331 } 332 /* send event to ccb */ 333 else { 334 avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_REQ_EVT, (tAVDT_CCB_EVT*)p_evt); 335 } 336 } 337 338 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 339 340 return result; 341 } 342 343 /******************************************************************************* 344 * 345 * Function AVDT_GetCapReq 346 * 347 * Description This function initiates a connection to the AVDTP service 348 * on the peer device, if not already present, and gets the 349 * capabilities of a stream endpoint on the peer device. 350 * This function can be called at any time regardless of 351 * whether there is an AVDTP connection to the peer device. 352 * 353 * When the procedure is complete, an AVDT_GETCAP_CFM_EVT is 354 * sent to the application via its callback function. The 355 * application must not call AVDT_GetCapReq() or 356 * AVDT_DiscoverReq() again until the procedure is complete. 357 * 358 * The memory pointed to by p_cfg is allocated by the 359 * application. This memory is written to by AVDTP as part 360 * of the get capabilities procedure. This memory must 361 * remain accessible until the application receives 362 * the AVDT_GETCAP_CFM_EVT. 363 * 364 * Returns AVDT_SUCCESS if successful, otherwise error. 365 * 366 ******************************************************************************/ 367 uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t seid, 368 tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback) { 369 tAVDT_CCB_API_GETCAP getcap; 370 uint16_t result = AVDT_SUCCESS; 371 372 AVDT_TRACE_DEBUG("%s", __func__); 373 374 getcap.single.seid = seid; 375 getcap.single.sig_id = AVDT_SIG_GETCAP; 376 getcap.p_cfg = p_cfg; 377 getcap.p_cback = p_cback; 378 result = avdt_get_cap_req(bd_addr, &getcap); 379 380 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 381 382 return result; 383 } 384 385 /******************************************************************************* 386 * 387 * Function AVDT_GetAllCapReq 388 * 389 * Description This function initiates a connection to the AVDTP service 390 * on the peer device, if not already present, and gets the 391 * capabilities of a stream endpoint on the peer device. 392 * This function can be called at any time regardless of 393 * whether there is an AVDTP connection to the peer device. 394 * 395 * When the procedure is complete, an AVDT_GETCAP_CFM_EVT is 396 * sent to the application via its callback function. The 397 * application must not call AVDT_GetCapReq() or 398 * AVDT_DiscoverReq() again until the procedure is complete. 399 * 400 * The memory pointed to by p_cfg is allocated by the 401 * application. This memory is written to by AVDTP as part 402 * of the get capabilities procedure. This memory must 403 * remain accessible until the application receives 404 * the AVDT_GETCAP_CFM_EVT. 405 * 406 * Returns AVDT_SUCCESS if successful, otherwise error. 407 * 408 ******************************************************************************/ 409 uint16_t AVDT_GetAllCapReq(const RawAddress& bd_addr, uint8_t seid, 410 tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback) { 411 tAVDT_CCB_API_GETCAP getcap; 412 uint16_t result = AVDT_SUCCESS; 413 414 AVDT_TRACE_DEBUG("%s", __func__); 415 416 getcap.single.seid = seid; 417 getcap.single.sig_id = AVDT_SIG_GET_ALLCAP; 418 getcap.p_cfg = p_cfg; 419 getcap.p_cback = p_cback; 420 result = avdt_get_cap_req(bd_addr, &getcap); 421 422 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 423 424 return result; 425 } 426 427 /******************************************************************************* 428 * 429 * Function AVDT_DelayReport 430 * 431 * Description This functions sends a Delay Report to the peer device 432 * that is associated with a particular SEID. 433 * This function is called by SNK device. 434 * 435 * Returns AVDT_SUCCESS if successful, otherwise error. 436 * 437 ******************************************************************************/ 438 uint16_t AVDT_DelayReport(uint8_t handle, uint8_t seid, uint16_t delay) { 439 tAVDT_SCB* p_scb; 440 uint16_t result = AVDT_SUCCESS; 441 tAVDT_SCB_EVT evt; 442 443 AVDT_TRACE_DEBUG("%s: handle=%d ceid=%d delay=%d", __func__, handle, seid, 444 delay); 445 446 /* map handle to scb */ 447 p_scb = avdt_scb_by_hdl(handle); 448 if (p_scb == NULL) { 449 result = AVDT_BAD_HANDLE; 450 } else 451 /* send event to scb */ 452 { 453 evt.apidelay.hdr.seid = seid; 454 evt.apidelay.delay = delay; 455 avdt_scb_event(p_scb, AVDT_SCB_API_DELAY_RPT_REQ_EVT, &evt); 456 } 457 458 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 459 460 return result; 461 } 462 463 /******************************************************************************* 464 * 465 * Function AVDT_OpenReq 466 * 467 * Description This function initiates a connection to the AVDTP service 468 * on the peer device, if not already present, and connects 469 * to a stream endpoint on a peer device. When the connection 470 * is completed, an AVDT_OPEN_CFM_EVT is sent to the 471 * application via the control callback function for this 472 * handle. 473 * 474 * Returns AVDT_SUCCESS if successful, otherwise error. 475 * 476 ******************************************************************************/ 477 uint16_t AVDT_OpenReq(uint8_t handle, const RawAddress& bd_addr, uint8_t seid, 478 tAVDT_CFG* p_cfg) { 479 tAVDT_CCB* p_ccb = NULL; 480 tAVDT_SCB* p_scb = NULL; 481 uint16_t result = AVDT_SUCCESS; 482 tAVDT_SCB_EVT evt; 483 484 AVDT_TRACE_DEBUG("%s: handle=%d seid=%d", __func__, handle, seid); 485 486 /* verify SEID */ 487 if ((seid < AVDT_SEID_MIN) || (seid > AVDT_SEID_MAX)) { 488 result = AVDT_BAD_PARAMS; 489 } 490 /* map handle to scb */ 491 else { 492 p_scb = avdt_scb_by_hdl(handle); 493 if (p_scb == NULL) { 494 result = AVDT_BAD_HANDLE; 495 } 496 /* find channel control block for this bd addr; if none, allocate one */ 497 else { 498 p_ccb = avdt_ccb_by_bd(bd_addr); 499 if (p_ccb == NULL) { 500 p_ccb = avdt_ccb_alloc(bd_addr); 501 if (p_ccb == NULL) { 502 /* could not allocate channel control block */ 503 result = AVDT_NO_RESOURCES; 504 } 505 } 506 } 507 } 508 509 /* send event to scb */ 510 if (result == AVDT_SUCCESS) { 511 A2DP_DumpCodecInfo(p_cfg->codec_info); 512 513 evt.msg.config_cmd.hdr.seid = seid; 514 evt.msg.config_cmd.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb); 515 evt.msg.config_cmd.int_seid = handle; 516 evt.msg.config_cmd.p_cfg = p_cfg; 517 avdt_scb_event(p_scb, AVDT_SCB_API_SETCONFIG_REQ_EVT, &evt); 518 } 519 520 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 521 522 return result; 523 } 524 525 /******************************************************************************* 526 * 527 * Function AVDT_ConfigRsp 528 * 529 * Description Respond to a configure request from the peer device. This 530 * function must be called if the application receives an 531 * AVDT_CONFIG_IND_EVT through its control callback. 532 * 533 * 534 * Returns AVDT_SUCCESS if successful, otherwise error. 535 * 536 ******************************************************************************/ 537 uint16_t AVDT_ConfigRsp(uint8_t handle, uint8_t label, uint8_t error_code, 538 uint8_t category) { 539 tAVDT_SCB* p_scb; 540 tAVDT_SCB_EVT evt; 541 uint16_t result = AVDT_SUCCESS; 542 uint8_t event_code; 543 544 AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d category=%d", __func__, 545 handle, label, error_code, category); 546 547 /* map handle to scb */ 548 p_scb = avdt_scb_by_hdl(handle); 549 if (p_scb == NULL) { 550 result = AVDT_BAD_HANDLE; 551 } 552 /* handle special case when this function is called but peer has not send 553 ** a configuration cmd; ignore and return error result 554 */ 555 else if (!p_scb->in_use) { 556 result = AVDT_BAD_HANDLE; 557 } 558 /* send event to scb */ 559 else { 560 evt.msg.hdr.err_code = error_code; 561 evt.msg.hdr.err_param = category; 562 evt.msg.hdr.label = label; 563 if (error_code == 0) { 564 event_code = AVDT_SCB_API_SETCONFIG_RSP_EVT; 565 } else { 566 event_code = AVDT_SCB_API_SETCONFIG_REJ_EVT; 567 } 568 avdt_scb_event(p_scb, event_code, &evt); 569 } 570 571 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 572 573 return result; 574 } 575 576 /******************************************************************************* 577 * 578 * Function AVDT_StartReq 579 * 580 * Description Start one or more stream endpoints. This initiates the 581 * transfer of media packets for the streams. All stream 582 * endpoints must previously be opened. When the streams 583 * are started, an AVDT_START_CFM_EVT is sent to the 584 * application via the control callback function for each 585 * stream. 586 * 587 * 588 * Returns AVDT_SUCCESS if successful, otherwise error. 589 * 590 ******************************************************************************/ 591 uint16_t AVDT_StartReq(uint8_t* p_handles, uint8_t num_handles) { 592 tAVDT_SCB* p_scb = NULL; 593 tAVDT_CCB_EVT evt; 594 uint16_t result = AVDT_SUCCESS; 595 int i; 596 597 AVDT_TRACE_DEBUG("%s: num_handles=%d", __func__, num_handles); 598 599 if ((num_handles == 0) || (num_handles > AVDT_NUM_SEPS)) { 600 result = AVDT_BAD_PARAMS; 601 } else { 602 /* verify handles */ 603 for (i = 0; i < num_handles; i++) { 604 p_scb = avdt_scb_by_hdl(p_handles[i]); 605 if (p_scb == NULL) { 606 result = AVDT_BAD_HANDLE; 607 break; 608 } 609 } 610 } 611 612 if (result == AVDT_SUCCESS) { 613 if (p_scb->p_ccb == NULL) { 614 result = AVDT_BAD_HANDLE; 615 } else { 616 /* send event to ccb */ 617 memcpy(evt.msg.multi.seid_list, p_handles, num_handles); 618 evt.msg.multi.num_seps = num_handles; 619 avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_API_START_REQ_EVT, &evt); 620 } 621 } 622 623 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 624 625 return result; 626 } 627 628 /******************************************************************************* 629 * 630 * Function AVDT_SuspendReq 631 * 632 * Description Suspend one or more stream endpoints. This suspends the 633 * transfer of media packets for the streams. All stream 634 * endpoints must previously be open and started. When the 635 * streams are suspended, an AVDT_SUSPEND_CFM_EVT is sent to 636 * the application via the control callback function for 637 * each stream. 638 * 639 * 640 * Returns AVDT_SUCCESS if successful, otherwise error. 641 * 642 ******************************************************************************/ 643 uint16_t AVDT_SuspendReq(uint8_t* p_handles, uint8_t num_handles) { 644 tAVDT_SCB* p_scb = NULL; 645 tAVDT_CCB_EVT evt; 646 uint16_t result = AVDT_SUCCESS; 647 int i; 648 649 AVDT_TRACE_DEBUG("%s: num_handles=%d", __func__, num_handles); 650 651 if ((num_handles == 0) || (num_handles > AVDT_NUM_SEPS)) { 652 result = AVDT_BAD_PARAMS; 653 } else { 654 /* verify handles */ 655 for (i = 0; i < num_handles; i++) { 656 p_scb = avdt_scb_by_hdl(p_handles[i]); 657 if (p_scb == NULL) { 658 result = AVDT_BAD_HANDLE; 659 break; 660 } 661 } 662 } 663 664 if (result == AVDT_SUCCESS) { 665 if (p_scb->p_ccb == NULL) { 666 result = AVDT_BAD_HANDLE; 667 } else { 668 /* send event to ccb */ 669 memcpy(evt.msg.multi.seid_list, p_handles, num_handles); 670 evt.msg.multi.num_seps = num_handles; 671 avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_API_SUSPEND_REQ_EVT, &evt); 672 } 673 } 674 675 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 676 677 return result; 678 } 679 680 /******************************************************************************* 681 * 682 * Function AVDT_CloseReq 683 * 684 * Description Close a stream endpoint. This stops the transfer of media 685 * packets and closes the transport channel associated with 686 * this stream endpoint. When the stream is closed, an 687 * AVDT_CLOSE_CFM_EVT is sent to the application via the 688 * control callback function for this handle. 689 * 690 * 691 * Returns AVDT_SUCCESS if successful, otherwise error. 692 * 693 ******************************************************************************/ 694 uint16_t AVDT_CloseReq(uint8_t handle) { 695 tAVDT_SCB* p_scb; 696 uint16_t result = AVDT_SUCCESS; 697 698 AVDT_TRACE_DEBUG("%s: handle=%d", __func__, handle); 699 700 /* map handle to scb */ 701 p_scb = avdt_scb_by_hdl(handle); 702 if (p_scb == NULL) { 703 result = AVDT_BAD_HANDLE; 704 } else 705 /* send event to scb */ 706 { 707 avdt_scb_event(p_scb, AVDT_SCB_API_CLOSE_REQ_EVT, NULL); 708 } 709 710 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 711 712 return result; 713 } 714 715 /******************************************************************************* 716 * 717 * Function AVDT_ReconfigReq 718 * 719 * Description Reconfigure a stream endpoint. This allows the application 720 * to change the codec or content protection capabilities of 721 * a stream endpoint after it has been opened. This function 722 * can only be called if the stream is opened but not started 723 * or if the stream has been suspended. When the procedure 724 * is completed, an AVDT_RECONFIG_CFM_EVT is sent to the 725 * application via the control callback function for this 726 * handle. 727 * 728 * 729 * Returns AVDT_SUCCESS if successful, otherwise error. 730 * 731 ******************************************************************************/ 732 uint16_t AVDT_ReconfigReq(uint8_t handle, tAVDT_CFG* p_cfg) { 733 tAVDT_SCB* p_scb; 734 uint16_t result = AVDT_SUCCESS; 735 tAVDT_SCB_EVT evt; 736 737 AVDT_TRACE_DEBUG("%s: handle=%d", __func__, handle); 738 739 /* map handle to scb */ 740 p_scb = avdt_scb_by_hdl(handle); 741 if (p_scb == NULL) { 742 result = AVDT_BAD_HANDLE; 743 } 744 /* send event to scb */ 745 else { 746 /* force psc_mask to zero */ 747 p_cfg->psc_mask = 0; 748 evt.msg.reconfig_cmd.p_cfg = p_cfg; 749 avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_REQ_EVT, &evt); 750 } 751 752 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 753 754 return result; 755 } 756 757 /******************************************************************************* 758 * 759 * Function AVDT_ReconfigRsp 760 * 761 * Description Respond to a reconfigure request from the peer device. 762 * This function must be called if the application receives 763 * an AVDT_RECONFIG_IND_EVT through its control callback. 764 * 765 * 766 * Returns AVDT_SUCCESS if successful, otherwise error. 767 * 768 ******************************************************************************/ 769 uint16_t AVDT_ReconfigRsp(uint8_t handle, uint8_t label, uint8_t error_code, 770 uint8_t category) { 771 tAVDT_SCB* p_scb; 772 tAVDT_SCB_EVT evt; 773 uint16_t result = AVDT_SUCCESS; 774 775 AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d category=%d", __func__, 776 handle, label, error_code, category); 777 778 /* map handle to scb */ 779 p_scb = avdt_scb_by_hdl(handle); 780 if (p_scb == NULL) { 781 result = AVDT_BAD_HANDLE; 782 } 783 /* send event to scb */ 784 else { 785 evt.msg.hdr.err_code = error_code; 786 evt.msg.hdr.err_param = category; 787 evt.msg.hdr.label = label; 788 avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_RSP_EVT, &evt); 789 } 790 791 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 792 793 return result; 794 } 795 796 /******************************************************************************* 797 * 798 * Function AVDT_SecurityReq 799 * 800 * Description Send a security request to the peer device. When the 801 * security procedure is completed, an AVDT_SECURITY_CFM_EVT 802 * is sent to the application via the control callback function 803 * for this handle. (Please note that AVDTP security 804 * procedures are unrelated to Bluetooth link level security.) 805 * 806 * 807 * Returns AVDT_SUCCESS if successful, otherwise error. 808 * 809 ******************************************************************************/ 810 uint16_t AVDT_SecurityReq(uint8_t handle, uint8_t* p_data, uint16_t len) { 811 tAVDT_SCB* p_scb; 812 uint16_t result = AVDT_SUCCESS; 813 tAVDT_SCB_EVT evt; 814 815 AVDT_TRACE_DEBUG("%s: handle=%d len=%d", __func__, handle, len); 816 817 /* map handle to scb */ 818 p_scb = avdt_scb_by_hdl(handle); 819 if (p_scb == NULL) { 820 result = AVDT_BAD_HANDLE; 821 } 822 /* send event to scb */ 823 else { 824 evt.msg.security_rsp.p_data = p_data; 825 evt.msg.security_rsp.len = len; 826 avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_REQ_EVT, &evt); 827 } 828 829 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 830 831 return result; 832 } 833 834 /******************************************************************************* 835 * 836 * Function AVDT_SecurityRsp 837 * 838 * Description Respond to a security request from the peer device. 839 * This function must be called if the application receives 840 * an AVDT_SECURITY_IND_EVT through its control callback. 841 * (Please note that AVDTP security procedures are unrelated 842 * to Bluetooth link level security.) 843 * 844 * 845 * Returns AVDT_SUCCESS if successful, otherwise error. 846 * 847 ******************************************************************************/ 848 uint16_t AVDT_SecurityRsp(uint8_t handle, uint8_t label, uint8_t error_code, 849 uint8_t* p_data, uint16_t len) { 850 tAVDT_SCB* p_scb; 851 uint16_t result = AVDT_SUCCESS; 852 tAVDT_SCB_EVT evt; 853 854 AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d len=%d", __func__, 855 handle, label, error_code, len); 856 857 /* map handle to scb */ 858 p_scb = avdt_scb_by_hdl(handle); 859 if (p_scb == NULL) { 860 result = AVDT_BAD_HANDLE; 861 } 862 /* send event to scb */ 863 else { 864 evt.msg.security_rsp.hdr.err_code = error_code; 865 evt.msg.security_rsp.hdr.label = label; 866 evt.msg.security_rsp.p_data = p_data; 867 evt.msg.security_rsp.len = len; 868 avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_RSP_EVT, &evt); 869 } 870 871 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 872 873 return result; 874 } 875 876 /******************************************************************************* 877 * 878 * Function AVDT_WriteReqOpt 879 * 880 * Description Send a media packet to the peer device. The stream must 881 * be started before this function is called. Also, this 882 * function can only be called if the stream is a SRC. 883 * 884 * When AVDTP has sent the media packet and is ready for the 885 * next packet, an AVDT_WRITE_CFM_EVT is sent to the 886 * application via the control callback. The application must 887 * wait for the AVDT_WRITE_CFM_EVT before it makes the next 888 * call to AVDT_WriteReq(). If the applications calls 889 * AVDT_WriteReq() before it receives the event the packet 890 * will not be sent. The application may make its first call 891 * to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT 892 * or AVDT_START_IND_EVT. 893 * 894 * The application passes the packet using the BT_HDR 895 * structure. 896 * This structure is described in section 2.1. The offset 897 * field must be equal to or greater than AVDT_MEDIA_OFFSET 898 * (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used). 899 * This allows enough space in the buffer for the L2CAP and 900 * AVDTP headers. 901 * 902 * The memory pointed to by p_pkt must be a GKI buffer 903 * allocated by the application. This buffer will be freed 904 * by the protocol stack; the application must not free 905 * this buffer. 906 * 907 * The opt parameter allows passing specific options like: 908 * - NO_RTP : do not add the RTP header to buffer 909 * 910 * Returns AVDT_SUCCESS if successful, otherwise error. 911 * 912 ******************************************************************************/ 913 uint16_t AVDT_WriteReqOpt(uint8_t handle, BT_HDR* p_pkt, uint32_t time_stamp, 914 uint8_t m_pt, tAVDT_DATA_OPT_MASK opt) { 915 tAVDT_SCB* p_scb; 916 tAVDT_SCB_EVT evt; 917 uint16_t result = AVDT_SUCCESS; 918 919 AVDT_TRACE_DEBUG("%s: handle=%d timestamp=%d m_pt=0x%x opt=0x%x", __func__, 920 handle, time_stamp, m_pt, opt); 921 922 /* map handle to scb */ 923 p_scb = avdt_scb_by_hdl(handle); 924 if (p_scb == NULL) { 925 result = AVDT_BAD_HANDLE; 926 } else { 927 evt.apiwrite.p_buf = p_pkt; 928 evt.apiwrite.time_stamp = time_stamp; 929 evt.apiwrite.m_pt = m_pt; 930 evt.apiwrite.opt = opt; 931 avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt); 932 } 933 934 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 935 936 return result; 937 } 938 939 /******************************************************************************* 940 * 941 * Function AVDT_WriteReq 942 * 943 * Description Send a media packet to the peer device. The stream must 944 * be started before this function is called. Also, this 945 * function can only be called if the stream is a SRC. 946 * 947 * When AVDTP has sent the media packet and is ready for the 948 * next packet, an AVDT_WRITE_CFM_EVT is sent to the 949 * application via the control callback. The application must 950 * wait for the AVDT_WRITE_CFM_EVT before it makes the next 951 * call to AVDT_WriteReq(). If the applications calls 952 * AVDT_WriteReq() before it receives the event the packet 953 * will not be sent. The application may make its first call 954 * to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT 955 * or AVDT_START_IND_EVT. 956 * 957 * The application passes the packet using the BT_HDR 958 * structure. 959 * This structure is described in section 2.1. The offset 960 * field must be equal to or greater than AVDT_MEDIA_OFFSET. 961 * This allows enough space in the buffer for the L2CAP and 962 * AVDTP headers. 963 * 964 * The memory pointed to by p_pkt must be a GKI buffer 965 * allocated by the application. This buffer will be freed 966 * by the protocol stack; the application must not free 967 * this buffer. 968 * 969 * 970 * Returns AVDT_SUCCESS if successful, otherwise error. 971 * 972 ******************************************************************************/ 973 uint16_t AVDT_WriteReq(uint8_t handle, BT_HDR* p_pkt, uint32_t time_stamp, 974 uint8_t m_pt) { 975 return AVDT_WriteReqOpt(handle, p_pkt, time_stamp, m_pt, AVDT_DATA_OPT_NONE); 976 } 977 978 /******************************************************************************* 979 * 980 * Function AVDT_ConnectReq 981 * 982 * Description This function initiates an AVDTP signaling connection 983 * to the peer device. When the connection is completed, an 984 * AVDT_CONNECT_IND_EVT is sent to the application via its 985 * control callback function. If the connection attempt fails 986 * an AVDT_DISCONNECT_IND_EVT is sent. The security mask 987 * parameter overrides the outgoing security mask set in 988 * AVDT_Register(). 989 * 990 * Returns AVDT_SUCCESS if successful, otherwise error. 991 * 992 ******************************************************************************/ 993 uint16_t AVDT_ConnectReq(const RawAddress& bd_addr, uint8_t sec_mask, 994 tAVDT_CTRL_CBACK* p_cback) { 995 tAVDT_CCB* p_ccb = NULL; 996 uint16_t result = AVDT_SUCCESS; 997 tAVDT_CCB_EVT evt; 998 999 AVDT_TRACE_DEBUG("%s: sec_mask=0x%x", __func__, sec_mask); 1000 1001 /* find channel control block for this bd addr; if none, allocate one */ 1002 p_ccb = avdt_ccb_by_bd(bd_addr); 1003 if (p_ccb == NULL) { 1004 p_ccb = avdt_ccb_alloc(bd_addr); 1005 if (p_ccb == NULL) { 1006 /* could not allocate channel control block */ 1007 result = AVDT_NO_RESOURCES; 1008 } 1009 } else if (p_ccb->ll_opened == false) { 1010 AVDT_TRACE_WARNING("AVDT_ConnectReq: CCB LL is in the middle of opening"); 1011 1012 /* ccb was already allocated for the incoming signalling. */ 1013 result = AVDT_BUSY; 1014 } 1015 1016 if (result == AVDT_SUCCESS) { 1017 /* send event to ccb */ 1018 evt.connect.p_cback = p_cback; 1019 evt.connect.sec_mask = sec_mask; 1020 avdt_ccb_event(p_ccb, AVDT_CCB_API_CONNECT_REQ_EVT, &evt); 1021 } 1022 1023 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 1024 1025 return result; 1026 } 1027 1028 /******************************************************************************* 1029 * 1030 * Function AVDT_DisconnectReq 1031 * 1032 * Description This function disconnect an AVDTP signaling connection 1033 * to the peer device. When disconnected an 1034 * AVDT_DISCONNECT_IND_EVT is sent to the application via its 1035 * control callback function. 1036 * 1037 * Returns AVDT_SUCCESS if successful, otherwise error. 1038 * 1039 ******************************************************************************/ 1040 uint16_t AVDT_DisconnectReq(const RawAddress& bd_addr, 1041 tAVDT_CTRL_CBACK* p_cback) { 1042 tAVDT_CCB* p_ccb = NULL; 1043 uint16_t result = AVDT_SUCCESS; 1044 tAVDT_CCB_EVT evt; 1045 1046 AVDT_TRACE_WARNING("%s: address=%s", __func__, bd_addr.ToString().c_str()); 1047 1048 /* find channel control block for this bd addr; if none, error */ 1049 p_ccb = avdt_ccb_by_bd(bd_addr); 1050 if (p_ccb == NULL) { 1051 result = AVDT_BAD_PARAMS; 1052 } 1053 1054 if (result == AVDT_SUCCESS) { 1055 /* send event to ccb */ 1056 evt.disconnect.p_cback = p_cback; 1057 avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCONNECT_REQ_EVT, &evt); 1058 } 1059 1060 AVDT_TRACE_DEBUG("%s: address=%s result=%d", __func__, 1061 bd_addr.ToString().c_str(), result); 1062 1063 return result; 1064 } 1065 1066 /******************************************************************************* 1067 * 1068 * Function AVDT_GetL2CapChannel 1069 * 1070 * Description Get the L2CAP CID used by the handle. 1071 * 1072 * Returns CID if successful, otherwise 0. 1073 * 1074 ******************************************************************************/ 1075 uint16_t AVDT_GetL2CapChannel(uint8_t handle) { 1076 tAVDT_SCB* p_scb; 1077 tAVDT_CCB* p_ccb; 1078 uint8_t tcid; 1079 uint16_t lcid = 0; 1080 1081 /* map handle to scb */ 1082 if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) && 1083 ((p_ccb = p_scb->p_ccb) != NULL)) { 1084 /* get tcid from type, scb */ 1085 tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb); 1086 1087 lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid; 1088 } 1089 1090 return (lcid); 1091 } 1092 1093 /******************************************************************************* 1094 * 1095 * Function AVDT_GetSignalChannel 1096 * 1097 * Description Get the L2CAP CID used by the signal channel of the given 1098 * handle. 1099 * 1100 * Returns CID if successful, otherwise 0. 1101 * 1102 ******************************************************************************/ 1103 uint16_t AVDT_GetSignalChannel(uint8_t handle, const RawAddress& bd_addr) { 1104 tAVDT_SCB* p_scb; 1105 tAVDT_CCB* p_ccb; 1106 uint8_t tcid = 0; /* tcid is always 0 for signal channel */ 1107 uint16_t lcid = 0; 1108 1109 /* map handle to scb */ 1110 if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) && 1111 ((p_ccb = p_scb->p_ccb) != NULL)) { 1112 lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid; 1113 } else { 1114 p_ccb = avdt_ccb_by_bd(bd_addr); 1115 if (p_ccb != NULL) { 1116 lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid; 1117 } 1118 } 1119 1120 return (lcid); 1121 } 1122 1123 #if (AVDT_REPORTING == TRUE) 1124 /******************************************************************************* 1125 * 1126 * Function AVDT_SendReport 1127 * 1128 * Description 1129 * 1130 * 1131 * 1132 * Returns 1133 * 1134 ******************************************************************************/ 1135 uint16_t AVDT_SendReport(uint8_t handle, AVDT_REPORT_TYPE type, 1136 tAVDT_REPORT_DATA* p_data) { 1137 tAVDT_SCB* p_scb; 1138 uint16_t result = AVDT_BAD_PARAMS; 1139 tAVDT_TC_TBL* p_tbl; 1140 uint8_t *p, *plen, *pm1, *p_end; 1141 uint32_t ssrc; 1142 uint16_t len; 1143 1144 AVDT_TRACE_DEBUG("%s: handle=%d type=%d", __func__, handle, type); 1145 1146 /* map handle to scb && verify parameters */ 1147 if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) && (p_scb->p_ccb != NULL) && 1148 (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) || 1149 ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) || 1150 (type == AVDT_RTCP_PT_SDES))) { 1151 result = AVDT_NO_RESOURCES; 1152 1153 /* build SR - assume fit in one packet */ 1154 p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb); 1155 if (p_tbl->state == AVDT_AD_ST_OPEN) { 1156 BT_HDR* p_pkt = (BT_HDR*)osi_malloc(p_tbl->peer_mtu + sizeof(BT_HDR)); 1157 1158 p_pkt->offset = L2CAP_MIN_OFFSET; 1159 p = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 1160 pm1 = p; 1161 *p++ = AVDT_MEDIA_OCTET1 | 1; 1162 *p++ = type; 1163 /* save the location for length */ 1164 plen = p; 1165 p += 2; 1166 ssrc = avdt_scb_gen_ssrc(p_scb); 1167 UINT32_TO_BE_STREAM(p, ssrc); 1168 1169 switch (type) { 1170 case AVDT_RTCP_PT_SR: /* Sender Report */ 1171 *pm1 = AVDT_MEDIA_OCTET1; 1172 UINT32_TO_BE_STREAM(p, p_data->sr.ntp_sec); 1173 UINT32_TO_BE_STREAM(p, p_data->sr.ntp_frac); 1174 UINT32_TO_BE_STREAM(p, p_data->sr.rtp_time); 1175 UINT32_TO_BE_STREAM(p, p_data->sr.pkt_count); 1176 UINT32_TO_BE_STREAM(p, p_data->sr.octet_count); 1177 break; 1178 1179 case AVDT_RTCP_PT_RR: /* Receiver Report */ 1180 *p++ = p_data->rr.frag_lost; 1181 AVDT_TRACE_API("packet_lost: %d", p_data->rr.packet_lost); 1182 p_data->rr.packet_lost &= 0xFFFFFF; 1183 AVDT_TRACE_API("packet_lost: %d", p_data->rr.packet_lost); 1184 UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost); 1185 UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd); 1186 UINT32_TO_BE_STREAM(p, p_data->rr.jitter); 1187 UINT32_TO_BE_STREAM(p, p_data->rr.lsr); 1188 UINT32_TO_BE_STREAM(p, p_data->rr.dlsr); 1189 break; 1190 1191 case AVDT_RTCP_PT_SDES: /* Source Description */ 1192 *p++ = AVDT_RTCP_SDES_CNAME; 1193 len = strlen((char*)p_data->cname); 1194 if (len > AVDT_MAX_CNAME_SIZE) len = AVDT_MAX_CNAME_SIZE; 1195 *p++ = (uint8_t)len; 1196 strlcpy((char*)p, (char*)p_data->cname, len + 1); 1197 p += len; 1198 break; 1199 } 1200 p_end = p; 1201 len = p - pm1 - 1; 1202 UINT16_TO_BE_STREAM(plen, len); 1203 1204 /* set the actual payload length */ 1205 p_pkt->len = p_end - p; 1206 /* send the packet */ 1207 if (L2CAP_DW_FAILED != 1208 avdt_ad_write_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, p_pkt)) 1209 result = AVDT_SUCCESS; 1210 } 1211 } 1212 1213 AVDT_TRACE_DEBUG("%s: result=%d", __func__, result); 1214 1215 return result; 1216 } 1217 #endif 1218 1219 /****************************************************************************** 1220 * 1221 * Function AVDT_SetTraceLevel 1222 * 1223 * Description Sets the trace level for AVDT. If 0xff is passed, the 1224 * current trace level is returned. 1225 * 1226 * Input Parameters: 1227 * new_level: The level to set the AVDT tracing to: 1228 * 0xff-returns the current setting. 1229 * 0-turns off tracing. 1230 * >= 1-Errors. 1231 * >= 2-Warnings. 1232 * >= 3-APIs. 1233 * >= 4-Events. 1234 * >= 5-Debug. 1235 * 1236 * Returns The new trace level or current trace level if 1237 * the input parameter is 0xff. 1238 * 1239 *****************************************************************************/ 1240 uint8_t AVDT_SetTraceLevel(uint8_t new_level) { 1241 if (new_level != 0xFF) avdt_cb.trace_level = new_level; 1242 1243 return (avdt_cb.trace_level); 1244 } 1245