summaryrefslogtreecommitdiffstats
path: root/stack/avct/avct_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'stack/avct/avct_api.c')
-rw-r--r--stack/avct/avct_api.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/stack/avct/avct_api.c b/stack/avct/avct_api.c
new file mode 100644
index 0000000..7e37a90
--- /dev/null
+++ b/stack/avct/avct_api.c
@@ -0,0 +1,465 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-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 control transport protocol.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_target.h"
+#include "gki.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#include "btm_api.h"
+#include "avct_api.h"
+#include "avct_int.h"
+
+/* Control block for AVCT */
+#if AVCT_DYNAMIC_MEMORY == FALSE
+tAVCT_CB avct_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function AVCT_Register
+**
+** Description This is the system level registration function for the
+** AVCTP protocol. This function initializes AVCTP and
+** prepares the protocol stack for its use. This function
+** must be called once by the system or platform using AVCTP
+** before the other functions of the API an be used.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask)
+{
+ AVCT_TRACE_API0("AVCT_Register");
+
+ /* register PSM with L2CAP */
+ L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_appl);
+
+ /* set security level */
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
+
+ /* initialize AVCTP data structures */
+ memset(&avct_cb, 0, sizeof(tAVCT_CB));
+
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ /* Include the browsing channel which uses eFCR */
+ L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_br_appl);
+
+ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
+ BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
+
+ if (mtu_br < AVCT_MIN_BROWSE_MTU)
+ mtu_br = AVCT_MIN_BROWSE_MTU;
+ avct_cb.mtu_br = mtu_br;
+#endif
+
+#if defined(AVCT_INITIAL_TRACE_LEVEL)
+ avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
+#else
+ avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+
+ if (mtu < AVCT_MIN_CONTROL_MTU)
+ mtu = AVCT_MIN_CONTROL_MTU;
+ /* store mtu */
+ avct_cb.mtu = mtu;
+}
+
+/*******************************************************************************
+**
+** Function AVCT_Deregister
+**
+** Description This function is called to deregister use AVCTP protocol.
+** It is called when AVCTP is no longer being used by any
+** application in the system. Before this function can be
+** called, all connections must be removed with
+** AVCT_RemoveConn().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void AVCT_Deregister(void)
+{
+ AVCT_TRACE_API0("AVCT_Deregister");
+
+ /* deregister PSM with L2CAP */
+ L2CA_Deregister(AVCT_PSM);
+}
+
+/*******************************************************************************
+**
+** Function AVCT_CreateConn
+**
+** Description Create an AVCTP connection. There are two types of
+** connections, initiator and acceptor, as determined by
+** the p_cc->role parameter. When this function is called to
+** create an initiator connection, an AVCTP connection to
+** the peer device is initiated if one does not already exist.
+** If an acceptor connection is created, the connection waits
+** passively for an incoming AVCTP connection from a peer device.
+**
+**
+** Returns AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_CreateConn(UINT8 *p_handle, tAVCT_CC *p_cc, BD_ADDR peer_addr)
+{
+ UINT16 result = AVCT_SUCCESS;
+ tAVCT_CCB *p_ccb;
+ tAVCT_LCB *p_lcb;
+
+ AVCT_TRACE_API2("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control);
+
+ /* Allocate ccb; if no ccbs, return failure */
+ if ((p_ccb = avct_ccb_alloc(p_cc)) == NULL)
+ {
+ result = AVCT_NO_RESOURCES;
+ }
+ else
+ {
+ /* get handle */
+ *p_handle = avct_ccb_to_idx(p_ccb);
+
+ /* if initiator connection */
+ if (p_cc->role == AVCT_INT)
+ {
+ /* find link; if none allocate a new one */
+ if ((p_lcb = avct_lcb_by_bd(peer_addr)) == NULL)
+ {
+ if ((p_lcb = avct_lcb_alloc(peer_addr)) == NULL)
+ {
+ /* no link resources; free ccb as well */
+ avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
+ result = AVCT_NO_RESOURCES;
+ }
+ }
+ /* check if PID already in use */
+ else if (avct_lcb_has_pid(p_lcb, p_cc->pid))
+ {
+ avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
+ result = AVCT_PID_IN_USE;
+ }
+
+ if (result == AVCT_SUCCESS)
+ {
+ /* bind lcb to ccb */
+ p_ccb->p_lcb = p_lcb;
+ AVCT_TRACE_DEBUG1("ch_state: %d", p_lcb->ch_state);
+ avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+ }
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVCT_RemoveConn
+**
+** Description Remove an AVCTP connection. This function is called when
+** the application is no longer using a connection. If this
+** is the last connection to a peer the L2CAP channel for AVCTP
+** will be closed.
+**
+**
+** Returns AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_RemoveConn(UINT8 handle)
+{
+ UINT16 result = AVCT_SUCCESS;
+ tAVCT_CCB *p_ccb;
+
+ AVCT_TRACE_API0("AVCT_RemoveConn");
+
+ /* map handle to ccb */
+ if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+ {
+ result = AVCT_BAD_HANDLE;
+ }
+ /* if connection not bound to lcb, dealloc */
+ else if (p_ccb->p_lcb == NULL)
+ {
+ avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
+ }
+ /* send unbind event to lcb */
+ else
+ {
+ avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function AVCT_CreateBrowse
+**
+** Description Create an AVCTP Browse channel. There are two types of
+** connections, initiator and acceptor, as determined by
+** the role parameter. When this function is called to
+** create an initiator connection, the Browse channel to
+** the peer device is initiated if one does not already exist.
+** If an acceptor connection is created, the connection waits
+** passively for an incoming AVCTP connection from a peer device.
+**
+**
+** Returns AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_CreateBrowse (UINT8 handle, UINT8 role)
+{
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ UINT16 result = AVCT_SUCCESS;
+ tAVCT_CCB *p_ccb;
+ tAVCT_BCB *p_bcb;
+ int index;
+
+ AVCT_TRACE_API1("AVCT_CreateBrowse: %d", role);
+
+ /* map handle to ccb */
+ if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+ {
+ return AVCT_BAD_HANDLE;
+ }
+ else
+ {
+ /* mark this CCB as supporting browsing channel */
+ if ((p_ccb->allocated & AVCT_ALOC_BCB) == 0)
+ {
+ p_ccb->allocated |= AVCT_ALOC_BCB;
+ }
+ }
+
+ /* if initiator connection */
+ if (role == AVCT_INT)
+ {
+ /* the link control block must exist before this function is called as INT. */
+ if (p_ccb->p_lcb == NULL)
+ {
+ result = AVCT_NOT_OPEN;
+ }
+ else
+ {
+ /* find link; if none allocate a new one */
+ index = p_ccb->p_lcb->allocated;
+ if (index > AVCT_NUM_LINKS)
+ {
+ result = AVCT_BAD_HANDLE;
+ }
+ else
+ {
+ p_bcb = &avct_cb.bcb[index - 1];
+ p_bcb->allocated = index;
+ }
+ }
+
+ if (result == AVCT_SUCCESS)
+ {
+ /* bind bcb to ccb */
+ p_ccb->p_bcb = p_bcb;
+ AVCT_TRACE_DEBUG1("ch_state: %d", p_bcb->ch_state);
+ avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+ }
+ }
+
+ return result;
+#else
+ return AVCT_NO_RESOURCES;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function AVCT_RemoveBrowse
+**
+** Description Remove an AVCTP Browse channel. This function is called when
+** the application is no longer using a connection. If this
+** is the last connection to a peer the L2CAP channel for AVCTP
+** will be closed.
+**
+**
+** Returns AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_RemoveBrowse (UINT8 handle)
+{
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ UINT16 result = AVCT_SUCCESS;
+ tAVCT_CCB *p_ccb;
+
+ AVCT_TRACE_API0("AVCT_RemoveBrowse");
+
+ /* map handle to ccb */
+ if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+ {
+ result = AVCT_BAD_HANDLE;
+ }
+ else if (p_ccb->p_bcb != NULL)
+ /* send unbind event to bcb */
+ {
+ avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
+ }
+ return result;
+#else
+ return AVCT_NO_RESOURCES;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function AVCT_GetBrowseMtu
+**
+** Description Get the peer_mtu for the AVCTP Browse channel of the given
+** connection.
+**
+** Returns the peer browsing channel MTU.
+**
+*******************************************************************************/
+UINT16 AVCT_GetBrowseMtu (UINT8 handle)
+{
+ UINT16 peer_mtu = AVCT_MIN_BROWSE_MTU;
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ tAVCT_CCB *p_ccb;
+
+ if ((p_ccb = avct_ccb_by_idx(handle)) != NULL && p_ccb->p_bcb != NULL)
+ {
+ peer_mtu = p_ccb->p_bcb->peer_mtu;
+ }
+#endif
+ return peer_mtu;
+}
+
+/*******************************************************************************
+**
+** Function AVCT_GetPeerMtu
+**
+** Description Get the peer_mtu for the AVCTP channel of the given
+** connection.
+**
+** Returns the peer MTU size.
+**
+*******************************************************************************/
+UINT16 AVCT_GetPeerMtu (UINT8 handle)
+{
+ UINT16 peer_mtu = L2CAP_DEFAULT_MTU;
+ tAVCT_CCB *p_ccb;
+
+ /* map handle to ccb */
+ if ((p_ccb = avct_ccb_by_idx(handle)) != NULL)
+ {
+ if (p_ccb->p_lcb)
+ {
+ peer_mtu = p_ccb->p_lcb->peer_mtu;
+ }
+ }
+
+ return peer_mtu;
+}
+
+/*******************************************************************************
+**
+** Function AVCT_MsgReq
+**
+** Description Send an AVCTP message to a peer device. In calling
+** AVCT_MsgReq(), the application should keep track of the
+** congestion state of AVCTP as communicated with events
+** AVCT_CONG_IND_EVT and AVCT_UNCONG_IND_EVT. If the
+** application calls AVCT_MsgReq() when AVCTP is congested
+** the message may be discarded. The application may make its
+** first call to AVCT_MsgReq() after it receives an
+** AVCT_CONNECT_CFM_EVT or AVCT_CONNECT_IND_EVT on control channel or
+** AVCT_BROWSE_CONN_CFM_EVT or AVCT_BROWSE_CONN_IND_EVT on browsing channel.
+**
+** p_msg->layer_specific must be set to
+** AVCT_DATA_CTRL for control channel traffic;
+** AVCT_DATA_BROWSE for for browse channel traffic.
+**
+** Returns AVCT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg)
+{
+ UINT16 result = AVCT_SUCCESS;
+ tAVCT_CCB *p_ccb;
+ tAVCT_UL_MSG ul_msg;
+
+ AVCT_TRACE_API0("AVCT_MsgReq");
+
+ /* verify p_msg parameter */
+ if (p_msg == NULL)
+ {
+ return AVCT_NO_RESOURCES;
+ }
+ AVCT_TRACE_API1("len: %d", p_msg->len);
+
+ /* map handle to ccb */
+ if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
+ {
+ result = AVCT_BAD_HANDLE;
+ GKI_freebuf(p_msg);
+ }
+ /* verify channel is bound to link */
+ else if (p_ccb->p_lcb == NULL)
+ {
+ result = AVCT_NOT_OPEN;
+ GKI_freebuf(p_msg);
+ }
+
+ if (result == AVCT_SUCCESS)
+ {
+ ul_msg.p_buf = p_msg;
+ ul_msg.p_ccb = p_ccb;
+ ul_msg.label = label;
+ ul_msg.cr = cr;
+
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ /* send msg event to bcb */
+ if (p_msg->layer_specific == AVCT_DATA_BROWSE)
+ {
+ if (p_ccb->p_bcb == NULL && (p_ccb->allocated & AVCT_ALOC_BCB) == 0)
+ {
+ /* BCB channel is not open and not allocated */
+ result = AVCT_BAD_HANDLE;
+ GKI_freebuf(p_msg);
+ }
+ else
+ {
+ p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
+ avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+ }
+ }
+ /* send msg event to lcb */
+ else
+#endif
+ {
+ avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+ }
+ }
+ return result;
+}
+