* Copyright (C) 2021 Huawei Device Co., Ltd.
* 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.
*/
#include "avctp_br_act.h"
#include "avctp_st.h"
#include "avctp_conn.h"
#include "avctp_gap.h"
#include "avctp_ctrl.h"
#include "avctp_ctrl_act.h"
#include "avctp_br.h"
#include "l2cap_if.h"
#include "log.h"
* Globle Data Define
****************************************************************************/
* Function AvctCbBrChConn
* Description This function is called to Open browser channel link.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChConn(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
GAP_Service serviceId;
if (g_avctMng.role == AVCT_CT) {
serviceId = AVRCP_CT_BROWSING;
} else {
serviceId = AVRCP_TG_BROWSING;
}
AvctRequestSecurity(cbDev, serviceId, AVCT_BR_PSM);
return AVCT_SUCCESS;
}
* Function AvctCbBrChConnFail
* Description This function is called when Open browser channel link failed.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChConnFail(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConn *cbConn = NULL;
for (uint8_t i = 0; i < AVCT_MAX_CONNECTS; i++) {
cbConn = &g_avctMng.cbConn[i];
if ((cbConn->status == AVCT_CONN_BIND) && (cbConn->cbDev == cbDev)) {
if (cbDev->chLink & AVCT_ALLOC_BR) {
AvctCbConnEvtCallback(cbConn, AVCT_BR_CONNECT_CFM_EVT, data->result, &(cbConn->cbDev->peerAddr));
}
}
}
AvctCbChDealloc(&(cbDev->cbBr));
cbDev->chLink &= ~AVCT_ALLOC_BR;
return AVCT_SUCCESS;
}
* Function AvctCbBrChBind
* Description This function is called when the browser channel had been
* created, only bind it.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChBind(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConnEvtCallback(data->cbConn, AVCT_BR_CONNECT_CFM_EVT, AVCT_SUCCESS, &(data->cbConn->cbDev->peerAddr));
return AVCT_SUCCESS;
}
* Function AvctCbBrChBindFail
* Description This function is called when the browser channel had been
* created, try to bind it failed.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChBindFail(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConnEvtCallback(data->cbConn, AVCT_BR_CONNECT_CFM_EVT, AVCT_FAILED, &(data->cbConn->cbDev->peerAddr));
return AVCT_SUCCESS;
}
* Function AvctCbBrChDisconn
* Description This function is called to disconnect the browser channel .
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChDisconn(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
L2CIF_DisconnectionReq(cbDev->cbBr->chId, NULL);
return AVCT_SUCCESS;
}
* Function AvctCbBrChUnbind
* Description This function is called to unbind and disconnect the browser
* channel.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChUnbind(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConnEvtCallback(data->cbConn, AVCT_BR_DISCONNECT_CFM_EVT, AVCT_SUCCESS, &(data->cbConn->cbDev->peerAddr));
return AVCT_SUCCESS;
}
* Function AvctCbBrChCheckDisconn
* Description This function is called to check if the connect is the last one which is using the br channel.
* If it is the last one, disconnect the channel.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChCheckDisconn(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
if (cbDev->bindCnt > 1) {
AvctCbBrChUnbind(cbDev, data);
} else {
if (cbDev->cbBr != NULL) {
AvctCbBrEvt(cbDev, AVCT_DISCONN_EVT, data);
}
}
return AVCT_SUCCESS;
}
* Function AvctCbBrChConnInd
* Description This function is called when receive connect ind.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChConnInd(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConn *cbConn = NULL;
bool bind = false;
for (uint8_t i = 0; i < AVCT_MAX_CONNECTS; i++) {
cbConn = &g_avctMng.cbConn[i];
if ((cbConn->status == AVCT_CONN_BIND) && (cbConn->cbDev == cbDev)) {
bind = true;
if (cbDev->cbBr->ia == AVCT_ACPT) {
AvctCbConnEvtCallback(cbConn, AVCT_BR_CONNECT_IND_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
} else {
AvctCbConnEvtCallback(cbConn, AVCT_BR_CONNECT_CFM_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
}
}
}
if (!bind) {
AvctCbBrEvt(cbDev, AVCT_DISCONN_EVT, data);
}
return AVCT_SUCCESS;
}
* Function AvctCbBrChCloseInd
* Description This function is called when receive close ind.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChCloseInd(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConn *cbConn = NULL;
for (uint8_t i = 0; i < AVCT_MAX_CONNECTS; i++) {
if (g_avctMng.cbConn[i].cbDev == cbDev) {
cbConn = &g_avctMng.cbConn[i];
AvctCbConnEvtCallback(cbConn, AVCT_BR_DISCONNECT_IND_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
}
}
AvctCbChDealloc(&(cbDev->cbBr));
cbDev->chLink &= ~AVCT_ALLOC_BR;
return AVCT_SUCCESS;
}
* Function AvctCbBrChCloseCfm
* Description This function is called when receive close confirm.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChCloseCfm(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConn *cbConn = NULL;
for (uint8_t i = 0; i < AVCT_MAX_CONNECTS; i++) {
cbConn = &g_avctMng.cbConn[i];
if ((cbConn->status == AVCT_CONN_BIND) && (cbConn->cbDev == cbDev)) {
AvctCbConnEvtCallback(cbConn, AVCT_BR_DISCONNECT_CFM_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
}
}
AvctCbChDealloc(&(cbDev->cbBr));
cbDev->chLink &= ~AVCT_ALLOC_BR;
return AVCT_SUCCESS;
}
* Function AvctCbBrChBusyInd
* Description This function is called when receive channel busy.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrChBusyInd(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
AvctCbConn *cbConn = NULL;
uint8_t event = AVCT_BR_CHANNEL_UNBUSY_EVT;
if (data->result == AVCT_BUSY_ST) {
event = AVCT_BR_CHANNEL_BUSY_EVT;
}
for (uint8_t i = 0; i < AVCT_MAX_CONNECTS; i++) {
cbConn = &g_avctMng.cbConn[i];
if ((cbConn->status == AVCT_CONN_BIND) && (cbConn->cbDev == cbDev)) {
AvctCbConnEvtCallback(cbConn, event, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
}
}
return AVCT_SUCCESS;
}
* Function AvctCbBrDiscardMsg
* Description This function is called when discard received message.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrDiscardMsg(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
return AVCT_FAILED;
}
* Function AvctCbBrSendMsg
* Description This function is called to send message.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrSendMsg(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
uint16_t ret = AVCT_SUCCESS;
AvctTxMsg txMsg = data->txMsg;
AvctCbCh *cbBr = cbDev->cbBr;
Packet *pkt = PacketInheritMalloc(txMsg.buf, AVCT_PKG_HDR_LEN_SINGLE, 0);
if (pkt == NULL) {
LOG_ERROR("[AVCT] %{public}s: PacketInheritMalloc failed!", __func__);
ret = AVCT_ERR_NO_RESOURCES;
} else {
AvctMakeSignleMsgHead(pkt, txMsg.label, txMsg.cr, txMsg.cbConn->connParam.pid);
int lRet = L2CIF_SendData(cbBr->chId, pkt, NULL);
if (lRet) {
LOG_WARN("[AVCT] %{public}s:L2CIF_SendData failed.error is %{public}d", __func__, lRet);
}
PacketFree(pkt);
}
return ret;
}
* Function AvctCbBrRevMsg
* Description This function is called when received message.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrRevMsg(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
uint16_t ret = AVCT_SUCCESS;
uint8_t sHead[AVCT_PKG_HDR_LEN_SINGLE] = {0};
Packet *pkt = AvctMsgAsmbl(cbDev->cbBr, data->buf);
if (pkt == NULL) {
return ret;
}
PacketExtractHead(pkt, sHead, AVCT_PKG_HDR_LEN_SINGLE);
uint8_t label;
uint8_t cr;
uint8_t ipid;
uint16_t pid;
AVCT_PARSE_SIGNLE_HDR(sHead, label, cr, ipid, pid);
if (ipid == 1) {
LOG_WARN("[AVCT] %{public}s: Invalid ipid!", __func__);
return ret;
}
uint8_t conId = 255;
for (uint8_t i = 0; i <= AVCT_MAX_CONNECTS;) {
AvctCbConn *cbConn = AvctGetCbConidConn(cbDev, pid, i, &conId);
if ((cbConn != NULL) && (cbConn->connParam.msgCallback != NULL)) {
(*cbConn->connParam.msgCallback)(cbConn->connId, label, cr, AVCT_DATA_BR, pkt, cbConn->connParam.context);
i = conId + 1;
continue;
} else if (conId < AVCT_MAX_CONNECTS) {
return ret;
}
break;
}
if (cr == AVCT_CMD) {
Packet *sndPkg = PacketMalloc(AVCT_PKG_HDR_LEN_SINGLE, 0, 0);
if (sndPkg == NULL) {
LOG_ERROR("[AVCT] %{public}s: PacketMalloc failed!", __func__);
ret = AVCT_ERR_NO_RESOURCES;
} else {
AvctMakeRejMsgHead(sndPkg, label, pid);
int lRet = L2CIF_SendData(cbDev->cbBr->chId, sndPkg, NULL);
if (lRet) {
LOG_WARN("[AVCT] %{public}s:L2CIF_SendData failed.error is %{public}d", __func__, lRet);
}
PacketFree(sndPkg);
}
}
return ret;
}
* Function AvctCbBrDiscardRevMsg
* Description This function is called to discard received message.
* Param[in] *cbDev The point to the device block.
* Param[in] *data Event data
* Return AVCT_SUCCESS. Others: Fail
*/
uint16_t AvctCbBrDiscardRevMsg(AvctCbDev *cbDev, const AvctEvtData *data)
{
LOG_DEBUG("[AVCT] %{public}s:", __func__);
return AVCT_SUCCESS;
}