* 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_gap.h"
#include "avctp_br_l2cap.h"
#include "avctp_ctrl.h"
#include "avctp_ctrl_l2cap.h"
#include "avctp_st.h"
#include "log.h"
#include "securec.h"
* Globle Data Define
****************************************************************************/
* Function
****************************************************************************/
* Function AvctSecurityResultCallback
* Description This function is the callback from gap to check service security .
* Param[in] result The check result.
* Param[in] channelId The service info.
* Param[in] context The connection control block.
* Return void
*/
void AvctSecurityResultCallback(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context)
{
LOG_INFO("[AVCT] %{public}s:result(%hu) ", __func__, result);
AvctSecurityResultCallbackTskParam *param = malloc(sizeof(AvctSecurityResultCallbackTskParam));
if (param == NULL) {
LOG_ERROR("[AVCT] %{public}s: memory malloc failed", __func__);
return;
}
(void)memset_s(param, sizeof(AvctSecurityResultCallbackTskParam), 0, sizeof(AvctSecurityResultCallbackTskParam));
param->result = result;
(void)memcpy_s(¶m->serviceInfo, sizeof(GapServiceSecurityInfo), &serviceInfo, sizeof(GapServiceSecurityInfo));
param->context = context;
if (AvctAsyncProcess(AvctSecurityResultCallbackTsk, param)) {
free(param);
}
return;
}
void AvctSecurityResultCallbackTsk(void *context)
{
AvctSecurityResultCallbackTskParam *param = (AvctSecurityResultCallbackTskParam *)context;
AvctSecurityResult(param->result, param->serviceInfo, param->context);
free(param);
return;
}
void AvctSecurityResult(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context)
{
LOG_DEBUG("[AVCT] %{public}s:result(%hu) ", __func__, result);
AvctCbDev *cbDev = ((AvctCbDev *)context);
AvctCbCh *cbCh = NULL;
if (result != GAP_SUCCESS) {
AvctEvtData evtData;
evtData.result = AVCT_FAILED;
AvctCbCtrlEvt(cbDev, AVCT_REV_DISCONN_EVT, &evtData);
return;
}
LOG_DEBUG("[AVCT] %{public}s: channelId.l2capPsm is (%x),serviceId(%{public}d),chlink(%hhu) ",
__func__,
serviceInfo.channelId.l2capPsm,
serviceInfo.serviceId,
cbDev->chLink);
if ((serviceInfo.serviceId == AVRCP_CT) || (serviceInfo.serviceId == AVRCP_TG)) {
if (cbDev->chLink & AVCT_ALLOC_CTRL) {
cbCh = cbDev->cbCtrl;
cbCh->chState = AVCT_CH_CONN;
if (L2CIF_ConnectReq(&(cbDev->peerAddr), AVCT_PSM, AVCT_PSM, NULL, AvctCtrlL2CIFConnectReqCallback)) {
LOG_ERROR("[AVCT] %{public}s:L2CIF_ConnectReq failed.", __func__);
}
} else {
LOG_ERROR("[AVCT] %{public}s: Ctrl channel not allocated, Can't connect!", __func__);
}
} else if ((serviceInfo.serviceId == AVRCP_CT_BROWSING) || (serviceInfo.serviceId == AVRCP_TG_BROWSING)) {
if (cbDev->chLink & AVCT_ALLOC_BR) {
cbCh = cbDev->cbBr;
cbCh->chState = AVCT_CH_CONN;
if (L2CIF_ConnectReq(&(cbDev->peerAddr), AVCT_BR_PSM, AVCT_BR_PSM, NULL, AvctBrwL2CIFConnectReqCallback)) {
LOG_ERROR("[AVCT] %{public}s:L2CIF_ConnectReq failed.", __func__);
}
} else {
LOG_ERROR("[AVCT] %{public}s: Br channel not allocated, Can't connect!", __func__);
}
} else {
LOG_WARN("[AVCT] %{public}s: ServiceID(%{public}d) from GAP is error!", __func__, serviceInfo.serviceId);
}
return;
}
* Function AvctRevConnSecurityResultCallback
* Description GAP security request check callback func.
* Param[in] result Check result.
* Param[in] channelId Channel Id.
* Param[out] context
* Return void
*/
void AvctRevConnSecurityResultCallback(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context)
{
LOG_INFO("[AVCT] %{public}s:result(%hu)", __func__, result);
AvctRevConnSecurityResultCallbackTskParam *param = malloc(sizeof(AvctRevConnSecurityResultCallbackTskParam));
if (param == NULL) {
LOG_ERROR("[AVCT] %{public}s: memory malloc failed", __func__);
return;
}
(void)memset_s(
param, sizeof(AvctRevConnSecurityResultCallbackTskParam), 0, sizeof(AvctRevConnSecurityResultCallbackTskParam));
param->result = result;
(void)memcpy_s(¶m->serviceInfo, sizeof(GapServiceSecurityInfo), &serviceInfo, sizeof(GapServiceSecurityInfo));
param->context = context;
if (AvctAsyncProcess(AvctRevConnSecurityResultCallbackTsk, param)) {
free((AvctRevConnParam *)param->context);
free(param);
}
return;
}
void AvctRevConnSecurityResultCallbackTsk(void *context)
{
AvctRevConnSecurityResultCallbackTskParam *param = (AvctRevConnSecurityResultCallbackTskParam *)context;
AvctRevConnSecurityResult(param->result, param->serviceInfo, param->context);
free(param);
return;
}
void AvctRevConnSecurityResult(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context)
{
LOG_DEBUG("[AVCT] %{public}s:result(%hu)", __func__, result);
AvctRevConnParam *param = (AvctRevConnParam *)context;
if (result != GAP_SUCCESS) {
result = L2CAP_SECURITY_BLOCK;
L2CIF_ConnectRsp(param->lcid, param->id, result, 0, NULL);
} else {
if ((serviceInfo.serviceId == AVRCP_CT) || (serviceInfo.serviceId == AVRCP_TG)) {
AvctRecvConnectionReqAct(&(param->addr), param->aclHandle, param->lcid, param->id, param->psm);
} else if ((serviceInfo.serviceId == AVRCP_CT_BROWSING) || (serviceInfo.serviceId == AVRCP_TG_BROWSING)) {
AvctBrRecvConnectionReqAct(&(param->addr), param->aclHandle, param->lcid, param->id, param->psm);
} else {
LOG_WARN("[AVCT] %{public}s: ServiceID(%{public}d) from GAP is error!", __func__, serviceInfo.serviceId);
}
}
if (param != NULL) {
free(param);
param = NULL;
}
return;
}
* Function AvctRequestSecurity
* Description This function is called to Open control channel link.
* Param[in] *cbDev The point to the device block.
* Param[in] serviceId seviced id defined by GAP
* Param[in] psm
* Return AVCT_SUCCESS. Others: Fail
*/
void AvctRequestSecurity(const AvctCbDev *cbDev, GAP_Service serviceId, uint16_t psm)
{
LOG_DEBUG("[AVCT] %{public}s:Sevcieid(0x%x),psm(0x%x)", __func__, serviceId, psm);
GapRequestSecurityParam gapParam = {0};
gapParam.info.protocolId = SEC_PROTOCOL_L2CAP;
gapParam.callback = AvctSecurityResultCallback;
gapParam.context = (AvctCbDev *)cbDev;
gapParam.info.direction = OUTGOING;
gapParam.info.serviceId = serviceId;
gapParam.info.channelId.l2capPsm = psm;
if (GAPIF_RequestSecurityAsync(&(cbDev->peerAddr), &gapParam)) {
LOG_ERROR("[AVCT] %{public}s:GAP_RequestSecurity failed!", __func__);
}
return;
}
* Function AvctRequestSecurityBy
* Description This function is the callback from gap to check service security .
* Param[in] aclHandle ACL handle.
* Param[in] lcid The link channel id.
* Param[in] id
* Param[in] lpsm
* Return void
*/
void AvctRequestSecurityBy(
const uint16_t aclHandle, const BtAddr addr, const uint16_t lcid, const uint8_t id, const uint16_t lpsm)
{
LOG_DEBUG("[AVCT] %{public}s:Addr(%x:%x:%x:%x:%x:%x)", __func__, BT_ADDR_FMT_ASC(addr.addr));
AvctRevConnParam *connParam = malloc(sizeof(AvctRevConnParam));
if (connParam == NULL) {
LOG_ERROR("[AVCT] %{public}s:memory alloc failed!", __func__);
return;
}
connParam->addr = addr;
connParam->aclHandle = aclHandle;
connParam->lcid = lcid;
connParam->id = id;
connParam->psm = lpsm;
GapRequestSecurityParam gapParam;
gapParam.info.protocolId = SEC_PROTOCOL_L2CAP;
gapParam.callback = (GapSecurityResultCallback)AvctRevConnSecurityResultCallback;
gapParam.context = connParam;
gapParam.info.channelId.l2capPsm = lpsm;
if (lpsm == AVCT_PSM) {
if (g_avctMng.role == AVCT_CT) {
gapParam.info.serviceId = AVRCP_CT;
} else {
gapParam.info.serviceId = AVRCP_TG;
}
} else {
if (g_avctMng.role == AVCT_CT) {
gapParam.info.serviceId = AVRCP_CT_BROWSING;
} else {
gapParam.info.serviceId = AVRCP_TG_BROWSING;
}
}
gapParam.info.direction = INCOMING;
if (GAPIF_RequestSecurityAsync(&addr, &gapParam)) {
LOG_ERROR("[AVCT] %{public}s:GAP_RequestSecurity failed!", __func__);
free(connParam);
}
return;
}