summaryrefslogtreecommitdiffstats
path: root/stack/avdt/avdt_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'stack/avdt/avdt_api.c')
-rw-r--r--stack/avdt/avdt_api.c1383
1 files changed, 1383 insertions, 0 deletions
diff --git a/stack/avdt/avdt_api.c b/stack/avdt/avdt_api.c
new file mode 100644
index 0000000..67fe452
--- /dev/null
+++ b/stack/avdt/avdt_api.c
@@ -0,0 +1,1383 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains API of the audio/video distribution transport
+ * protocol.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "avdt_api.h"
+#include "avdtc_api.h"
+#include "avdt_int.h"
+#include "l2c_api.h"
+#include "btm_api.h"
+#include "btu.h"
+
+
+#if (defined BTTRC_INCLUDED && BTTRC_INCLUDED == TRUE)
+#include "bttrc_str_ids.h"
+#endif
+
+/* Control block for AVDT */
+#if AVDT_DYNAMIC_MEMORY == FALSE
+tAVDT_CB avdt_cb;
+#endif
+
+
+/*******************************************************************************
+**
+** Function avdt_process_timeout
+**
+** Description This function is called by BTU when an AVDTP timer
+** expires. The function sends a timer event to the
+** appropriate CCB or SCB state machine.
+**
+** This function is for use internal to the stack only.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void avdt_process_timeout(TIMER_LIST_ENT *p_tle)
+{
+ UINT8 event = 0;
+ UINT8 err_code = AVDT_ERR_TIMEOUT;
+
+ switch (p_tle->event)
+ {
+ case BTU_TTYPE_AVDT_CCB_RET:
+ event = AVDT_CCB_RET_TOUT_EVT + AVDT_CCB_MKR;
+ break;
+
+ case BTU_TTYPE_AVDT_CCB_RSP:
+ event = AVDT_CCB_RSP_TOUT_EVT + AVDT_CCB_MKR;
+ break;
+
+ case BTU_TTYPE_AVDT_CCB_IDLE:
+ event = AVDT_CCB_IDLE_TOUT_EVT + AVDT_CCB_MKR;
+ break;
+
+ case BTU_TTYPE_AVDT_SCB_TC:
+ event = AVDT_SCB_TC_TOUT_EVT;
+ break;
+
+ default:
+ break;
+ }
+
+ if (event & AVDT_CCB_MKR)
+ {
+ avdt_ccb_event((tAVDT_CCB *) p_tle->param, (UINT8) (event & ~AVDT_CCB_MKR),
+ (tAVDT_CCB_EVT *) &err_code);
+ }
+ else
+ {
+ avdt_scb_event((tAVDT_SCB *) p_tle->param, event, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function AVDT_Register
+**
+** Description This is the system level registration function for the
+** AVDTP protocol. This function initializes AVDTP and
+** prepares the protocol stack for its use. This function
+** must be called once by the system or platform using AVDTP
+** before the other functions of the API an be used.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void AVDT_Register(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback)
+{
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_REGISTER);
+
+ /* register PSM with L2CAP */
+ L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO *) &avdt_l2c_appl);
+
+ /* set security level */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG);
+
+ /* do not use security on the media channel */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA);
+
+#if AVDT_REPORTING == TRUE
+ /* do not use security on the reporting channel */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
+ AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT);
+#endif
+
+ /* initialize AVDTP data structures */
+ avdt_scb_init();
+ avdt_ccb_init();
+ avdt_ad_init();
+#if defined(AVDT_INITIAL_TRACE_LEVEL)
+ avdt_cb.trace_level = AVDT_INITIAL_TRACE_LEVEL;
+#else
+ avdt_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+
+ /* copy registration struct */
+ memcpy(&avdt_cb.rcb, p_reg, sizeof(tAVDT_REG));
+ avdt_cb.p_conn_cback = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_Deregister
+**
+** Description This function is called to deregister use AVDTP protocol.
+** It is called when AVDTP is no longer being used by any
+** application in the system. Before this function can be
+** called, all streams must be removed with AVDT_RemoveStream().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void AVDT_Deregister(void)
+{
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DEREGISTER);
+
+ /* deregister PSM with L2CAP */
+ L2CA_Deregister(AVDT_PSM);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_CreateStream
+**
+** Description Create a stream endpoint. After a stream endpoint is
+** created an application can initiate a connection between
+** this endpoint and an endpoint on a peer device. In
+** addition, a peer device can discover, get the capabilities,
+** and connect to this endpoint.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs)
+{
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB *p_scb;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CREATESTREAM);
+
+ /* Verify parameters; if invalid, return failure */
+ if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || (p_cs->p_ctrl_cback == NULL))
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+ /* Allocate scb; if no scbs, return failure */
+ else if ((p_scb = avdt_scb_alloc(p_cs)) == NULL)
+ {
+ result = AVDT_NO_RESOURCES;
+ }
+ else
+ {
+ *p_handle = avdt_scb_to_hdl(p_scb);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_RemoveStream
+**
+** Description Remove a stream endpoint. This function is called when
+** the application is no longer using a stream endpoint.
+** If this function is called when the endpoint is connected
+** the connection is closed and then the stream endpoint
+** is removed.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_RemoveStream(UINT8 handle)
+{
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB *p_scb;
+
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_REMOVESTREAM);
+
+ /* look up scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ /* send remove event to scb */
+ avdt_scb_event(p_scb, AVDT_SCB_API_REMOVE_EVT, NULL);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_DiscoverReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and discovers
+** the stream endpoints on the peer device. (Please note
+** that AVDTP discovery is unrelated to SDP discovery).
+** This function can be called at any time regardless of whether
+** there is an AVDTP connection to the peer device.
+**
+** When discovery is complete, an AVDT_DISCOVER_CFM_EVT
+** is sent to the application via its callback function.
+** The application must not call AVDT_GetCapReq() or
+** AVDT_DiscoverReq() again to the same device until
+** discovery is complete.
+**
+** The memory addressed by sep_info is allocated by the
+** application. This memory is written to by AVDTP as part
+** of the discovery procedure. This memory must remain
+** accessible until the application receives the
+** AVDT_DISCOVER_CFM_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_DiscoverReq(BD_ADDR bd_addr, tAVDT_SEP_INFO *p_sep_info,
+ UINT8 max_seps, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB *p_ccb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_CCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DISCOVER_REQ);
+
+ /* find channel control block for this bd addr; if none, allocate one */
+ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* make sure no discovery or get capabilities req already in progress */
+ if (p_ccb->proc_busy)
+ {
+ result = AVDT_BUSY;
+ }
+ /* send event to ccb */
+ else
+ {
+ evt.discover.p_sep_info = p_sep_info;
+ evt.discover.num_seps = max_seps;
+ evt.discover.p_cback = p_cback;
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_REQ_EVT, &evt);
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function avdt_get_cap_req
+**
+** Description internal function to serve both AVDT_GetCapReq and
+** AVDT_GetAllCapReq
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+static UINT16 avdt_get_cap_req(BD_ADDR bd_addr, tAVDT_CCB_API_GETCAP *p_evt)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+
+ /* verify SEID */
+ if ((p_evt->single.seid < AVDT_SEID_MIN) || (p_evt->single.seid > AVDT_SEID_MAX))
+ {
+ AVDT_TRACE_ERROR1("seid: %d", p_evt->single.seid);
+ result = AVDT_BAD_PARAMS;
+ }
+ /* find channel control block for this bd addr; if none, allocate one */
+ else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* make sure no discovery or get capabilities req already in progress */
+ if (p_ccb->proc_busy)
+ {
+ result = AVDT_BUSY;
+ }
+ /* send event to ccb */
+ else
+ {
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_REQ_EVT, (tAVDT_CCB_EVT *)p_evt);
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetCapReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and gets the
+** capabilities of a stream endpoint on the peer device.
+** This function can be called at any time regardless of
+** whether there is an AVDTP connection to the peer device.
+**
+** When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
+** sent to the application via its callback function. The
+** application must not call AVDT_GetCapReq() or
+** AVDT_DiscoverReq() again until the procedure is complete.
+**
+** The memory pointed to by p_cfg is allocated by the
+** application. This memory is written to by AVDTP as part
+** of the get capabilities procedure. This memory must
+** remain accessible until the application receives
+** the AVDT_GETCAP_CFM_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_GetCapReq(BD_ADDR bd_addr, UINT8 seid, tAVDT_CFG *p_cfg, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB_API_GETCAP getcap;
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GETCAP_REQ, BTTRC_PARAM_UINT8, seid);
+
+ getcap.single.seid = seid;
+ getcap.single.sig_id = AVDT_SIG_GETCAP;
+ getcap.p_cfg = p_cfg;
+ getcap.p_cback = p_cback;
+ return avdt_get_cap_req (bd_addr, &getcap);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetAllCapReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and gets the
+** capabilities of a stream endpoint on the peer device.
+** This function can be called at any time regardless of
+** whether there is an AVDTP connection to the peer device.
+**
+** When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
+** sent to the application via its callback function. The
+** application must not call AVDT_GetCapReq() or
+** AVDT_DiscoverReq() again until the procedure is complete.
+**
+** The memory pointed to by p_cfg is allocated by the
+** application. This memory is written to by AVDTP as part
+** of the get capabilities procedure. This memory must
+** remain accessible until the application receives
+** the AVDT_GETCAP_CFM_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_GetAllCapReq(BD_ADDR bd_addr, UINT8 seid, tAVDT_CFG *p_cfg, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB_API_GETCAP getcap;
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GET_ALLCAP_REQ, BTTRC_PARAM_UINT8, seid);
+
+ getcap.single.seid = seid;
+ getcap.single.sig_id = AVDT_SIG_GET_ALLCAP;
+ getcap.p_cfg = p_cfg;
+ getcap.p_cback = p_cback;
+ return avdt_get_cap_req (bd_addr, &getcap);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_DelayReport
+**
+** Description This functions sends a Delay Report to the peer device
+** that is associated with a particular SEID.
+** This function is called by SNK device.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_DelayReport(UINT8 handle, UINT8 seid, UINT16 delay)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DELAY_REPORT);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ /* send event to scb */
+ {
+ evt.apidelay.hdr.seid = seid;
+ evt.apidelay.delay = delay;
+ avdt_scb_event(p_scb, AVDT_SCB_API_DELAY_RPT_REQ_EVT, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_OpenReq
+**
+** Description This function initiates a connection to the AVDTP service
+** on the peer device, if not already present, and connects
+** to a stream endpoint on a peer device. When the connection
+** is completed, an AVDT_OPEN_CFM_EVT is sent to the
+** application via the control callback function for this handle.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_OpenReq(UINT8 handle, BD_ADDR bd_addr, UINT8 seid, tAVDT_CFG *p_cfg)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ tAVDT_SCB *p_scb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_OPEN_REQ);
+
+
+ /* verify SEID */
+ if ((seid < AVDT_SEID_MIN) || (seid > AVDT_SEID_MAX))
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+ /* map handle to scb */
+ else if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* find channel control block for this bd addr; if none, allocate one */
+ else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+
+ /* send event to scb */
+ if (result == AVDT_SUCCESS)
+ {
+ evt.msg.config_cmd.hdr.seid = seid;
+ evt.msg.config_cmd.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
+ evt.msg.config_cmd.int_seid = handle;
+ evt.msg.config_cmd.p_cfg = p_cfg;
+ avdt_scb_event(p_scb, AVDT_SCB_API_SETCONFIG_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ConfigRsp
+**
+** Description Respond to a configure request from the peer device. This
+** function must be called if the application receives an
+** AVDT_CONFIG_IND_EVT through its control callback.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ConfigRsp(UINT8 handle, UINT8 label, UINT8 error_code, UINT8 category)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+ UINT8 event_code;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CONFIG_RSP);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* handle special case when this function is called but peer has not send
+ ** a configuration cmd; ignore and return error result
+ */
+ else if (!p_scb->in_use)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.hdr.err_code = error_code;
+ evt.msg.hdr.err_param = category;
+ evt.msg.hdr.label = label;
+ if (error_code == 0)
+ {
+ event_code = AVDT_SCB_API_SETCONFIG_RSP_EVT;
+ }
+ else
+ {
+ event_code = AVDT_SCB_API_SETCONFIG_REJ_EVT;
+ }
+ avdt_scb_event(p_scb, event_code, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_StartReq
+**
+** Description Start one or more stream endpoints. This initiates the
+** transfer of media packets for the streams. All stream
+** endpoints must previously be opened. When the streams
+** are started, an AVDT_START_CFM_EVT is sent to the
+** application via the control callback function for each stream.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_StartReq(UINT8 *p_handles, UINT8 num_handles)
+{
+ tAVDT_SCB *p_scb = NULL;
+ tAVDT_CCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+ int i;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_START_REQ);
+
+ if ((num_handles == 0) || (num_handles > AVDT_NUM_SEPS))
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+ else
+ {
+ /* verify handles */
+ for (i = 0; i < num_handles; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_handles[i])) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ break;
+ }
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ if (p_scb->p_ccb == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ /* send event to ccb */
+ memcpy(evt.msg.multi.seid_list, p_handles, num_handles);
+ evt.msg.multi.num_seps = num_handles;
+ avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_API_START_REQ_EVT, &evt);
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_SuspendReq
+**
+** Description Suspend one or more stream endpoints. This suspends the
+** transfer of media packets for the streams. All stream
+** endpoints must previously be open and started. When the
+** streams are suspended, an AVDT_SUSPEND_CFM_EVT is sent to
+** the application via the control callback function for
+** each stream.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_SuspendReq(UINT8 *p_handles, UINT8 num_handles)
+{
+ tAVDT_SCB *p_scb = NULL;
+ tAVDT_CCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+ int i;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SUSPEND_REQ);
+
+ if ((num_handles == 0) || (num_handles > AVDT_NUM_SEPS))
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+ else
+ {
+ /* verify handles */
+ for (i = 0; i < num_handles; i++)
+ {
+ if ((p_scb = avdt_scb_by_hdl(p_handles[i])) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ break;
+ }
+ }
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ if (p_scb->p_ccb == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ /* send event to ccb */
+ memcpy(evt.msg.multi.seid_list, p_handles, num_handles);
+ evt.msg.multi.num_seps = num_handles;
+ avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_API_SUSPEND_REQ_EVT, &evt);
+ }
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_CloseReq
+**
+** Description Close a stream endpoint. This stops the transfer of media
+** packets and closes the transport channel associated with
+** this stream endpoint. When the stream is closed, an
+** AVDT_CLOSE_CFM_EVT is sent to the application via the
+** control callback function for this handle.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_CloseReq(UINT8 handle)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CLOSE_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ /* send event to scb */
+ {
+ avdt_scb_event(p_scb, AVDT_SCB_API_CLOSE_REQ_EVT, NULL);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ReconfigReq
+**
+** Description Reconfigure a stream endpoint. This allows the application
+** to change the codec or content protection capabilities of
+** a stream endpoint after it has been opened. This function
+** can only be called if the stream is opened but not started
+** or if the stream has been suspended. When the procedure
+** is completed, an AVDT_RECONFIG_CFM_EVT is sent to the
+** application via the control callback function for this handle.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ReconfigReq(UINT8 handle, tAVDT_CFG *p_cfg)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_RECONFIG_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ /* force psc_mask to zero */
+ p_cfg->psc_mask = 0;
+
+ evt.msg.reconfig_cmd.p_cfg = p_cfg;
+ avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ReconfigRsp
+**
+** Description Respond to a reconfigure request from the peer device.
+** This function must be called if the application receives
+** an AVDT_RECONFIG_IND_EVT through its control callback.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ReconfigRsp(UINT8 handle, UINT8 label, UINT8 error_code, UINT8 category)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_RECONFIG_RSP);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.hdr.err_code = error_code;
+ evt.msg.hdr.err_param = category;
+ evt.msg.hdr.label = label;
+ avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_RSP_EVT, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_SecurityReq
+**
+** Description Send a security request to the peer device. When the
+** security procedure is completed, an AVDT_SECURITY_CFM_EVT
+** is sent to the application via the control callback function
+** for this handle. (Please note that AVDTP security procedures
+** are unrelated to Bluetooth link level security.)
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_SecurityReq(UINT8 handle, UINT8 *p_data, UINT16 len)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SECURITY_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.security_rsp.p_data = p_data;
+ evt.msg.security_rsp.len = len;
+ avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_SecurityRsp
+**
+** Description Respond to a security request from the peer device.
+** This function must be called if the application receives
+** an AVDT_SECURITY_IND_EVT through its control callback.
+** (Please note that AVDTP security procedures are unrelated
+** to Bluetooth link level security.)
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_SecurityRsp(UINT8 handle, UINT8 label, UINT8 error_code,
+ UINT8 *p_data, UINT16 len)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_SCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SECURITY_RSP);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ /* send event to scb */
+ else
+ {
+ evt.msg.security_rsp.hdr.err_code = error_code;
+ evt.msg.security_rsp.hdr.label = label;
+ evt.msg.security_rsp.p_data = p_data;
+ evt.msg.security_rsp.len = len;
+ avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_RSP_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_WriteReq
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC.
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteReq(). If the applications calls
+** AVDT_WriteReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+** or AVDT_START_IND_EVT.
+**
+** The application passes the packet using the BT_HDR structure.
+** This structure is described in section 2.1. The offset
+** field must be equal to or greater than AVDT_MEDIA_OFFSET.
+** This allows enough space in the buffer for the L2CAP and
+** AVDTP headers.
+**
+** The memory pointed to by p_pkt must be a GKI buffer
+** allocated by the application. This buffer will be freed
+** by the protocol stack; the application must not free
+** this buffer.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_WRITE_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ evt.apiwrite.p_buf = p_pkt;
+ evt.apiwrite.time_stamp = time_stamp;
+ evt.apiwrite.m_pt = m_pt;
+#if AVDT_MULTIPLEXING == TRUE
+ GKI_init_q (&evt.apiwrite.frag_q);
+#endif
+ avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_ConnectReq
+**
+** Description This function initiates an AVDTP signaling connection
+** to the peer device. When the connection is completed, an
+** AVDT_CONNECT_IND_EVT is sent to the application via its
+** control callback function. If the connection attempt fails
+** an AVDT_DISCONNECT_IND_EVT is sent. The security mask
+** parameter overrides the outgoing security mask set in
+** AVDT_Register().
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_ConnectReq(BD_ADDR bd_addr, UINT8 sec_mask, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_CCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_CONNECT_REQ);
+
+ /* find channel control block for this bd addr; if none, allocate one */
+ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
+ {
+ /* could not allocate channel control block */
+ result = AVDT_NO_RESOURCES;
+ }
+ }
+ else if (p_ccb->ll_opened == FALSE)
+ {
+ AVDT_TRACE_WARNING0("AVDT_ConnectReq: CCB LL is in the middle of opening");
+
+ /* ccb was already allocated for the incoming signalling. */
+ result = AVDT_BUSY;
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* send event to ccb */
+ evt.connect.p_cback = p_cback;
+ evt.connect.sec_mask = sec_mask;
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_CONNECT_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_DisconnectReq
+**
+** Description This function disconnect an AVDTP signaling connection
+** to the peer device. When disconnected an
+** AVDT_DISCONNECT_IND_EVT is sent to the application via its
+** control callback function.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_DisconnectReq(BD_ADDR bd_addr, tAVDT_CTRL_CBACK *p_cback)
+{
+ tAVDT_CCB *p_ccb = NULL;
+ UINT16 result = AVDT_SUCCESS;
+ tAVDT_CCB_EVT evt;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_DISCONNECT_REQ);
+
+
+ /* find channel control block for this bd addr; if none, error */
+ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+ {
+ result = AVDT_BAD_PARAMS;
+ }
+
+ if (result == AVDT_SUCCESS)
+ {
+ /* send event to ccb */
+ evt.disconnect.p_cback = p_cback;
+ avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCONNECT_REQ_EVT, &evt);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetL2CapChannel
+**
+** Description Get the L2CAP CID used by the handle.
+**
+** Returns CID if successful, otherwise 0.
+**
+*******************************************************************************/
+UINT16 AVDT_GetL2CapChannel(UINT8 handle)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_CCB *p_ccb;
+ UINT8 tcid;
+ UINT16 lcid = 0;
+
+ /* map handle to scb */
+ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
+ && ((p_ccb = p_scb->p_ccb) != NULL))
+ {
+ /* get tcid from type, scb */
+ tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
+
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ }
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GET_L2CAP_CHAN, BTTRC_PARAM_UINT16, lcid);
+
+ return (lcid);
+}
+
+/*******************************************************************************
+**
+** Function AVDT_GetSignalChannel
+**
+** Description Get the L2CAP CID used by the signal channel of the given handle.
+**
+** Returns CID if successful, otherwise 0.
+**
+*******************************************************************************/
+UINT16 AVDT_GetSignalChannel(UINT8 handle, BD_ADDR bd_addr)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_CCB *p_ccb;
+ UINT8 tcid = 0; /* tcid is always 0 for signal channel */
+ UINT16 lcid = 0;
+
+ /* map handle to scb */
+ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
+ && ((p_ccb = p_scb->p_ccb) != NULL))
+ {
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ }
+ else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) != NULL)
+ {
+ lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ }
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_GET_SIGNAL_CHAN, BTTRC_PARAM_UINT16, lcid);
+
+ return (lcid);
+}
+
+#if AVDT_MULTIPLEXING == TRUE
+/*******************************************************************************
+**
+** Function AVDT_WriteDataReq
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC.
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteDataReq(). If the applications calls
+** AVDT_WriteDataReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteDataReq() after it receives an
+** AVDT_START_CFM_EVT or AVDT_START_IND_EVT.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+AVDT_API extern UINT16 AVDT_WriteDataReq(UINT8 handle, UINT8 *p_data, UINT32 data_len,
+ UINT32 time_stamp, UINT8 m_pt, UINT8 marker)
+{
+
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API1(AVDT_TRACE_API_WRITE_DATA_REQ, BTTRC_PARAM_UINT32, data_len);
+
+ do
+ {
+ /* check length of media frame */
+ if(data_len > AVDT_MAX_MEDIA_SIZE)
+ {
+ result = AVDT_BAD_PARAMS;
+ break;
+ }
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ break;
+ }
+ AVDT_TRACE_WARNING1("mux_tsid_media:%d", p_scb->curr_cfg.mux_tsid_media);
+
+ if (p_scb->p_pkt != NULL
+ || p_scb->p_ccb == NULL
+ || !GKI_queue_is_empty(&p_scb->frag_q)
+ || p_scb->frag_off != 0
+ || p_scb->curr_cfg.mux_tsid_media == 0)
+ {
+ result = AVDT_ERR_BAD_STATE;
+ AVDT_TRACE_WARNING4("p_scb->p_pkt=%x, p_scb->p_ccb=%x, IsQueueEmpty=%x, p_scb->frag_off=%x",
+ p_scb->p_pkt, p_scb->p_ccb, GKI_queue_is_empty(&p_scb->frag_q), p_scb->frag_off);
+ break;
+ }
+ evt.apiwrite.p_buf = 0; /* it will indicate using of fragments queue frag_q */
+ /* create queue of media fragments */
+ GKI_init_q (&evt.apiwrite.frag_q);
+
+ /* compose fragments from media payload and put fragments into gueue */
+ avdt_scb_queue_frags(p_scb, &p_data, &data_len, &evt.apiwrite.frag_q);
+
+ if(GKI_queue_is_empty(&evt.apiwrite.frag_q))
+ {
+ AVDT_TRACE_WARNING0("AVDT_WriteDataReq out of GKI buffers");
+ result = AVDT_ERR_RESOURCE;
+ break;
+ }
+ evt.apiwrite.data_len = data_len;
+ evt.apiwrite.p_data = p_data;
+
+ /* process the fragments queue */
+ evt.apiwrite.time_stamp = time_stamp;
+ evt.apiwrite.m_pt = m_pt | (marker<<7);
+ avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
+ } while (0);
+
+#if (BT_USE_TRACES == TRUE)
+ if(result != AVDT_SUCCESS)
+ {
+ AVDT_TRACE_WARNING1("*** AVDT_WriteDataReq failed result=%d",result);
+ }
+#endif
+ return result;
+}
+#endif
+
+#if AVDT_MULTIPLEXING == TRUE
+/*******************************************************************************
+**
+** Function AVDT_SetMediaBuf
+**
+** Description Assigns buffer for media packets or forbids using of assigned
+** buffer if argument p_buf is NULL. This function can only
+** be called if the stream is a SNK.
+**
+** AVDTP uses this buffer to reassemble fragmented media packets.
+** When AVDTP receives a complete media packet, it calls the
+** p_media_cback assigned by AVDT_CreateStream().
+** This function can be called during callback to assign a
+** different buffer for next media packet or can leave the current
+** buffer for next packet.
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+AVDT_API extern UINT16 AVDT_SetMediaBuf(UINT8 handle, UINT8 *p_buf, UINT32 buf_len)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SET_MEDIABUF);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ if(p_buf && p_scb->cs.p_media_cback == NULL)
+ result = AVDT_NO_RESOURCES;
+ else
+ {
+ p_scb->p_media_buf = p_buf;
+ p_scb->media_buf_len = buf_len;
+ }
+ }
+
+ return result;
+}
+#endif
+
+#if AVDT_REPORTING == TRUE
+/*******************************************************************************
+**
+** Function AVDT_SendReport
+**
+** Description
+**
+**
+**
+** Returns
+**
+*******************************************************************************/
+UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
+ tAVDT_REPORT_DATA *p_data)
+{
+ tAVDT_SCB *p_scb;
+ UINT16 result = AVDT_BAD_PARAMS;
+ BT_HDR *p_pkt;
+ tAVDT_TC_TBL *p_tbl;
+ UINT8 *p, *plen, *pm1, *p_end;
+#if AVDT_MULTIPLEXING == TRUE
+ UINT8 *p_al, u;
+#endif
+ UINT32 ssrc;
+ UINT16 len;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_SEND_REPORT);
+
+ /* map handle to scb && verify parameters */
+ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
+ && (p_scb->p_ccb != NULL)
+ && (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) ||
+ ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) ||
+ (type == AVDT_RTCP_PT_SDES)) )
+ {
+ result = AVDT_NO_RESOURCES;
+
+ /* build SR - assume fit in one packet */
+ p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb);
+ if((p_tbl->state == AVDT_AD_ST_OPEN) &&
+ (p_pkt = (BT_HDR *)GKI_getbuf(p_tbl->peer_mtu)) != NULL)
+ {
+ p_pkt->offset = L2CAP_MIN_OFFSET;
+ p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+#if AVDT_MULTIPLEXING == TRUE
+ if(p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX)
+ {
+ /* Adaptation Layer header later */
+ p_al = p;
+ p += 2;
+ }
+#endif
+ pm1 = p;
+ *p++ = AVDT_MEDIA_OCTET1 | 1;
+ *p++ = type;
+ /* save the location for length */
+ plen = p;
+ p+= 2;
+ ssrc = avdt_scb_gen_ssrc(p_scb);
+ UINT32_TO_BE_STREAM(p, ssrc);
+
+ switch(type)
+ {
+ case AVDT_RTCP_PT_SR: /* Sender Report */
+ *pm1 = AVDT_MEDIA_OCTET1;
+ UINT32_TO_BE_STREAM(p, p_data->sr.ntp_sec);
+ UINT32_TO_BE_STREAM(p, p_data->sr.ntp_frac);
+ UINT32_TO_BE_STREAM(p, p_data->sr.rtp_time);
+ UINT32_TO_BE_STREAM(p, p_data->sr.pkt_count);
+ UINT32_TO_BE_STREAM(p, p_data->sr.octet_count);
+ break;
+
+ case AVDT_RTCP_PT_RR: /* Receiver Report */
+ *p++ = p_data->rr.frag_lost;
+ AVDT_TRACE_API1("packet_lost: %d", p_data->rr.packet_lost);
+ p_data->rr.packet_lost &= 0xFFFFFF;
+ AVDT_TRACE_API1("packet_lost: %d", p_data->rr.packet_lost);
+ UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost);
+ UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd);
+ UINT32_TO_BE_STREAM(p, p_data->rr.jitter);
+ UINT32_TO_BE_STREAM(p, p_data->rr.lsr);
+ UINT32_TO_BE_STREAM(p, p_data->rr.dlsr);
+ break;
+
+ case AVDT_RTCP_PT_SDES: /* Source Description */
+ *p++ = AVDT_RTCP_SDES_CNAME;
+ len = strlen((char *)p_data->cname);
+ if(len > AVDT_MAX_CNAME_SIZE)
+ len = AVDT_MAX_CNAME_SIZE;
+ *p++ = (UINT8)len;
+ BCM_STRNCPY_S((char *)p, len+1, (char *)p_data->cname, len+1);
+ p += len;
+ break;
+ }
+ p_end = p;
+ len = p - pm1 - 1;
+ UINT16_TO_BE_STREAM(plen, len);
+
+#if AVDT_MULTIPLEXING == TRUE
+ if(p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX)
+ {
+ /* Adaptation Layer header */
+ p = p_al;
+ len++;
+ UINT16_TO_BE_STREAM(p_al, len );
+ /* TSID, no-fragment bit and coding of length(9-bit length field) */
+ u = *p;
+ *p = (p_scb->curr_cfg.mux_tsid_report<<3) | AVDT_ALH_LCODE_9BITM0;
+ if(u)
+ *p |= AVDT_ALH_LCODE_9BITM1;
+ }
+#endif
+
+ /* set the actual payload length */
+ p_pkt->len = p_end - p;
+ /* send the packet */
+ if(L2CAP_DW_FAILED != avdt_ad_write_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, p_pkt))
+ result = AVDT_SUCCESS;
+ }
+ }
+
+ return result;
+}
+#endif
+
+/******************************************************************************
+**
+** Function AVDT_SetTraceLevel
+**
+** Description Sets the trace level for AVDT. If 0xff is passed, the
+** current trace level is returned.
+**
+** Input Parameters:
+** new_level: The level to set the AVDT tracing to:
+** 0xff-returns the current setting.
+** 0-turns off tracing.
+** >= 1-Errors.
+** >= 2-Warnings.
+** >= 3-APIs.
+** >= 4-Events.
+** >= 5-Debug.
+**
+** Returns The new trace level or current trace level if
+** the input parameter is 0xff.
+**
+******************************************************************************/
+UINT8 AVDT_SetTraceLevel (UINT8 new_level)
+{
+ if (new_level != 0xFF)
+ avdt_cb.trace_level = new_level;
+
+ return (avdt_cb.trace_level);
+}
+