/*
 * 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_ctrl_act.h"
#include "avctp_br.h"
#include "avctp_conn.h"
#include "avctp_ctrl.h"
#include "avctp_dev.h"
#include "avctp_gap.h"
#include "avctp_st.h"
#include "l2cap_if.h"
#include "log.h"

/*****************************************************************************
 * Globle Data  Define
 ****************************************************************************/
/*****************************************************************************
 * Function
 ****************************************************************************/
Packet *AvctMakeFrgMsgHeadStart(uint8_t num, uint8_t label, uint8_t cr, uint16_t pid);
Packet *AvctMakeFrgMsgHeadContinueEnd(uint8_t label, uint8_t type, uint8_t cr);

/*
 * Function     AvctCbCtrlChConn
 * Description  This function is called to Open control channel link.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChConn(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    GAP_Service serviceId;
    /* Request servcie security */
    if (g_avctMng.role == AVCT_CT) {
        serviceId = AVRCP_CT;
    } else {
        serviceId = AVRCP_TG;
    }
    AvctRequestSecurity(cbDev, serviceId, AVCT_PSM);
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChConnFail
 * Description  This function is called to Open control channel link failed.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChConnFail(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_CONNECT_CFM_EVT, data->result, &(cbConn->cbDev->peerAddr));
            AvctCbConnDealloc(cbConn);
        }
    }
    AvctCbDevDealloc(cbDev);
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChBind
 * Description  This function is called when the control channel has been
 *              created,and try to bind it.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChBind(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    data->cbConn->cbDev = cbDev;
    cbDev->bindCnt++;
    /* Send callback event to app */
    AvctCbConnEvtCallback(data->cbConn, AVCT_CONNECT_CFM_EVT, AVCT_SUCCESS, &(data->cbConn->cbDev->peerAddr));
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChBindFail
 * Description  This function is called when the control bind failed.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChBindFail(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    /* send connect cfm event ,result failed */
    AvctCbConnEvtCallback(data->cbConn, AVCT_CONNECT_CFM_EVT, AVCT_FAILED, &(data->cbConn->cbDev->peerAddr));
    /* dealloc memory */
    AvctCbConnDealloc(data->cbConn);
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChDisconn
 * Description  This function is called to disconnect the control channel.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChDisconn(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    L2CIF_DisconnectionReq(cbDev->cbCtrl->chId, NULL);
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChUnbind
 * Description  This function is called to unbind and disconnect the control
 *              channel.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChUnbind(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    /* send disconnect cfm event ,result failed */
    AvctCbConnEvtCallback(data->cbConn, AVCT_DISCONNECT_CFM_EVT, AVCT_SUCCESS, &(data->cbConn->cbDev->peerAddr));
    /* dealloc memory */
    AvctCbConnDealloc(data->cbConn);
    cbDev->bindCnt--;
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChCheckDisconn
 * Description  This function is called to check if the connect is the last one which is using the ctrl 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 AvctCbCtrlChCheckDisconn(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    /* check if the connect is the last one which is using the ctrl channel */
    if (cbDev->bindCnt > 1) {
        /* unbind */
        AvctCbCtrlChUnbind(cbDev, data);
    } else {
        /* ctrl channel disconnect */
        AvctCbCtrlEvt(cbDev, AVCT_DISCONN_EVT, data);
        /* if the browser channel is exit, disconnect too */
        if (cbDev->cbBr != NULL) {
            AvctCbBrEvt(cbDev, AVCT_DISCONN_EVT, data);
        }
    }
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChConnInd
 * Description  This function is called when receive the connect ind.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChConnInd(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    AvctCbConn *cbConn = NULL;
    bool bind = false;
    /* find the conn for the connection */
    for (uint8_t i = 0; i < AVCT_MAX_CONNECTS; i++) {
        cbConn = &g_avctMng.cbConn[i];
        if (cbConn->status) {
            if ((cbConn->status == AVCT_CONN_BIND) && (cbConn->cbDev == cbDev)) {
                /* find the connection to the device and send cfm event to app */
                bind = true;
                AvctCbConnEvtCallback(cbConn, AVCT_CONNECT_CFM_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
            } else if ((cbConn->cbDev == NULL) && (cbConn->connParam.role == AVCT_ACPT)) {
                /* bind the connection(ACCEPT) to the device */
                bind = true;
                cbConn->cbDev = cbDev;
                cbConn->status = AVCT_CONN_BIND;
                AvctCbConnEvtCallback(cbConn, AVCT_CONNECT_IND_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
            } else {
                LOG_DEBUG("[AVCT] %{public}s:i(%hhu)Can't find the cbConn! "
                          "cbConn->connId(%hhu),cbConn->status(%hhu)",
                    __func__,
                    i,
                    cbConn->connId,
                    cbConn->status);
            }
        }
    }
    /* can not bind to conn,send disconnect */
    if (!bind) {
        AvctCbCtrlEvt(cbDev, AVCT_DISCONN_EVT, data);
    }
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChCloseInd
 * Description  This function is called when receive the close ind.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChCloseInd(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    AvctCbConn *cbConn = NULL;
    /* find conn which connected to the device, send callback event, relase memory */
    for (uint8_t i = 0; i < AVCT_MAX_CONNECTS; i++) {
        cbConn = &g_avctMng.cbConn[i];
        if ((cbConn->status == AVCT_CONN_BIND) && (cbConn->cbDev == cbDev)) {
            /* Send AVCT_DISCONNECT_IND_EVT */
            AvctCbConnEvtCallback(cbConn, AVCT_DISCONNECT_IND_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
            /* If Br channel is connected, send AVCT_DISCONN_EVT to close channel */
            if (cbConn->cbDev->cbBr != NULL) {
                AvctCbBrEvt(cbDev, AVCT_DISCONN_EVT, (AvctEvtData *)&cbConn);
            }
            AvctCbConnDealloc(cbConn);
        }
    }
    AvctCbChDealloc(&(cbDev->cbCtrl));
    AvctCbDevDealloc(cbDev);
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChCloseCfm
 * Description  This function is called when receive the close confirm.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChCloseCfm(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)) {
            /* Send AVCT_DISCONNECT_CFM_EVT */
            AvctCbConnEvtCallback(cbConn, AVCT_DISCONNECT_CFM_EVT, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
            AvctCbConnDealloc(cbConn);
        }
    }
    /* Free resource */
    AvctCbChDealloc(&(cbDev->cbCtrl));
    AvctCbDevDealloc(cbDev);
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlChBusyInd
 * Description  This function is called when receive the channel busy ind.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlChBusyInd(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    AvctCbConn *cbConn = NULL;
    uint8_t event = AVCT_CHANNEL_UNBUSY_EVT;
    if (data->result == AVCT_BUSY_ST) {
        event = AVCT_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)) {
            /* Send AVCT_BR_CHANNEL_BUSY_EVT */
            AvctCbConnEvtCallback(cbConn, event, AVCT_SUCCESS, &(cbConn->cbDev->peerAddr));
        }
    }
    return AVCT_SUCCESS;
}

/*
 * Function     AvctCbCtrlDiscardMsg
 * Description  This function is called to discard message.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctCbCtrlDiscardMsg(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    return AVCT_FAILED;
}

/*
 * Function     AvctCbCtrlSendMsg
 * 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 AvctCbCtrlSendMsg(AvctCbDev *cbDev, const AvctEvtData *data)
{
    uint16_t ret;
    Packet *pkt = data->txMsg.buf;
    uint16_t msgLen = (uint16_t)PacketSize(pkt);
    LOG_DEBUG("[AVCT] %{public}s:PKT length %hu", __func__, msgLen);
    if (msgLen > (cbDev->cbCtrl->peerMtu - AVCT_PKG_HDR_LEN_SINGLE)) {
        /* Need Message Fragmentation */
        ret = AvctSendFraMsg((const AvctCbCh *)cbDev->cbCtrl, (const AvctTxMsg)data->txMsg);
    } else {
        /* Send signle Message */
        ret = AvctSendSignleMsg((const AvctCbCh *)cbDev->cbCtrl, (const AvctTxMsg)data->txMsg);
    }
    return ret;
}

/*
 * Function     AvctCbCtrlRevMsg
 * Description  This function is called when receive message.
 * Param[in]    *cbDev  The point to the device block.
 * Param[in]    *data  Event data
 * Return       AVCT_SUCCESS. Others: Fail
 */
NO_SANITIZE("cfi") uint16_t AvctCbCtrlRevMsg(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->cbCtrl, data->buf);
    if (pkt == NULL) {
        return ret;
    }
    /* Extract signle pkt head info */
    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) {
        /* an invalid Profile Identifier received */
        LOG_WARN("[AVCT] %{public}s: Invalid ipid!", __func__);
        return ret;
    }
    /* call all cb of pid */
    uint8_t conId = 255; //invalid value
    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_CTRL, pkt, cbConn->connParam.context);
            i = conId + 1;
            continue;
        } else if (conId < AVCT_MAX_CONNECTS) {
            return ret;
        }
        break;
    }
    LOG_DEBUG("[AVCT] %{public}s: ---------cbConn is null--------!", __func__);
    /* Don't find pid connection,send reject */
    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->cbCtrl->chId, sndPkg, NULL);
            if (lRet) {
                LOG_WARN("[AVCT] %{public}s:L2CIF_SendData failed.error is %{public}d", __func__, lRet);
            }
            PacketFree(sndPkg);
        }
    }
    return ret;
}

/*
 * Function     AvctCbCtrlDiscardRevMsg
 * 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 AvctCbCtrlDiscardRevMsg(AvctCbDev *cbDev, const AvctEvtData *data)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    return AVCT_SUCCESS;
}

/*
 * Function     AvctSendSignleMsg
 * Description  This function is called to send single type package.
 * Param[in]    *cbCh  The point to the send link.
 * Param[in]    txMsg  Package data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctSendSignleMsg(const AvctCbCh *cbCh, const AvctTxMsg txMsg)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    uint16_t ret;
    /* Malloc Head */
    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 {
        /* Make Packet Head */
        AvctMakeSignleMsgHead(pkt, txMsg.label, txMsg.cr, txMsg.cbConn->connParam.pid);
        /* Send Packet */
        ret = L2CIF_SendData(cbCh->chId, pkt, NULL);
        /* pkt data debug print */
        AvctPktDataPrint(pkt);
        PacketFree(pkt);
    }
    return ret;
}

/*
 * Function     AvctSendFraMsg
 * Description  This function is called to send fragmentation package.
 * Param[in]    *cbCh  The point to the send link.
 * Param[in]    txMsg  Package data
 * Return       AVCT_SUCCESS. Others: Fail
 */
uint16_t AvctSendFraMsg(const AvctCbCh *cbCh, const AvctTxMsg txMsg)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    uint16_t ret;
    uint8_t pktType = AVCT_PKT_TYPE_START;
    Packet *pkt = txMsg.buf;
    Packet *sndPkg = NULL;
    uint16_t msgLen = (uint16_t)PacketSize(pkt);
    size_t size;
    /* calculate Number of AVCTP Packets */
    uint8_t num = (msgLen - (cbCh->peerMtu - AVCT_PKG_HDR_LEN_START)) / (cbCh->peerMtu - AVCT_PKG_HDR_LEN_CONTINUE) + 1;
    if ((msgLen - (cbCh->peerMtu - AVCT_PKG_HDR_LEN_START)) % (cbCh->peerMtu - AVCT_PKG_HDR_LEN_CONTINUE) != 0) {
        num++;
    }
    /* Fragement Message */
    do {
        /* Make Packet Head data */
        if (pktType == AVCT_PKT_TYPE_START) {
            sndPkg = AvctMakeFrgMsgHeadStart(num, txMsg.label, txMsg.cr, txMsg.cbConn->connParam.pid);
            if (sndPkg == NULL) {
                LOG_ERROR("[AVCT] %{public}s: PacketMalloc failed!", __func__);
                ret = AVCT_ERR_NO_RESOURCES;
                break;
            }
        } else {
            sndPkg = AvctMakeFrgMsgHeadContinueEnd(txMsg.label, pktType, txMsg.cr);
            if (sndPkg == NULL) {
                LOG_ERROR("[AVCT] %{public}s: Packet memory Malloc failed!", __func__);
                ret = AVCT_ERR_NO_RESOURCES;
                break;
            }
        }
        /* Make Fragment packet */
        if (pktType == AVCT_PKT_TYPE_START) {
            size = cbCh->peerMtu - AVCT_PKG_HDR_LEN_START;
        } else {
            size = cbCh->peerMtu - AVCT_PKG_HDR_LEN_CONTINUE;
        }
        msgLen = PacketFragment(pkt, sndPkg, size);
        /* Send packet */
        ret = L2CIF_SendData(cbCh->chId, sndPkg, NULL);
        /* Free pkt memmory */
        PacketFree(sndPkg);
        /* Change packet type */
        if (msgLen > (cbCh->peerMtu - AVCT_PKG_HDR_LEN_END)) {
            pktType = AVCT_PKT_TYPE_CONTINUE;
        } else {
            pktType = AVCT_PKT_TYPE_END;
        }
    } while ((msgLen > 0) && (ret == L2CAP_SUCCESS));
    return ret;
}

/*
 * Function     AvctParsePktType
 * Description  This function is parase pkt type.
 * Param[in]    data  pkg first byte.
 * Param[out]   type  Package type
 * Return       void
 */
void AvctParsePktType(uint8_t data, uint8_t *type)
{
    *type = (data >> MOVE_2BIT) & PKG_TYPE_MASK;
}

/*
 * Function     AvctMsgAsmbl
 * Description  This function is called to asbmle fragmentation package.
 * Param[in]    *cbCh  The point to the send link.
 * Param[in]    pkt  Package data buffer
 * Return       Packet. Package data buffer or NULL
 */
Packet *AvctMsgAsmbl(AvctCbCh *cbCh, Packet *pkt)
{
    Packet *ret = NULL;
    uint8_t fistByte = 0;
    uint8_t pktType = 0;
    uint8_t sHead[4] = {0};
    /* Read first byte to check packet type */
    PacketPayloadRead(pkt, &fistByte, 0, 1);
    AvctParsePktType(fistByte, &pktType);
    LOG_DEBUG("[AVCT] %{public}s:packet type is %hhu", __func__, pktType);
    if (pktType == AVCT_PKT_TYPE_SINGLE) {
        ret = pkt;
    } else if (pktType == AVCT_PKT_TYPE_START) {
        if (cbCh->rxMsg != NULL) {
            /* Free pkt memmory */
            PacketFree(cbCh->rxMsg);
            cbCh->rxMsg = NULL;
        }
        /* Make single packet head at payload */
        cbCh->rxMsg = PacketMalloc(0, 0, AVCT_PKG_HDR_LEN_SINGLE);
        sHead[0] = fistByte;
        PacketPayloadRead(pkt, &sHead[1], AVCT_START_PKT_PID_OFFSET, AVCT_START_PKT_PID_SIZE);
        PacketPayloadWrite(cbCh->rxMsg, sHead, 0, AVCT_PKG_HDR_LEN_SINGLE);
        /* Extrect start head */
        PacketExtractHead(pkt, sHead, AVCT_PKG_HDR_LEN_START);
        /* Add packet playload */
        PacketAssemble(cbCh->rxMsg, pkt);
        LOG_DEBUG("[AVCT] %{public}s:cbCh->rxMsg PacketSize(%u)", __func__, PacketSize(cbCh->rxMsg));
    } else {
        /* continue or end */
        if (cbCh->rxMsg == NULL) {
            LOG_ERROR("[AVCT] %{public}s: continue/end without start, drop.", __func__);
            return ret;
        }
        /* Extrect continue/end head */
        PacketExtractHead(pkt, sHead, AVCT_PKG_HDR_LEN_CONTINUE);
        /* Add packet playload */
        PacketAssemble(cbCh->rxMsg, pkt);
        if (pktType == AVCT_PKT_TYPE_END) {
            ret = cbCh->rxMsg;
        }
        LOG_DEBUG("[AVCT] %{public}s:cbCh->rxMsg PacketSize(%u)", __func__, PacketSize(cbCh->rxMsg));
    }
    return ret;
}
/*
 * Function     AvctMakeSignleMsgHead
 * Description  Make signle packet head.
 * Param[out]   *pkt    The point to the packet.
 * Param[in]    label   stransport label
 * Param[in]    cr      scommand / response
 * Param[in]    pid     profile id
 * Return       void
 */
void AvctMakeSignleMsgHead(const Packet *pkt, uint8_t label, uint8_t cr, uint16_t pid)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    Buffer *buf = PacketHead(pkt);
    uint8_t *p = (uint8_t *)BufferPtr(buf);
    if (p == NULL) {
        LOG_ERROR("[AVCT] %{public}s: BufferPtr failed!", __func__);
        return;
    }
    do {
        *(p)++ = (((label) << MOVE_4BIT) | (AVCT_PKT_TYPE_SINGLE << MOVE_2BIT) | ((cr) << MOVE_1BIT));
        *(p)++ = (uint8_t)((pid) >> MOVE_8BIT);
        *(p) = (uint8_t)((pid)&0x00FF);
    } while (0);
    return;
}
/*
 * Function     AvctMakeRejMsgHead
 * Description  Make reject pakect head.
 * Param[out]   *pkt    The point to the packet.
 * Param[in]    label   stransport label
 * Param[in]    pid     profile id
 * Return       void
 */
void AvctMakeRejMsgHead(const Packet *pkt, uint8_t label, uint16_t pid)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    Buffer *buf = PacketHead(pkt);
    uint8_t *p = (uint8_t *)BufferPtr(buf);
    if (p == NULL) {
        LOG_ERROR("[AVCT] %{public}s: BufferPtr failed!", __func__);
        return;
    }
    do {
        *(p)++ = (((label) << MOVE_4BIT) | (AVCT_PKT_TYPE_SINGLE << MOVE_2BIT) | AVCT_REJ);
        *(p)++ = (uint8_t)((pid) >> MOVE_8BIT);
        *(p) = (uint8_t)((pid)&0x00FF);
    } while (0);
    return;
}
/*
 * Function     AvctMakeFrgMsgHeadStart
 * Description  Make fragment message type start.
 * Param[in]    num    The num of fragment pakect.
 * Param[in]    label   stransport label
 * Param[in]    pid     profile id
 * Return       void
 */
Packet *AvctMakeFrgMsgHeadStart(uint8_t num, uint8_t label, uint8_t cr, uint16_t pid)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    Packet *pkg = PacketMalloc(AVCT_PKG_HDR_LEN_START, 0, 0);
    if (pkg != NULL) {
        Buffer *buf = PacketHead(pkg);
        uint8_t *p = (uint8_t *)BufferPtr(buf);
        if (p == NULL) {
            LOG_ERROR("[AVCT] %{public}s: head buffer is NULL.", __func__);
            PacketFree(pkg);
            return NULL;
        }
        do {
            *(p)++ = (((label) << MOVE_4BIT) | (AVCT_PKT_TYPE_START << MOVE_2BIT) | ((cr) << MOVE_1BIT));
            *(p)++ = num;
            *(p)++ = (uint8_t)((pid) >> MOVE_8BIT);
            *(p) = (uint8_t)((pid)&0x00FF);
        } while (0);
    }
    return pkg;
}
/*
 * Function     AvctMakeFrgMsgHeadContinueEnd
 * Description  Make fragment message type continue/End.
 * Param[in]    label   stransport label
 * Param[in]    type    continue/End
 * Param[in]    cr      command/response
 * Return       void
 */
Packet *AvctMakeFrgMsgHeadContinueEnd(uint8_t label, uint8_t type, uint8_t cr)
{
    LOG_DEBUG("[AVCT] %{public}s:", __func__);
    /* Create Continue/End Head */
    Packet *pkg = PacketMalloc(AVCT_PKG_HDR_LEN_CONTINUE, 0, 0);
    if (pkg != NULL) {
        Buffer *buf = PacketHead(pkg);
        uint8_t *p = (uint8_t *)BufferPtr(buf);
        if (p == NULL) {
            LOG_ERROR("[AVCT] %{public}s: head buffer is NULL.", __func__);
            PacketFree(pkg);
            return NULL;
        }
        do {
            *(p)++ = (((label) << MOVE_4BIT) | ((type) << MOVE_2BIT) | ((cr) << MOVE_1BIT));
        } while (0);
    }
    return pkg;
}

void AvctPktDataPrint(const Packet *pkt)
{
    uint16_t len = (uint16_t)PacketSize(pkt);
    uint8_t buf[AVCT_32BYTE] = {0};
    if (len > AVCT_32BYTE) {
        len = AVCT_32BYTE;
    }
    PacketRead(pkt, buf, 0, len);
    for (int i = 0; i < len; i++) {
        LOG_DEBUG("%02X ", buf[i]);
    }
}