/*
 * 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.
 */

/**
 * @file att_common.c
 *
 * @brief implement common function to be called.
 *
 */

#include "att_common.h"
#include "att_connect.h"

#include <stdlib.h>

#include "alarm.h"
#include "log.h"

#include "platform/include/allocator.h"

#include "btm/btm_thread.h"

static AttConnectInfo g_connectInfo[MAXCONNECT] = {0};
static AttConnectingInfo g_connecting[MAXCONNECT] = {0};
static AttClientDataCallback g_attClientCallback;
static AttServerDataCallback g_attServerCallback;
static AttClientSendDataCallback g_attClientSendDataCB;
static AttServerSendDataCallback g_attServerSendDataCB;
static AttConnectedCallback g_attConnect;
#define FUNCTIONLIST 256
recvDataFunction g_functionList[FUNCTIONLIST];

typedef struct LeRecvSendDataCallbackAsyncContext {
    uint16_t aclHandle;
    int result;
} LeRecvSendDataCallbackAsyncContext;

typedef struct BREDRRecvSendDataCallbackAsyncContext {
    uint16_t lcid;
    int result;
} BREDRRecvSendDataCallbackAsyncContext;

typedef struct TransactionTimeOutContext {
    uint16_t connectHandle;
} TransactionTimeOutContext;

typedef struct AttRecvDataAsyncContext {
    uint16_t lcid;
    Packet *packet;
    void *ctx;
} AttRecvDataAsyncContext;

typedef struct AttRecvLeDataAsyncContext {
    uint16_t aclHandle;
    Packet *packet;
} AttRecvLeDataAsyncContext;

typedef struct AttConnectRegisterContext {
    AttConnectCallback connectBack;
    void *context;
} AttConnectRegisterContext;

static void AttTransactionTimeOut(const void *parameter);

static void AttClientDataRegisterAsync(const void *context);
static void AttClientDataRegisterAsyncDestroy(const void *context);
static void AttClientDataDeregisterAsync(const void *context);
static void AttClientDataDeregisterAsyncDestroy(const void *context);

static void AttServerDataRegisterAsync(const void *context);
static void AttServerDataRegisterAsyncDestroy(const void *context);
static void AttServerDataDeregisterAsync(const void *context);
static void AttServerDataDeregisterAsyncDestroy(const void *context);

static void LeRecvSendDataCallbackAsync(const void *context);
static void LeRecvSendDataCallbackAsyncDestroy(const void *context);

static void BREDRRecvSendDataCallbackAsync(const void *context);
static void BREDRRecvSendDataCallbackAsyncDestroy(const void *context);

static void AttTransactionTimeOutAsync(const void *context);
static void AttTransactionTimeOutAsyncDestroy(const void *context);

static recvDataFunction GetFunction(uint8_t opcode);

static void AttRecvDataAsync(const void *context);
static void AttRecvDataAsyncDestroy(const void *context);
static void AttRecvLeDataAsync(const void *context);
static void AttRecvLeDataAsyncDestroy(const void *context);

static void AttConnectRegisterAsync(const void *context);
static void AttConnectRegisterAsyncDestroy(const void *context);
static void AttConnectDeregisterAsync(const void *context);
static void AttConnectDeregisterAsyncDestroy(const void *context);

static void AttBREDRSendRespCallbackAsync(const void *context);
static void AttBREDRSendRespCallbackAsyncDestroy(const void *context);
static void AttBREDRSendRespCallback(uint16_t lcid, int result);

static void AttLeSendRespCallbackAsync(const void *context);
static void AttLeSendRespCallbackAsyncDestroy(const void *context);
static void AttLeSendRespCallback(uint16_t aclHandle, int result);

static void AttTransactionTimeOutAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    TransactionTimeOutContext *transTimeOutPtr = (TransactionTimeOutContext *)context;
    AttConnectInfo *connect = NULL;
    int listSize;
    AttClientDataCallback *attClientDataCallback = NULL;
    AttServerDataCallback *attServerDataCallback = NULL;
    uint16_t index = 0;

    AttGetConnectInfoIndexByConnectHandle(transTimeOutPtr->connectHandle, &index, &connect);

    if (connect == NULL) {
        LOG_INFO("%{public}s connect == NULL and goto ATTTRANSACTIONTIMEOUT_END", __FUNCTION__);
        goto ATTTRANSACTIONTIMEOUT_END;
    }

    if (!connect->serverSendFlag) {
        attClientDataCallback = AttGetATTClientCallback();
        if ((attClientDataCallback == NULL) || (attClientDataCallback->attClientCallback == NULL)) {
            LOG_WARN("%{public}s attClientDataCallback or attClientDataCallback->attClientCallback is NULL",
                __FUNCTION__);
        } else {
            attClientDataCallback->attClientCallback(
                connect->retGattConnectHandle, ATT_TRANSACTION_TIME_OUT_ID, NULL, NULL, attClientDataCallback->context);
        }
    } else {
        connect->serverSendFlag = false;
        attServerDataCallback = AttGetATTServerCallback();
        if ((attServerDataCallback == NULL) || (attServerDataCallback->attServerCallback == NULL)) {
            LOG_WARN("%{public}s attServerDataCallback or attServerDataCallback->attServerCallback is NULL",
                __FUNCTION__);
        } else {
            attServerDataCallback->attServerCallback(
                connect->retGattConnectHandle, ATT_TRANSACTION_TIME_OUT_ID, NULL, NULL, attServerDataCallback->context);
        }
    }

    InitiativeDisconnect(transTimeOutPtr->connectHandle);
    listSize = ListGetSize(connect->instruct);
    for (; listSize > 0; --listSize) {
        ListRemoveLast(connect->instruct);
    }

ATTTRANSACTIONTIMEOUT_END:
    MEM_MALLOC.free(transTimeOutPtr);
    return;
}

static void AttTransactionTimeOutAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    TransactionTimeOutContext *transTimeOutPtr = (TransactionTimeOutContext *)context;

    MEM_MALLOC.free(transTimeOutPtr);

    return;
}

/**
 * @brief att transaction timeout.
 *
 * @param parameter Indicates the pointer to parameter.
 */
static void AttTransactionTimeOut(const void *parameter)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttConnectInfo *connect = (AttConnectInfo *)parameter;
    TransactionTimeOutContext *transTimeOutPtr = MEM_MALLOC.alloc(sizeof(TransactionTimeOutContext));
    if (transTimeOutPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }
    transTimeOutPtr->connectHandle = connect->retGattConnectHandle;

    AttAsyncProcess(AttTransactionTimeOutAsync, AttTransactionTimeOutAsyncDestroy, transTimeOutPtr);

    return;
}

/**
 * @brief get AttConnectInfo information.
 *
 * @return Returns the pointer to AttConnectInfo.
 */
AttConnectInfo *AttGetConnectStart()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return g_connectInfo;
}

/**
 * @brief lookup AttConnectInfo info by aclHandle.
 *
 * @param1 aclHandle Indicates the aclHandle.
 * @param2 connect Indicates the second rank pointer to AttConnectInfo.
 */
void AttGetConnectInfoIndexByAclHandle(uint16_t aclHandle, AttConnectInfo **connect)
{
    LOG_INFO("%{public}s enter, aclHandle = %hu", __FUNCTION__, aclHandle);

    uint16_t index = 0;

    for (; index < MAXCONNECT; ++index) {
        if (g_connectInfo[index].aclHandle == aclHandle) {
            break;
        }
    }

    if (index != MAXCONNECT) {
        *connect = &g_connectInfo[index];
    } else {
        *connect = NULL;
    }

    LOG_INFO("%{public}s return: index = %hu", __FUNCTION__, index);
    return;
}

/**
 * @brief lookup AttConnectInfo info by cid.
 *
 * @param1 cid Indicates the cid.
 * @param2 connect Indicates the second rank pointer to AttConnectInfo.
 */
void AttGetConnectInfoIndexByCid(uint16_t cid, AttConnectInfo **connect)
{
    LOG_INFO("%{public}s enter, cid = %hu", __FUNCTION__, cid);

    uint16_t index = 0;

    for (; index < MAXCONNECT; ++index) {
        if (g_connectInfo[index].transportType == BT_TRANSPORT_BR_EDR) {
            if (g_connectInfo[index].AttConnectID.bredrcid == cid) {
                break;
            }
        }
        if (g_connectInfo[index].transportType == BT_TRANSPORT_LE) {
            if (g_connectInfo[index].aclHandle == cid) {
                break;
            }
        }
    }

    if (index != MAXCONNECT) {
        *connect = &g_connectInfo[index];
    } else {
        *connect = NULL;
    }

    LOG_INFO("%{public}s return: index = %hu", __FUNCTION__, index);
    return;
}

/**
 * @brief lookup AttConnectInfo info by cid and output parameter index.
 *
 * @param1 cid Indicates the cid.
 * @param2 index Indicates the pointer to index.
 * @param3 connect Indicates second rank pointer to AttConnectInfo.
 */
void AttGetConnectInfoIndexByCidOutIndex(uint16_t cid, uint16_t *index, AttConnectInfo **connect)
{
    LOG_INFO("%{public}s enter,cid = %hu", __FUNCTION__, cid);

    uint16_t indexNumber = 0;

    for (; indexNumber < MAXCONNECT; ++indexNumber) {
        if (g_connectInfo[indexNumber].AttConnectID.bredrcid == cid) {
            break;
        }
    }

    *index = indexNumber;

    if (indexNumber != MAXCONNECT) {
        *connect = &g_connectInfo[indexNumber];
    } else {
        *connect = NULL;
    }

    LOG_INFO("%{public}s return: *index = %hu", __FUNCTION__, *index);
    return;
}

/**
 * @brief lookup AttConnectInfo info by connectHandle and output parameter index.
 *
 * @param1 connectHandle Indicates the connectHandle.
 * @param2 index Indicates the pointer to index.
 * @param3 connect Indicates the Secondary pointer to AttConnectInfo.
 */
void AttGetConnectInfoIndexByConnectHandle(uint16_t connectHandle, uint16_t *index, AttConnectInfo **connect)
{
    LOG_INFO("%{public}s enter, connectHandle = %hu", __FUNCTION__, connectHandle);

    uint16_t inindex = 0;

    for (; inindex < MAXCONNECT; ++inindex) {
        if (g_connectInfo[inindex].retGattConnectHandle == connectHandle) {
            break;
        }
    }

    *index = inindex;

    if (inindex != MAXCONNECT) {
        *connect = &g_connectInfo[inindex];

        goto ATTGETCONNECTINFOINDEXBYCONNECTHANDLE_END;
    } else {
        *connect = NULL;
        *index = MAXCONNECT;
        goto ATTGETCONNECTINFOINDEXBYCONNECTHANDLE_END;
    }

ATTGETCONNECTINFOINDEXBYCONNECTHANDLE_END:
    LOG_INFO("%{public}s return: *index = %hu", __FUNCTION__, *index);
    return;
}

/**
 * @brief gatt register client data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttClientDataRegisterAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttClientDataCallback *attClientDataCallbackAsyncPtr = (AttClientDataCallback *)context;

    g_attClientCallback.attClientCallback = attClientDataCallbackAsyncPtr->attClientCallback;
    g_attClientCallback.context = attClientDataCallbackAsyncPtr->context;

    MEM_MALLOC.free(attClientDataCallbackAsyncPtr);

    return;
}

/**
 * @brief destroy gatt register client data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttClientDataRegisterAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttClientDataCallback *attClientDataCallbackAsyncPtr = (AttClientDataCallback *)context;

    MEM_MALLOC.free(attClientDataCallbackAsyncPtr);

    return;
}

/**
 * @brief gatt register client data to att.
 *
 * @param1 dataCallback Indicates the pointer to callback.
 * @param2 context Indicates the pointer to context.
 */
void ATT_ClientDataRegister(attCallback dataCallback, void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttClientDataCallback *attClientDataCallbackAsyncPtr = MEM_MALLOC.alloc(sizeof(AttClientDataCallback));
    if (attClientDataCallbackAsyncPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }
    attClientDataCallbackAsyncPtr->attClientCallback = dataCallback;
    attClientDataCallbackAsyncPtr->context = context;

    AttAsyncProcess(AttClientDataRegisterAsync, AttClientDataRegisterAsyncDestroy, attClientDataCallbackAsyncPtr);

    return;
}

/**
 * @brief gatt deregister client data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttClientDataDeregisterAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    g_attClientCallback.attClientCallback = NULL;
    g_attClientCallback.context = NULL;

    return;
}

/**
 * @brief destroy gatt deregister client data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttClientDataDeregisterAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return;
}

/**
 * @brief gatt deregister client data to att.
 *
 */
void ATT_ClientDataDeregister()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttAsyncProcess(AttClientDataDeregisterAsync, AttClientDataDeregisterAsyncDestroy, NULL);

    return;
}

/**
 * @brief gatt register server data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttServerDataRegisterAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttServerDataCallback *attServerDataCallbackAsyncPtr = (AttServerDataCallback *)context;

    g_attServerCallback.attServerCallback = attServerDataCallbackAsyncPtr->attServerCallback;
    g_attServerCallback.context = attServerDataCallbackAsyncPtr->context;

    MEM_MALLOC.free(attServerDataCallbackAsyncPtr);

    return;
}

/**
 * @brief destroy gatt register server data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttServerDataRegisterAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttServerDataCallback *attServerDataCallbackAsyncPtr = (AttServerDataCallback *)context;

    MEM_MALLOC.free(attServerDataCallbackAsyncPtr);

    return;
}

/**
 * @brief gatt register server data to att.
 *
 * @param1 dataCallback Indicates the pointer to callback.
 * @param2 context Indicates the pointer to context.
 */
void ATT_ServerDataRegister(attCallback dataCallback, void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttServerDataCallback *attServerDataCallbackAsyncPtr = MEM_MALLOC.alloc(sizeof(AttServerDataCallback));
    if (attServerDataCallbackAsyncPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }
    attServerDataCallbackAsyncPtr->attServerCallback = dataCallback;
    attServerDataCallbackAsyncPtr->context = context;

    AttAsyncProcess(AttServerDataRegisterAsync, AttServerDataRegisterAsyncDestroy, attServerDataCallbackAsyncPtr);

    return;
}

/**
 * @brief destroy gatt deregister server data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttServerDataDeregisterAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    g_attServerCallback.attServerCallback = NULL;
    g_attServerCallback.context = NULL;

    return;
}

/**
 * @brief destroy gatt deregister server data to att in self thread..
 *
 * @param context Indicates the pointer to context.
 */
static void AttServerDataDeregisterAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return;
}

/**
 * @brief gatt deregister server data to att.
 *
 */
void ATT_ServerDataDeregister()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttAsyncProcess(AttServerDataDeregisterAsync, AttServerDataDeregisterAsyncDestroy, NULL);

    return;
}

/**
 * @brief get AttClientDataCallback information.
 *
 * @return Returns the pointer to AttClientDataCallback.
 */
AttClientDataCallback *AttGetATTClientCallback()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return &g_attClientCallback;
}

/**
 * @brief get AttServerDataCallback information.
 *
 * @return Returns the pointer to AttServerDataCallback.
 */
AttServerDataCallback *AttGetATTServerCallback()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return &g_attServerCallback;
}

/**
 * @brief initiative execut instructions by Scheduling.
 *
 * @param connect Indicates the pointer to AttConnectInfo.
 * @return Returns <b>0</b> if the operation is successful; returns <b>!0</b> if the operation fails.
 */
int AttSendSequenceScheduling(const AttConnectInfo *connect)
{
    LOG_INFO("%{public}s enter, listsize = %u", __FUNCTION__, ListGetSize(connect->instruct));

    int ret = BT_SUCCESS;

    if (ListGetSize(connect->instruct) == 1) {
        ListNode *listNodePtr = ListGetFirstNode(connect->instruct);
        if (listNodePtr == NULL) {
            LOG_INFO("%{public}s listNodePtr == NULL", __FUNCTION__);
            ret = BT_OPERATION_FAILED;
            goto ATTSENDSEQUENCESCHEDULING_END;
        }
        Packet *packet = ListGetNodeData(listNodePtr);
        if (connect->transportType == BT_TRANSPORT_LE) {
            ret = L2CIF_LeSendFixChannelData(connect->aclHandle, (uint16_t)LE_CID, packet, LeRecvSendDataCallback);
        }
        if (connect->transportType == BT_TRANSPORT_BR_EDR) {
            ret = L2CIF_SendData(connect->AttConnectID.bredrcid, packet, BREDRRecvSendDataCallback);
        }
        if (ret != BT_SUCCESS) {
            LOG_INFO("%{public}s call l2cap interface return not success", __FUNCTION__);
        } else {
            AlarmSet(
                connect->alarm, (uint64_t)INSTRUCTIONTIMEOUT, (void (*)(void *))AttTransactionTimeOut, (void *)connect);
        }
    }

ATTSENDSEQUENCESCHEDULING_END:
    return ret;
}

/**
 * @brief execut instructions by Scheduling after receiving response.
 *
 * @param connect Indicates the pointer to AttConnectInfo.
 */
void AttReceiveSequenceScheduling(const AttConnectInfo *connect)
{
    LOG_INFO("%{public}s enter, listsize = %u, transportType = %hhu",
        __FUNCTION__,
        ListGetSize(connect->instruct),
        connect->transportType);

    int ret = BT_OPERATION_FAILED;

    if (ListGetSize(connect->instruct) > 0) {
        ListNode *listNodePtr = ListGetFirstNode(connect->instruct);
        if (listNodePtr == NULL) {
            LOG_INFO("%{public}s listNodePtr == NULL", __FUNCTION__);
            goto ATTRECEIVESEQUENCESCHEDULING_END;
        }
        Packet *PacketPtr = ListGetNodeData(listNodePtr);
        if (connect->transportType == BT_TRANSPORT_LE) {
            ret = L2CIF_LeSendFixChannelData(connect->aclHandle, (uint16_t)LE_CID, PacketPtr, LeRecvSendDataCallback);
        }
        if (connect->transportType == BT_TRANSPORT_BR_EDR) {
            ret = L2CIF_SendData(connect->AttConnectID.bredrcid, PacketPtr, BREDRRecvSendDataCallback);
        }

        if (ret != BT_SUCCESS) {
            LOG_INFO("%{public}s call l2cap interface return not success", __FUNCTION__);
        } else {
            AlarmSet(connect->alarm,
                (uint64_t)INSTRUCTIONTIMEOUT,
                (void (*)(void *))AttTransactionTimeOut,
                (AttConnectInfo *)connect);
        }
    }

ATTRECEIVESEQUENCESCHEDULING_END:
    return;
}

/**
 * @brief get AttConnectingInfo information.
 *
 * @return Returns the pointer to AttConnectingInfo.
 */
AttConnectingInfo *AttGetConnectingStart()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return g_connecting;
}

/**
 * @brief lookup AttConnectingInfo info by cid.
 *
 * @param1 cid Indicates the cid.
 * @param2 connecting Indicates the Secondary pointer to AttConnectingInfo.
 */
void AttGetConnectingIndexByCid(uint16_t cid, AttConnectingInfo **connecting)
{
    LOG_INFO("%{public}s enter, cid = %hu", __FUNCTION__, cid);

    uint16_t index = 0;

    for (; index < MAXCONNECT; ++index) {
        if (g_connecting[index].cid == cid) {
            break;
        }
    }

    if (index != MAXCONNECT) {
        *connecting = &g_connecting[index];
        goto ATTGETCONNECTINGINDEXBYCID_END;
    } else {
        *connecting = NULL;
        goto ATTGETCONNECTINGINDEXBYCID_END;
    }

ATTGETCONNECTINGINDEXBYCID_END:
    LOG_INFO("%{public}s return: index = %hu", __FUNCTION__, index);
    return;
}

/**
 * @brief lookup AttConnectingInfo info by cid and output parameter index.
 *
 * @param1 cid Indicates the cid.
 * @param2 index Indicates the pointer to index.
 * @param3 connecting Indicates the Secondary pointer to AttConnectingInfo.
 */
void AttGetConnectingIndexByCidOutIndex(uint16_t cid, uint16_t *index, AttConnectingInfo **connecting)
{
    LOG_INFO("%{public}s enter,cid = %hu", __FUNCTION__, cid);

    uint16_t indexNumber = 0;

    for (; indexNumber < MAXCONNECT; ++indexNumber) {
        if (g_connecting[indexNumber].cid == cid) {
            break;
        }
    }

    if (indexNumber != MAXCONNECT) {
        *connecting = &g_connecting[indexNumber];
        *index = indexNumber;
        goto ATTGETCONNECTINGINDEXBYCIDOUTINDEX_END;
    } else {
        *connecting = NULL;
        *index = MAXCONNECT;
        goto ATTGETCONNECTINGINDEXBYCIDOUTINDEX_END;
    }

ATTGETCONNECTINGINDEXBYCIDOUTINDEX_END:
    LOG_INFO("%{public}s return: *index = %hu", __FUNCTION__, *index);
    return;
}

/**
 * @brief lookup AttConnectingInfo info by connectHandle.
 *
 * @param1 connectHandle Indicates the connectHandle.
 * @param2 connecting Indicates the Secondary pointer to AttConnectingInfo.
 */
void AttGetConnectingIndexByConnectHandle(uint16_t connectHandle, AttConnectingInfo **connecting)
{
    LOG_INFO("%{public}s enter, connectHandle = %hu", __FUNCTION__, connectHandle);

    uint16_t index = 0;

    for (; index < MAXCONNECT; ++index) {
        if (g_connecting[index].connectHandle == connectHandle) {
            break;
        }
    }

    if (index != MAXCONNECT) {
        *connecting = &g_connecting[index];
        goto ATTGETCONNECTINGINDEXBYCONNECTHANDLE_END;
    } else {
        *connecting = NULL;
        goto ATTGETCONNECTINGINDEXBYCONNECTHANDLE_END;
    }

ATTGETCONNECTINGINDEXBYCONNECTHANDLE_END:
    LOG_INFO("%{public}s return: index = %hu", __FUNCTION__, index);
    return;
}

/**
 * @brief lookup AttConnectingInfo info by cid and connectHandle, result to output parameter index.
 *
 * @param1 cid Indicates the cid.
 * @param2 connectHandle Indicates the connectHandle.
 * @param3 index Indicates the pointer to index.
 * @param4 connecting Indicates the Secondary pointer to AttConnectingInfo.
 */
void AttGetConnectingIndexByCidConnectHandle(
    uint16_t cid, uint16_t connectHandle, uint16_t *index, AttConnectingInfo **connecting)
{
    LOG_INFO("%{public}s enter, cid = %hu,connectHandle = %hu", __FUNCTION__, cid, connectHandle);

    uint16_t inindex = 0;

    for (; inindex < MAXCONNECT; ++inindex) {
        if ((g_connecting[inindex].cid == cid) && (g_connecting[inindex].connectHandle == connectHandle)) {
            break;
        }
    }

    *index = inindex;

    if (inindex != MAXCONNECT) {
        *connecting = &g_connecting[inindex];
        goto ATTGETCONNECTINGINDEXBYCIDCONNECTHANDLE_END;
    } else {
        *connecting = NULL;
        goto ATTGETCONNECTINGINDEXBYCIDCONNECTHANDLE_END;
    }

ATTGETCONNECTINGINDEXBYCIDCONNECTHANDLE_END:
    LOG_INFO("%{public}s return: *index = %hu", __FUNCTION__, *index);
    return;
}

/**
 * @brief lookup AttConnectingInfo info by addr.
 *
 * @param1 addr Indicates the pointer to const BtAddr.
 * @param2 connecting Indicates the second rank pointer to AttConnectingInfo.
 */
void AttGetConnectingIndexByAddr(const BtAddr *addr, AttConnectingInfo **connecting)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    uint16_t index = 0;

    for (; index < MAXCONNECT; ++index) {
        if (!memcmp(g_connecting[index].addr.addr, addr->addr, ADDRESSLEN)) {
            break;
        }
    }

    if (index != MAXCONNECT) {
        *connecting = &g_connecting[index];
        goto ATTGETCONNECTINGINDEXBYADDR_END;
    } else {
        *connecting = NULL;
        goto ATTGETCONNECTINGINDEXBYADDR_END;
    }

ATTGETCONNECTINGINDEXBYADDR_END:
    LOG_INFO("%{public}s return: index = %hu", __FUNCTION__, index);
    return;
}

/**
 * @brief lookup AttConnectingInfo info by addr cid.
 *
 * @param1 addr Indicates the pointer to addr.
 * @param2 addr Indicates the cid.
 * @param3 connect Indicates the second rank pointer to AttConnectingInfo.
 */
void AttGetConnectingIndexByAddrUninitializedCid(const BtAddr *addr, AttConnectingInfo **connecting)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    uint16_t index = 0;

    for (; index < MAXCONNECT; ++index) {
        if ((!memcmp(g_connecting[index].addr.addr, addr->addr, ADDRESSLEN)) && (g_connecting[index].cid == 0)) {
            break;
        }
    }

    LOG_INFO("%{public}s,index = %hu", __FUNCTION__, index);

    if (index != MAXCONNECT) {
        *connecting = &g_connecting[index];
        goto ATTGETCONNECTINGINDEXBYADDRUNINITIALIZEDCID_END;
    } else {
        *connecting = NULL;
        goto ATTGETCONNECTINGINDEXBYADDRUNINITIALIZEDCID_END;
    }

ATTGETCONNECTINGINDEXBYADDRUNINITIALIZEDCID_END:
    LOG_INFO("%{public}s return: index = %hu", __FUNCTION__, index);
    return;
}

/**
 * @brief lookup AttConnectingInfo info by addr aclhandle cid.
 *
 * @param1 addr Indicates pointer to addr.
 * @param2 addr Indicates the aclHandle.
 * @param3 addr Indicates the cid.
 * @param2 connect Indicates the second rank pointer to AttConnectingInfo.
 */
void AttGetConnectingIndexByAddrAclhandleCid(
    const BtAddr *addr, uint16_t aclHandle, uint16_t cid, AttConnectingInfo **connecting)
{
    LOG_INFO("%{public}s enter, aclHandle = %hu, cid = %hu", __FUNCTION__, aclHandle, cid);
    uint16_t index = 0;

    for (; index < MAXCONNECT; ++index) {
        if ((!memcmp(g_connecting[index].addr.addr, addr->addr, ADDRESSLEN)) &&
            (g_connecting[index].aclHandle == aclHandle) && (g_connecting[index].cid == cid)) {
            break;
        }
    }

    if (index != MAXCONNECT) {
        *connecting = &g_connecting[index];
        goto ATTGETCONNECTINGINDEXBYADDRACLHANDLECID_END;
    } else {
        *connecting = NULL;
        goto ATTGETCONNECTINGINDEXBYADDRACLHANDLECID_END;
    }

ATTGETCONNECTINGINDEXBYADDRACLHANDLECID_END:
    LOG_INFO("%{public}s return: index = %hu", __FUNCTION__, index);
    return;
}

/**
 * @brief client call back copy.
 *
 * @param1 attSendDataCb Indicates the pointer to attSendDataCallback.
 * @param2 context Indicates the pointer to context.
 */
void AttClientCallBackCopyToCommon(attSendDataCallback attSendDataCB, const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    g_attClientSendDataCB.attSendDataCB = attSendDataCB;
    g_attClientSendDataCB.context = (void *)context;

    return;
}
/**
 * @brief server call back copy.
 *
 * @param1 attSendDataCb Indicates the pointer to attSendDataCallback.
 * @param2 context Indicates the pointer to context.
 */
void AttServerCallBackCopyToCommon(attSendDataCallback attSendDataCB, const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    g_attServerSendDataCB.attSendDataCB = attSendDataCB;
    g_attServerSendDataCB.context = (void *)context;

    return;
}

/**
 * @brief le receive senddata callback async.
 *
 * @param context Indicates the pointer to context.
 */
static void LeRecvSendDataCallbackAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    LeRecvSendDataCallbackAsyncContext *leRecvSendDataCallPtr = (LeRecvSendDataCallbackAsyncContext *)context;
    AttConnectInfo *connect = NULL;

    AttGetConnectInfoIndexByCid(leRecvSendDataCallPtr->aclHandle, &connect);

    if (connect == NULL) {
        goto RECVSENDDATACALLBACK_END;
    }

    if (g_attClientSendDataCB.attSendDataCB != NULL) {
        g_attClientSendDataCB.attSendDataCB(
            connect->retGattConnectHandle, leRecvSendDataCallPtr->result, g_attClientSendDataCB.context);
    }
    if (leRecvSendDataCallPtr->result == BT_SUCCESS) {
        AlarmSet(connect->alarm, (uint64_t)INSTRUCTIONTIMEOUT, (void (*)(void *))AttTransactionTimeOut, connect);
    } else {
        LOG_WARN("L2CAP error code = %{public}d", leRecvSendDataCallPtr->result);
        AlarmCancel(connect->alarm);
    }

RECVSENDDATACALLBACK_END:
    MEM_MALLOC.free(leRecvSendDataCallPtr);
    return;
}

/**
 * @brief le receive senddata callback async destroy.
 *
 * @param context Indicates the pointer to context.
 */
static void LeRecvSendDataCallbackAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    LeRecvSendDataCallbackAsyncContext *leRecvSendDataCallPtr = (LeRecvSendDataCallbackAsyncContext *)context;

    MEM_MALLOC.free(leRecvSendDataCallPtr);

    return;
}

/**
 * @brief receive senddata callback.
 *
 * @param1 aclHandle Indicates the aclHandle.
 * @param2 result Indicates the result.
 */
void LeRecvSendDataCallback(uint16_t aclHandle, int result)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    LeRecvSendDataCallbackAsyncContext *leRecvSendDataCallPtr =
        MEM_MALLOC.alloc(sizeof(LeRecvSendDataCallbackAsyncContext));
    if (leRecvSendDataCallPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }

    leRecvSendDataCallPtr->aclHandle = aclHandle;
    leRecvSendDataCallPtr->result = result;

    AttAsyncProcess(LeRecvSendDataCallbackAsync, LeRecvSendDataCallbackAsyncDestroy, leRecvSendDataCallPtr);

    return;
}

/**
 * @brief BREDR receive senddata callback async.
 *
 * @param context Indicates the pointer to context.
 */
static void BREDRRecvSendDataCallbackAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    BREDRRecvSendDataCallbackAsyncContext *bredrRecvSendDataCallPtr = (BREDRRecvSendDataCallbackAsyncContext *)context;
    AttConnectInfo *connect = NULL;

    AttGetConnectInfoIndexByCid(bredrRecvSendDataCallPtr->lcid, &connect);

    if (connect == NULL) {
        goto BREDRRECVSENDDATACALLBACK_END;
    }

    if (g_attClientSendDataCB.attSendDataCB != NULL) {
        g_attClientSendDataCB.attSendDataCB(
            connect->retGattConnectHandle, bredrRecvSendDataCallPtr->result, g_attClientSendDataCB.context);
    }
    if (bredrRecvSendDataCallPtr->result == BT_SUCCESS) {
        AlarmSet(connect->alarm, (uint64_t)INSTRUCTIONTIMEOUT, (void (*)(void *))AttTransactionTimeOut, connect);
    } else {
        LOG_WARN("L2CAP error code = %{public}d", bredrRecvSendDataCallPtr->result);
        AlarmCancel(connect->alarm);
    }

BREDRRECVSENDDATACALLBACK_END:
    MEM_MALLOC.free(bredrRecvSendDataCallPtr);
    return;
}

/**
 * @brief BREDR receive senddata callback async destroy.
 *
 * @param context Indicates the pointer to context.
 */
static void BREDRRecvSendDataCallbackAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    BREDRRecvSendDataCallbackAsyncContext *bredrRecvSendDataCallPtr = (BREDRRecvSendDataCallbackAsyncContext *)context;

    MEM_MALLOC.free(bredrRecvSendDataCallPtr);

    return;
}

/**
 * @brief receive senddata callback.
 *
 * @param1 lcid Indicates the lcid.
 * @param2 result Indicates the result.
 * @param3 context Indicates the pointer to context.
 */
void BREDRRecvSendDataCallback(uint16_t lcid, int result)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    BREDRRecvSendDataCallbackAsyncContext *bredrSendDataCallPtr =
        MEM_MALLOC.alloc(sizeof(BREDRRecvSendDataCallbackAsyncContext));
    if (bredrSendDataCallPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }

    bredrSendDataCallPtr->lcid = lcid;
    bredrSendDataCallPtr->result = result;

    AttAsyncProcess(BREDRRecvSendDataCallbackAsync, BREDRRecvSendDataCallbackAsyncDestroy, bredrSendDataCallPtr);

    return;
}

/**
 * @brief receive delect callback.
 *
 */
void AttCallBackDelectCopyToCommon()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    g_attServerSendDataCB.attSendDataCB = NULL;
    g_attServerSendDataCB.context = NULL;

    return;
}

/**
 * @brief switch thread.
 *
 * @param1 callback Indicates the pointer to function pointer.
 * @param2 destroyCallback Indicates the pointer to function pointer.
 * @param3 context Indicates the pointer to context.
 */
void AttAsyncProcess(
    void (*callback)(const void *context), void (*destroyCallback)(const void *context), const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    int ret;

    ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_ATT, (void (*)(void *))callback, (void *)context);
    if (ret != BT_SUCCESS) {
        if (destroyCallback != NULL) {
            destroyCallback(context);
        }
    }

    return;
}

/**
 * @brief shut down clear connect information.
 *
 * @param connectInfo Indicates the pointer to AttConnectInfo.
 */
void AttShutDownClearConnectInfo(AttConnectInfo *connectInfo)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    connectInfo->aclHandle = 0;
    (void)memset_s(&connectInfo->AttConnectID, sizeof(connectInfo->AttConnectID), 0, sizeof(connectInfo->AttConnectID));
    connectInfo->retGattConnectHandle = 0;
    connectInfo->transportType = 0;
    (void)memset_s(&connectInfo->addr, sizeof(connectInfo->addr), 0, sizeof(BtAddr));
    connectInfo->mtu = 0;
    connectInfo->sendMtu = 0;
    connectInfo->receiveMtu = 0;
    connectInfo->mtuFlag = false;
    connectInfo->initPassConnFlag = 0;
    connectInfo->serverSendFlag = false;

    g_attClientCallback.attClientCallback = NULL;
    g_attServerCallback.attServerCallback = NULL;
    g_attClientSendDataCB.attSendDataCB = NULL;
    g_attServerSendDataCB.attSendDataCB = NULL;
    g_attConnect.attConnect.attBREDRConnectCompleted = NULL;
    g_attConnect.attConnect.attBREDRConnectInd = NULL;
    g_attConnect.attConnect.attBREDRDisconnectCompleted = NULL;
    g_attConnect.attConnect.attLEConnectCompleted = NULL;
    g_attConnect.attConnect.attLEDisconnectCompleted = NULL;

    return;
}

/**
 * @brief client callback btbadparam.
 *
 */
void ClientCallbackBTBADPARAM(const AttConnectInfo *connect)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    if (connect == NULL) {
        return;
    }

    if (g_attClientSendDataCB.attSendDataCB != NULL) {
        g_attClientSendDataCB.attSendDataCB(connect->retGattConnectHandle, BT_BAD_PARAM, g_attClientSendDataCB.context);
    }

    return;
}

/**
 * @brief server callback btbadparam.
 *
 */
void ServerCallbackBTBADPARAM(const AttConnectInfo *connect)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    if (g_attServerSendDataCB.attSendDataCB != NULL) {
        g_attServerSendDataCB.attSendDataCB(connect->retGattConnectHandle, BT_BAD_PARAM, g_attServerSendDataCB.context);
    }

    return;
}

/**
 * @brief client callback return value.
 *
 * @param1 ret Indicates the ret.
 * @param2 connect Indicates the pointer of AttConnectInfo.
 */
void ClientCallbackReturnValue(int ret, const AttConnectInfo *connect)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    if (ret != BT_SUCCESS) {
        if (g_attClientSendDataCB.attSendDataCB != NULL) {
            g_attClientSendDataCB.attSendDataCB(connect->retGattConnectHandle, ret, g_attClientSendDataCB.context);
        }
    }

    return;
}

/**
 * @brief server callback return value.
 *
 * @param1 ret Indicates the ret.
 * @param2 connect Indicates the pointer of AttConnectInfo.
 */
void ServerCallbackReturnValue(int ret, const AttConnectInfo *connect)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    if (ret != BT_SUCCESS) {
        if (g_attServerSendDataCB.attSendDataCB != NULL) {
            g_attServerSendDataCB.attSendDataCB(connect->retGattConnectHandle, ret, g_attServerSendDataCB.context);
        }
    }

    return;
}

/**
 * @brief receive  bredr connect instructions data in self thread.
 *
 * @param context Indicates the pointer to context.
 */
static void AttRecvDataAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    uint8_t opcode = 0;
    AttConnectInfo *connect = NULL;
    AttRecvDataAsyncContext *attRecvDataAsyncPtr = (AttRecvDataAsyncContext *)context;
    AttGetConnectInfoIndexByCid(attRecvDataAsyncPtr->lcid, &connect);
    if (connect != NULL) {
        PacketExtractHead(attRecvDataAsyncPtr->packet, &opcode, sizeof(uint8_t));
        Buffer *buffer = PacketContinuousPayload(attRecvDataAsyncPtr->packet);
        recvDataFunction functionPtr = GetFunction(opcode);
        if (functionPtr != NULL) {
            functionPtr(connect, buffer);
        } else {
            LOG_WARN("%{public}s UnKnow OpCode : %hhu", __FUNCTION__, opcode);
            if ((opcode & 0b01000000) == 0) {
                AttErrorCode(connect, opcode);
            }
        }
    }

    PacketFree(attRecvDataAsyncPtr->packet);
    MEM_MALLOC.free(attRecvDataAsyncPtr);

    return;
}

/**
 * @brief destroy receive bredr connect instructions data in self thread.
 *
 * @param context Indicates the pointer to context.
 */
static void AttRecvDataAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttRecvDataAsyncContext *attRecvDataAsyncPtr = (AttRecvDataAsyncContext *)context;

    PacketFree(attRecvDataAsyncPtr->packet);
    MEM_MALLOC.free(attRecvDataAsyncPtr);

    return;
}

/**
 * @brief receive  bredr connect instructions data.
 *
 * @param1 lcid Indicates the lcid.
 * @param2 packet Indicates the pointer to Packet.
 * @param3 ctx Indicates the pointer to  context.
 */
void AttRecvData(uint16_t lcid, const Packet *packet, const void *ctx)
{
    LOG_INFO("%{public}s enter,lcid = %hu", __FUNCTION__, lcid);

    Packet *packetPtr = PacketRefMalloc((Packet *)packet);
    AttRecvDataAsyncContext *attRecvDataAsyncPtr = MEM_MALLOC.alloc(sizeof(AttRecvDataAsyncContext));
    if (attRecvDataAsyncPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }
    attRecvDataAsyncPtr->lcid = lcid;
    attRecvDataAsyncPtr->packet = packetPtr;
    attRecvDataAsyncPtr->ctx = (void *)ctx;

    AttAsyncProcess(AttRecvDataAsync, AttRecvDataAsyncDestroy, attRecvDataAsyncPtr);

    return;
}

/**
 * @brief receive le connect instructions data in self thread.
 *
 * @param context Indicates the pointer to context.
 */
static void AttRecvLeDataAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    uint8_t opcode = 0;
    AttConnectInfo *connect = NULL;
    AttRecvLeDataAsyncContext *attRecvLeDataAsyncPtr = (AttRecvLeDataAsyncContext *)context;
    AttGetConnectInfoIndexByAclHandle(attRecvLeDataAsyncPtr->aclHandle, &connect);
    if (connect != NULL) {
        PacketExtractHead(attRecvLeDataAsyncPtr->packet, &opcode, sizeof(uint8_t));
        Buffer *buffer = PacketContinuousPayload(attRecvLeDataAsyncPtr->packet);
        recvDataFunction functionPtr = GetFunction(opcode);
        if (functionPtr != NULL) {
            functionPtr(connect, buffer);
        } else {
            LOG_WARN("UnKnow OpCode : %hhu", opcode);
            if ((opcode & 0b01000000) == 0) {
                AttErrorCode(connect, opcode);
            }
        }
    }

    PacketFree(attRecvLeDataAsyncPtr->packet);
    MEM_MALLOC.free(attRecvLeDataAsyncPtr);

    return;
}

/**
 * @brief destroy le bredr connect instructions data in self thread.
 *
 * @param context Indicates the pointer to context.
 */
static void AttRecvLeDataAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttRecvLeDataAsyncContext *attRecvLeDataAsyncPtr = (AttRecvLeDataAsyncContext *)context;

    PacketFree(attRecvLeDataAsyncPtr->packet);
    MEM_MALLOC.free(attRecvLeDataAsyncPtr);

    return;
}

/**
 * @brief receive  le connect instructions data.
 *
 * @param1 aclHandle Indicates the aclHandle.
 * @param2 packet Indicates the pointer to Packet.
 */
void AttRecvLeData(uint16_t aclHandle, const Packet *packet)
{
    LOG_INFO("%{public}s enter, aclHandle = %hu", __FUNCTION__, aclHandle);

    Packet *packetPtr = PacketRefMalloc((Packet *)packet);
    if (packetPtr == NULL) {
        LOG_ERROR("PacketRefMalloc failed");
        return;
    }
    AttRecvLeDataAsyncContext *attRecvLeDataAsyncPtr = MEM_MALLOC.alloc(sizeof(AttRecvLeDataAsyncContext));
    if (attRecvLeDataAsyncPtr == NULL) {
        LOG_ERROR("point to NULL");
        PacketFree(packetPtr);
        packetPtr = NULL;
        return;
    }
    attRecvLeDataAsyncPtr->aclHandle = aclHandle;
    attRecvLeDataAsyncPtr->packet = packetPtr;

    AttAsyncProcess(AttRecvLeDataAsync, AttRecvLeDataAsyncDestroy, attRecvLeDataAsyncPtr);

    return;
}

/**
 * @brief get function.
 *
 * @param1 opcode Indicates the opcode.
 * @return Returns the recvDataFunction.
 */
static recvDataFunction GetFunction(uint8_t opcode)
{
    return g_functionList[opcode];
}

/**
 * @brief get function array dress.
 *
 * @return Returns the pointer to recvDataFunction.
 */
recvDataFunction *GetFunctionArrayDress()
{
    return g_functionList;
}

/**
 * @brief get att connect callback.
 *
 * @return Returns the pointer to AttConnectedCallback.
 */
AttConnectedCallback *AttGetATTConnectCallback()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return &g_attConnect;
}

static void AttConnectRegisterAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttConnectRegisterContext *attConnRegPtr = (AttConnectRegisterContext *)context;
    AttConnectedCallback *attConnectCallback = AttGetATTConnectCallback();

    attConnectCallback->attConnect = attConnRegPtr->connectBack;
    attConnectCallback->context = attConnRegPtr->context;

    MEM_MALLOC.free(attConnRegPtr);

    return;
}

static void AttConnectRegisterAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttConnectRegisterContext *attConnRegPtr = (AttConnectRegisterContext *)context;

    MEM_MALLOC.free(attConnRegPtr);

    return;
}

/**
 * @brief gatt register connect to att.
 *
 * @param1 connectBack Indicates the struct to callback.
 * @param2 context Indicates the pointer to context.
 */
void ATT_ConnectRegister(AttConnectCallback connectBack, void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttConnectRegisterContext *attConnRegPtr = MEM_MALLOC.alloc(sizeof(AttConnectRegisterContext));
    if (attConnRegPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }

    (void)memcpy_s(
        &(attConnRegPtr->connectBack), sizeof(attConnRegPtr->connectBack), &connectBack, sizeof(AttConnectCallback));
    attConnRegPtr->context = context;

    AttAsyncProcess(AttConnectRegisterAsync, AttConnectRegisterAsyncDestroy, attConnRegPtr);

    return;
}

static void AttConnectDeregisterAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttConnectedCallback *attConnectCallback = AttGetATTConnectCallback();

    attConnectCallback->attConnect.attLEConnectCompleted = NULL;
    attConnectCallback->attConnect.attLEDisconnectCompleted = NULL;
    attConnectCallback->attConnect.attBREDRConnectCompleted = NULL;
    attConnectCallback->attConnect.attBREDRDisconnectCompleted = NULL;
    attConnectCallback->attConnect.attBREDRConnectInd = NULL;
    attConnectCallback->context = NULL;

    return;
}

static void AttConnectDeregisterAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    return;
}

/**
 * @brief gatt deregister connect to att.
 *
 */
void ATT_ConnectDeregister()
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    AttAsyncProcess(AttConnectDeregisterAsync, AttConnectDeregisterAsyncDestroy, NULL);

    return;
}

static void AttBREDRSendRespCallbackAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    BREDRRecvSendDataCallbackAsyncContext *attBredrSendRspPtr = (BREDRRecvSendDataCallbackAsyncContext *)context;
    AttConnectInfo *connect = NULL;

    AttGetConnectInfoIndexByCid(attBredrSendRspPtr->lcid, &connect);

    if (connect == NULL) {
        LOG_INFO("%{public}s connect == NULL", __FUNCTION__);
        goto ATTBREDRSENDRESPCALLBACK_END;
    }

    if (attBredrSendRspPtr->result != BT_SUCCESS) {
        LOG_WARN("L2CAP Send Resp error ,error code = %{public}d", attBredrSendRspPtr->result);
    }

    if (g_attServerSendDataCB.attSendDataCB != NULL) {
        g_attServerSendDataCB.attSendDataCB(
            connect->retGattConnectHandle, attBredrSendRspPtr->result, g_attServerSendDataCB.context);
    }

ATTBREDRSENDRESPCALLBACK_END:
    MEM_MALLOC.free(attBredrSendRspPtr);
    return;
}

static void AttBREDRSendRespCallbackAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    BREDRRecvSendDataCallbackAsyncContext *attBredrSendRspPtr = (BREDRRecvSendDataCallbackAsyncContext *)context;

    MEM_MALLOC.free(attBredrSendRspPtr);

    return;
}

/**
 * @brief callback of send response.
 *
 * @param1 lcid Indicates the lcid.
 * @param2 result Indicates the result.
 */
static void AttBREDRSendRespCallback(uint16_t lcid, int result)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    BREDRRecvSendDataCallbackAsyncContext *attBredrSendRspPtr =
        MEM_MALLOC.alloc(sizeof(BREDRRecvSendDataCallbackAsyncContext));
    if (attBredrSendRspPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }

    attBredrSendRspPtr->lcid = lcid;
    attBredrSendRspPtr->result = result;

    AttAsyncProcess(AttBREDRSendRespCallbackAsync, AttBREDRSendRespCallbackAsyncDestroy, attBredrSendRspPtr);

    return;
}

static void AttLeSendRespCallbackAsync(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    LeRecvSendDataCallbackAsyncContext *attLeSendRspPtr = (LeRecvSendDataCallbackAsyncContext *)context;
    AttConnectInfo *connect = NULL;

    AttGetConnectInfoIndexByCid(attLeSendRspPtr->aclHandle, &connect);

    if (connect == NULL) {
        LOG_INFO("%{public}s connect == NULL", __FUNCTION__);
        goto ATTLESENDRESPCALLBACK_END;
    }

    if (attLeSendRspPtr->result != BT_SUCCESS) {
        LOG_WARN("L2CAP Send Resp error ,error code = %{public}d", attLeSendRspPtr->result);
    }

    if (g_attServerSendDataCB.attSendDataCB != NULL) {
        g_attServerSendDataCB.attSendDataCB(
            connect->retGattConnectHandle, attLeSendRspPtr->result, g_attServerSendDataCB.context);
    }

ATTLESENDRESPCALLBACK_END:
    MEM_MALLOC.free(attLeSendRspPtr);
    return;
}

static void AttLeSendRespCallbackAsyncDestroy(const void *context)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    LeRecvSendDataCallbackAsyncContext *attLeSendRspPtr = (LeRecvSendDataCallbackAsyncContext *)context;

    MEM_MALLOC.free(attLeSendRspPtr);

    return;
}

static void AttLeSendRespCallback(uint16_t aclHandle, int result)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    LeRecvSendDataCallbackAsyncContext *attLeSendRspPtr = MEM_MALLOC.alloc(sizeof(LeRecvSendDataCallbackAsyncContext));
    if (attLeSendRspPtr == NULL) {
        LOG_ERROR("point to NULL");
        return;
    }

    attLeSendRspPtr->aclHandle = aclHandle;
    attLeSendRspPtr->result = result;

    AttAsyncProcess(AttLeSendRespCallbackAsync, AttLeSendRespCallbackAsyncDestroy, attLeSendRspPtr);

    return;
}

/**
 * @brief call l2cap interface to send data.
 *
 * @param1 connect Indicates the pointer to const AttConnectInfo.
 * @param2 packet Indicates the pointer to Packet.
 * @return Returns <b>0</b> if the operation is successful; returns <b>!0</b> if the operation fails.
 */
int AttResponseSendData(const AttConnectInfo *connect, const Packet *packet)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    int ret = BT_OPERATION_FAILED;

    if (connect == NULL) {
        LOG_INFO("%{public}s connect == NULL", __FUNCTION__);
        ret = BT_BAD_PARAM;
        return ret;
    }

    if (connect->transportType == BT_TRANSPORT_BR_EDR) {
        ret = L2CIF_SendData(connect->AttConnectID.bredrcid, (Packet *)packet, AttBREDRSendRespCallback);
    }
    if (connect->transportType == BT_TRANSPORT_LE) {
        ret = L2CIF_LeSendFixChannelData(connect->aclHandle, (uint16_t)LE_CID, (Packet *)packet, AttLeSendRespCallback);
    }

    return ret;
}

/**
 * @brief callback error code.
 *
 * @param1 connect Indicates the pointer to const AttConnectInfo.
 * @param2 opcode Indicates the opcode.
 */
void AttErrorCode(const AttConnectInfo *connect, uint8_t opcode)
{
    LOG_INFO("%{public}s enter", __FUNCTION__);

    if (connect == NULL) {
        LOG_INFO("%{public}s connect == NULL", __FUNCTION__);
        goto ATTERRORCODE_END;
    }

    AttServerDataCallback *attServerDataCallback = NULL;
    uint8_t errorCode = opcode;
    attServerDataCallback = AttGetATTServerCallback();
    attServerDataCallback->attServerCallback(
        connect->retGattConnectHandle, ATT_UNKNOW_OPCODE_ID, &errorCode, NULL, attServerDataCallback->context);

ATTERRORCODE_END:
    return;
}

uint16_t Min(uint16_t param1, uint16_t param2)
{
    if (param1 < param2) {
        return param1;
    } else {
        return param2;
    }
}