| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- /******************************************************************************
- *
- * 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 "stack/bt_types.h"
- #include "common/bt_target.h"
- #include "common/bt_defs.h"
- #include "stack/l2c_api.h"
- #include "stack/l2cdefs.h"
- #include "stack/btm_api.h"
- #include "stack/avct_api.h"
- #include "avct_int.h"
- #include "osi/allocator.h"
- #if (defined(AVCT_INCLUDED) && AVCT_INCLUDED == TRUE)
- /* Control block for AVCT */
- #if AVCT_DYNAMIC_MEMORY == FALSE
- tAVCT_CB avct_cb;
- #else
- tAVCT_CB *avct_cb_ptr;
- #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)
- {
- UNUSED(mtu_br);
- AVCT_TRACE_API("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_API("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_API("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_DEBUG("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_API("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_API("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) || (p_ccb->p_lcb->allocated == 0)) {
- 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_DEBUG("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
- UNUSED(handle);
- UNUSED(role);
- 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_API("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
- UNUSED(handle);
- 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;
- }
- #else
- UNUSED(handle);
- #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_API("AVCT_MsgReq");
- /* verify p_msg parameter */
- if (p_msg == NULL) {
- return AVCT_NO_RESOURCES;
- }
- AVCT_TRACE_API("len: %d", p_msg->len);
- /* map handle to ccb */
- if ((p_ccb = avct_ccb_by_idx(handle)) == NULL) {
- result = AVCT_BAD_HANDLE;
- osi_free(p_msg);
- }
- /* verify channel is bound to link */
- else if (p_ccb->p_lcb == NULL) {
- result = AVCT_NOT_OPEN;
- osi_free(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;
- osi_free(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;
- }
- #endif /* #if (defined(AVCT_INCLUDED) && AVCT_INCLUDED == TRUE) */
|