/*
 *
 *    Copyright (c) 2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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
 *          Provides an implementation of the BLEManager singleton object
 *          for the Beken platforms.
 */

/* this file behaves like a config.h, comes first */
#include <crypto/CHIPCryptoPAL.h>
#include <platform/CommissionableDataProvider.h>
#include <platform/DeviceInstanceInfoProvider.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <setup_payload/AdditionalDataPayloadGenerator.h>

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include <ble/CHIPBleServiceData.h>
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
#include <setup_payload/AdditionalDataPayloadGenerator.h>
#endif
#include "stdio.h"
#include "timers.h"
#include <string.h>

// BK7231n BLE related header files
#include "matter_pal.h"

/*******************************************************************************
 * Local data types
 *******************************************************************************/
using namespace ::chip;
using namespace ::chip::Ble;

namespace chip {
namespace DeviceLayer {
namespace Internal {

namespace {

/*******************************************************************************
 * Macros & Constants definitions
 *******************************************************************************/
#ifndef MAX_ADV_DATA_LEN
#define MAX_ADV_DATA_LEN 31
#endif
#define CHIP_ADV_DATA_TYPE_FLAGS 0x01
#define CHIP_ADV_DATA_FLAGS 0x06

/* advertising configuration */
#define CHIP_ADV_SHORT_UUID_LEN (2)

/* FreeRTOS sw timer */
TimerHandle_t bleFastAdvTimer;

enum
{
    DriveBLEExtPerfEvt_DISCONNECT = 0,
};

const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
                                                 0x9D, 0x11 } };
const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
                                                 0x9D, 0x12 } };
static const uint8_t _svc_uuid[16]         = { 0xF6, 0xFF, 0, 0, 0x0, 0x0, 0, 0, 0, 0, 0x0, 0x0, 0, 0, 0, 0 };

#define UUID_CHIPoBLECharact_RX                                                                                                    \
    {                                                                                                                              \
        0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18                             \
    }
// #define UUID_CHIPoBLECharact_RX   { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D,
// 0x11
// }
#define ChipUUID_CHIPoBLECharact_TX                                                                                                \
    {                                                                                                                              \
        0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18                             \
    }
// #define ChipUUID_CHIPoBLECharact_TX   { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D,
//  0x12 }
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
#define UUID_CHIPoBLEChar_C3                                                                                                       \
    {                                                                                                                              \
        0x04, 0x8F, 0x21, 0x83, 0x8A, 0x74, 0x7D, 0xB8, 0xF2, 0x45, 0x72, 0x87, 0x38, 0x02, 0x63, 0x64                             \
    }
#endif
#define BEKEN_ATT_DECL_PRIMARY_SERVICE_128                                                                                         \
    {                                                                                                                              \
        0x00, 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                                                                       \
    }
#define BEKEN_ATT_DECL_CHARACTERISTIC_128                                                                                          \
    {                                                                                                                              \
        0x03, 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                                                                       \
    }
#define BEKEN_ATT_DESC_CLIENT_CHAR_CFG_128                                                                                         \
    {                                                                                                                              \
        0x02, 0x29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                                                                       \
    }

enum
{
    SVR_FFF6_IDX_SVC,
    SVR_FFF6_RX_DECL,
    SVR_FFF6_RX_VALUE,
    SVR_FFF6_TX_DECL,
    SVR_FFF6_TX_VALUE,
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
    SVR_FFF6_C3_VALUE,
#endif
    SVR_FFF6_TX_CFG,
    SVR_FFF6_MAX,
};

ble_attm_desc_t svr_fff6_att_db[SVR_FFF6_MAX] = {
    //  Service Declaration
    [SVR_FFF6_IDX_SVC] = { BEKEN_ATT_DECL_PRIMARY_SERVICE_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 2 },

    //  Level Characteristic Declaration
    [SVR_FFF6_RX_DECL] = { BEKEN_ATT_DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 0 },
    //  Level Characteristic Value  BK_PERM_RIGHT_ENABLE WRITE_REQ_POS  RI_POS  UUID_LEN_POS  BK_PERM_RIGHT_UUID_128
    [SVR_FFF6_RX_VALUE] = { UUID_CHIPoBLECharact_RX, BK_BLE_PERM_SET(WRITE_REQ, ENABLE),
                            BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_128), 512 },

    /// RD_POS  NTF_POS
    [SVR_FFF6_TX_DECL] = { BEKEN_ATT_DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE) | BK_BLE_PERM_SET(NTF, ENABLE), 0, 0 },
    ////  UUID_LEN_POS   BK_PERM_RIGHT_UUID_128 RD_POS
    [SVR_FFF6_TX_VALUE] = { ChipUUID_CHIPoBLECharact_TX, BK_BLE_PERM_SET(RD, ENABLE) | BK_BLE_PERM_SET(NTF, ENABLE),
                            BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_128), 512 },
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
    [SVR_FFF6_C3_VALUE] = { UUID_CHIPoBLEChar_C3, BK_BLE_PERM_SET(RD, ENABLE),
                            BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_128), 512 },
#endif
    [SVR_FFF6_TX_CFG] = { BEKEN_ATT_DESC_CLIENT_CHAR_CFG_128, BK_BLE_PERM_SET(RD, ENABLE) | BK_BLE_PERM_SET(WRITE_REQ, ENABLE), 0,
                          2 },
};

/// const static uint8_t svr_fff6_att_db_item = SVR_FFF6_MAX;
} // namespace

BLEManagerImpl BLEManagerImpl::sInstance;

int BLEManagerImpl::beken_ble_init(void)
{
    int status;

    struct bk_ble_db_cfg ble_db_cfg;

    ble_db_cfg.att_db      = svr_fff6_att_db;
    ble_db_cfg.att_db_nb   = SVR_FFF6_MAX;
    ble_db_cfg.prf_task_id = 0;
    ble_db_cfg.start_hdl   = 0;
    ble_db_cfg.svc_perm    = BK_BLE_PERM_SET(SVC_UUID_LEN, UUID_16);
    memcpy(&(ble_db_cfg.uuid[0]), &_svc_uuid[0], 16);
    status = bk_ble_create_db(&ble_db_cfg);

    if (status != BK_ERR_BLE_SUCCESS)
    {
        return -1;
    }
    return 0;
}

CHIP_ERROR BLEManagerImpl::_Init()
{
    CHIP_ERROR err;

    // Initialize the CHIP BleLayer.
    err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
    SuccessOrExit(err);

    mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
    memset(mBleConnections, 0, sizeof(mBleConnections));
    // Check if BLE stack is initialized
    VerifyOrExit(!mFlags.Has(Flags::kAMEBABLEStackInitialized), err = CHIP_ERROR_INCORRECT_STATE);
    bk_ble_set_notice_cb(ble_event_notice);

    // Set related flags
    mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
    mFlags.Set(Flags::kAMEBABLEStackInitialized);
    mFlags.Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? true : false);
    mFlags.Set(Flags::kFastAdvertisingEnabled);
    mFlags.Set(Flags::kSlowAdvertisingEnabled);
    if (!mFlags.Has(Flags::kBEKENBLEAdvTimer))
    {
        uint32_t bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME;
        bleFastAdvTimer          = xTimerCreate("", (bleAdvTimeoutMs / 2), pdFALSE, NULL, ble_adv_timer_timeout_handle);
        mFlags.Set(Flags::kBEKENBLEAdvTimer);
    }

    PlatformMgr().ScheduleWork(DriveBLEState, 0);

exit:
    return err;
}

void BLEManagerImpl::HandleTXCharRead(void * param)
{
    CHIPoBLEConState * conState;
    ble_read_req_t * r_req = (ble_read_req_t *) param;
    if (param == NULL)
    {
        ChipLogError(DeviceLayer, "HandleTXCharRead failed: %p", param);
    }
    r_req->length = 0;
}

void BLEManagerImpl::HandleTXCharCCCDRead(void * param)
{
    CHIPoBLEConState * conState;
    ble_read_req_t * r_req = (ble_read_req_t *) param;
    conState               = GetConnectionState(r_req->conn_idx);

    if (param == NULL)
    {
        ChipLogError(DeviceLayer, "HandleTXCharCCCDRead failed");
        return;
    }

    if (conState != NULL)
    {
        r_req->value[0] = conState->subscribed ? 1 : 0;
        r_req->value[1] = 0;
        r_req->length   = 2;
    }
    else
    {
        ChipLogError(DeviceLayer, "conState failed: %p", conState);
        r_req->length = 0;
    }
}

void BLEManagerImpl::HandleTXCharCCCDWrite(int conn_id, int notificationsEnabled, int indicationsEnabled)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    // If the client has requested to enabled indications/notifications
    if (indicationsEnabled || notificationsEnabled)
    {
        // If indications are not already enabled for the connection...
        if (!IsSubscribed(conn_id))
        {
            // Record that indications have been enabled for this connection.
            err = SetSubscribed(conn_id);
            VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR);
            SuccessOrExit(err);
        }
    }
    else
    {
        // If indications had previously been enabled for this connection, record that they are no longer enabled.
        UnsetSubscribed(conn_id);
    }

    // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
    // whether the client is enabling or disabling indications.
    {
        ChipDeviceEvent event;
        event.Type                    = (indicationsEnabled || notificationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe
                                                                                     : DeviceEventType::kCHIPoBLEUnsubscribe;
        event.CHIPoBLESubscribe.ConId = conn_id;
        PlatformMgr().PostEventOrDie(&event);
    }

    ChipLogProgress(DeviceLayer, "CHIPoBLE %s received",
                    (indicationsEnabled || notificationsEnabled) ? "subscribe" : "unsubscribe");

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
    }

    return;
}

CHIP_ERROR BLEManagerImpl::HandleTXComplete(int conn_id)
{
    // Post an event to the Chip queue to process the indicate confirmation.
    ChipDeviceEvent event;
    event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
    event.CHIPoBLEIndicateConfirm.ConId = conn_id;
    PlatformMgr().PostEventOrDie(&event);
    return CHIP_NO_ERROR;
}

uint16_t BLEManagerImpl::_NumConnections(void)
{
    uint16_t numCons = 0;

    for (uint8_t i = 0; i < kMaxConnections; i++)
    {
        if (mBleConnections[i].allocated == 1)
        {
            numCons += 1;
        }
    }

    return numCons;
}

CHIP_ERROR BLEManagerImpl::HandleGAPConnect(uint16_t conn_id)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    // Track the number of active GAP connections.
    mNumGAPCons++;
    err = SetSubscribed(conn_id);
    VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(uint16_t conn_id, uint16_t disc_cause)
{
    // Update the number of GAP connections.
    if (mNumGAPCons > 0)
    {
        mNumGAPCons--;
    }

    if (RemoveConnection(conn_id))
    {
        CHIP_ERROR disconReason;
        switch (disc_cause)
        {
        case 0x13:
        case 0x08:
            disconReason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
            break;
        case 0x16:
            disconReason = BLE_ERROR_APP_CLOSED_CONNECTION;
            break;
        default:
            disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
            break;
        }
        HandleConnectionError(conn_id, disconReason);
    }

    // Force a reconfiguration of advertising in case we switched to non-connectable mode when
    // the BLE connection was established.
    mFlags.Set(Flags::kAdvertisingRefreshNeeded);
    return CHIP_NO_ERROR;
}

bool BLEManagerImpl::RemoveConnection(uint8_t connectionHandle)
{
    CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle);
    bool status                     = false;

    if (bleConnState != NULL)
    {
        bleConnState->Reset();
        memset(bleConnState, 0, sizeof(CHIPoBLEConState));
        status = true;
    }
    return status;
}

BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint8_t connectionHandle, bool allocate)
{
    uint8_t freeIndex = kMaxConnections;

    for (uint8_t i = 0; i < kMaxConnections; i++)
    {
        if (mBleConnections[i].allocated == 1)
        {
            if (mBleConnections[i].conn_idx == connectionHandle)
            {
                return &mBleConnections[i];
            }
        }

        else if (i < freeIndex)
        {
            freeIndex = i;
        }
    }

    if (allocate)
    {
        if (freeIndex < kMaxConnections)
        {
            mBleConnections[freeIndex].Set(connectionHandle);
            return &mBleConnections[freeIndex];
        }

        ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState");
    }

    return NULL;
}

CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);

    if (val != mServiceMode)
    {
        mServiceMode = val;
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }

exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);

    if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
    {
        mFlags.Set(Flags::kAdvertisingEnabled, val);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }

exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
{
    switch (mode)
    {
    case BLEAdvertisingMode::kFastAdvertising:
        mFlags.Set(Flags::kFastAdvertisingEnabled, true);
        break;
    case BLEAdvertisingMode::kSlowAdvertising:
        mFlags.Set(Flags::kFastAdvertisingEnabled, false);
        break;
    default:
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    mFlags.Set(Flags::kAdvertisingRefreshNeeded);

    PlatformMgr().ScheduleWork(DriveBLEState, 0);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
{
    if (strlen(mDeviceName) >= bufSize)
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }
    strcpy(buf, mDeviceName);
    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);

    if (deviceName != NULL && deviceName[0] != 0)
    {
        VerifyOrExit(strlen(deviceName) >= kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
        strcpy(mDeviceName, deviceName);
        mFlags.Set(Flags::kDeviceNameSet);
        ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", deviceName);
    }
    else
    {
        mDeviceName[0] = 0;
        mFlags.Clear(Flags::kDeviceNameSet);
    }

exit:
    return err;
}

void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
    switch (event->Type)
    {
    // Platform specific events
    case DeviceEventType::kCHIPoBLESubscribe:
        HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
        {
            ChipDeviceEvent connEstEvent;
            connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
            PlatformMgr().PostEventOrDie(&connEstEvent);
        }
        break;

    case DeviceEventType::kCHIPoBLEUnsubscribe: {
        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
        HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
    }
    break;

    case DeviceEventType::kCHIPoBLEWriteReceived: {
        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived");
        HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
                            PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
    }
    break;

    case DeviceEventType::kCHIPoBLEConnectionError: {
        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
        HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
    }
    break;

    case DeviceEventType::kCHIPoBLEIndicateConfirm: {
        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
        HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
    }
    break;

    case DeviceEventType::kServiceProvisioningChange:
    case DeviceEventType::kWiFiConnectivityChange:
        ChipLogProgress(DeviceLayer, "Updating advertising data");
        StartAdvertising();
        break;

    default:
        ChipLogProgress(DeviceLayer, "_OnPlatformEvent default:  event->Type = %d", event->Type);
        break;
    }
}

bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
    return false;
}

bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
    return false;
}

bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
{
    CHIP_ERROR err;
    ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
    uint32_t delay_time = 20;
    int ret;

    do
    {
        ret = bk_ble_disconnect(conId, beken_ble_cmd_cb);
        if (BK_ERR_BLE_SUCCESS == ret)
        {
            break;
        }

        rtos_delay_milliseconds(10);
        delay_time--;
    } while (delay_time);
    // Beken Ble close function
    err = MapBLEError(ret);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "bk_ble_disconnect() failed: %s", ErrorStr(err));
    }

    return false;
}

uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
{
    CHIPoBLEConState * conState = const_cast<BLEManagerImpl *>(this)->GetConnectionState(conId);
    return (conState != NULL) ? conState->mtu : 0;
}

bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                      PacketBufferHandle pBuf)
{
    ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
    return false;
}

bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                     PacketBufferHandle pBuf)
{
    ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
    return false;
}

bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
                                      const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
    return false;
}

void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
{
    // Nothing to do
}

bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                    PacketBufferHandle data)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    int ret;

    VerifyOrExit(IsSubscribed(conId), err = CHIP_ERROR_INVALID_ARGUMENT);
    ret = bk_ble_send_noti_value(conId, data->DataLength(), data->Start(), 0, SVR_FFF6_TX_VALUE);
    err = MapBLEError(ret);
exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
        return false;
    }

    return true;
}

/*******************************************************************************
 * Private functions
 *******************************************************************************/

CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    // If the device name is not specified, generate a CHIP-standard name based on the bottom digits of the Chip device id.
    uint16_t discriminator;
    SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator));

    if (!mFlags.Has(Flags::kDeviceNameSet))
    {
        snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
        mDeviceName[kMaxDeviceNameLength] = 0;
    }

    // Configure the BLE device name.
    sInstance.mFlags.Set(Flags::kDeviceNameDefSet);
    bk_ble_appm_set_dev_name(kMaxDeviceNameLength, (uint8_t *) mDeviceName);
exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
{
    ble_err_t bk_err;
    CHIP_ERROR err = CHIP_NO_ERROR;

    ChipLogProgress(DeviceLayer, "StartAdvertising...");
    ChipLogProgress(DeviceLayer, "BLE flag  = %x", mFlags.Raw());
    if ((!mFlags.Has(Flags::kDeviceNameSet)) && (!mFlags.Has(Flags::kDeviceNameDefSet)))
    {
        err = sInstance.ConfigureAdvertisingData();
        SuccessOrExit(err);
    }
    // Post a CHIPoBLEAdvertisingChange(Stopped) event.
    if (mFlags.Has(Flags::kBEKENBLEADVStop))
    {
        bk_ble_delete_advertising(adv_actv_idx, beken_ble_cmd_cb);
        mFlags.Clear(Flags::kBEKENBLEADVStop);
        ChipDeviceEvent advChange;
        advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
        advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
        PlatformMgr().PostEventOrDie(&advChange);
        goto exit;
    }
    else if (!mFlags.Has(Flags::kBEKENBLEADVCreate))
    {
        ChipLogProgress(DeviceLayer, "BLE ADVCreate...");
        uint16_t adv_int_min;
        uint16_t adv_int_max;
        ble_adv_param_t adv_param;

        memset(&adv_param, 0, sizeof(adv_param));

        if (mFlags.Has(Flags::kFastAdvertisingEnabled))
        {
            adv_int_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
            adv_int_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
            mFlags.Set(Flags::kAdvertisingIsFastADV);
        }
        else
        {
            adv_int_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
            adv_int_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
            mFlags.Clear(Flags::kAdvertisingIsFastADV);
        }

        adv_actv_idx = bk_ble_get_idle_actv_idx_handle();
        if (UNKNOW_ACT_IDX == adv_actv_idx)
        {
            ChipLogError(DeviceLayer, "adv act-idx:%d error", adv_actv_idx);
            return MapBLEError(-1);
        }
        adv_param.chnl_map      = 7;
        adv_param.adv_intv_max  = 160;
        adv_param.adv_intv_min  = 160;
        adv_param.own_addr_type = 0;
        adv_param.adv_type      = 0;
        adv_param.adv_prop      = 3;
        adv_param.prim_phy      = 1;
        // bk_ble_create_advertising(adv_actv_idx, 7, adv_int_min, adv_int_max, beken_ble_cmd_cb);
        bk_err = bk_ble_create_advertising(adv_actv_idx, &adv_param, beken_ble_cmd_cb);
        if (bk_err != BK_OK)
        {
            ChipLogProgress(DeviceLayer, "BLE ADVCreate ret= %x.", bk_err);
        }
        ChipLogProgress(DeviceLayer, "BLE ADVCreate ret= %x. adv_actv_idx = %x", bk_err, adv_actv_idx);
        sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
        goto exit;
    }
    else if (!mFlags.Has(Flags::kBEKENBLEADVSetData))
    {
        ChipLogProgress(DeviceLayer, "BLE SetData...");
        ChipBLEDeviceIdentificationInfo deviceIdInfo;
        uint8_t advData[MAX_ADV_DATA_LEN] = { 0 };
        uint8_t index                     = 0;
        /**************** Prepare advertising data *******************************************/
        memset(advData, 0, sizeof(advData));
        advData[index++] = 0x02;                     // length
        advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
        advData[index++] = CHIP_ADV_DATA_FLAGS;      // AD value
        advData[index++] = static_cast<uint8_t>(sizeof(deviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1);
        ;                                                             // length
        advData[index++] = 0x16;                                      // AD type: (Service Data - 16-bit UUID)
        advData[index++] = static_cast<uint8_t>(_svc_uuid[0] & 0xFF); // AD value
        advData[index++] = static_cast<uint8_t>(_svc_uuid[1] & 0xFF); // AD value
        err              = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(DeviceLayer, "GetBLEDeviceIdentificationInfo(): %s", ErrorStr(err));
            ExitNow();
        }

#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
        deviceIdInfo.SetAdditionalDataFlag(true);
#endif
        VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG);

        memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo));
        index = static_cast<uint8_t>(index + sizeof(deviceIdInfo));
        bk_ble_set_adv_data(adv_actv_idx, advData, index, beken_ble_cmd_cb);
        goto exit;
    }
    else if (!mFlags.Has(Flags::kBEKENBLEADVSetRsp))
    {
        /// uint8_t advData[MAX_ADV_DATA_LEN]    = { 0 };
        /// bk_ble_set_scan_rsp_data(adv_actv_idx, advData, 0xF, beken_ble_cmd_cb);
        sInstance.mFlags.Set(Flags::kBEKENBLEADVSetRsp);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        goto exit;
    }
    else if (!mFlags.Has(Flags::kBEKENBLEADVStarted))
    {
        ChipLogProgress(DeviceLayer, "BLE Started...");
        bk_ble_start_advertising(adv_actv_idx, 0, beken_ble_cmd_cb);
        goto exit;
    }

    if (mFlags.Has(Flags::kBEKENBLEADVStarted))
    {
        ChipDeviceEvent advChange;
        advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
        advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
        PlatformMgr().PostEventOrDie(&advChange);
    }

exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
{
    // Change flag status to the 'not Advertising state'
    if ((mFlags.Has(Flags::kBEKENBLEADVStarted)) && (!mFlags.Has(Flags::kBEKENBLEADVStop)))
    {
        mFlags.Set(Flags::kBEKENBLEADVStop);
        bk_ble_stop_advertising(adv_actv_idx, beken_ble_cmd_cb);
        ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopping");
        goto exit;
    }

    // Post a CHIPoBLEAdvertisingChange(Stopped) event.
    if (mFlags.Has(Flags::kBEKENBLEADVStop))
    {
        bk_ble_delete_advertising(adv_actv_idx, beken_ble_cmd_cb);
        mFlags.Clear(Flags::kBEKENBLEADVStop);
        ChipDeviceEvent advChange;
        advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
        advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
        PlatformMgr().PostEventOrDie(&advChange);
    }
exit:
    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr)
{
    switch (bleErr)
    {
    case BK_ERR_BLE_SUCCESS:
        return CHIP_NO_ERROR;
    default:
        return CHIP_ERROR_INCORRECT_STATE;
    }
}

void BLEManagerImpl::DriveBLEState(void)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    // Check if BLE stack is initialized
    VerifyOrExit(mFlags.Has(Flags::kAMEBABLEStackInitialized), /* */);
    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled)
    {
        if (!mFlags.Has(Flags::kBekenBLESGATTSReady))
        {
            beken_ble_init();
            goto exit;
        }
    }

    if ((!mFlags.Has(Flags::kFastAdvertisingEnabled)) && (!mFlags.Has(Flags::kSlowAdvertisingEnabled)))
    {
        mFlags.Clear(Flags::kAdvertisingEnabled);
        mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
    }

    if (mFlags.Has(Flags::kAdvertisingRefreshNeeded))
    {
        if (mFlags.Has(Flags::kBEKENBLEADVStarted))
        {
            err = StopAdvertising();
            SuccessOrExit(err);
            goto exit;
        }
        else if (mFlags.Has(Flags::kBEKENBLEADVStarted))
        {
            bk_ble_delete_advertising(adv_actv_idx, beken_ble_cmd_cb);
            goto exit;
        }
    }

    // Start advertising if needed...
    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
        ((mFlags.Has(Flags::kAdvertisingEnabled)) || (mFlags.Has(Flags::kAdvertisingRefreshNeeded))))
    {
        // Start/re-start advertising if not already started, or if there is a pending change
        // to the advertising configuration.
        if (!mFlags.Has(Flags::kBEKENBLEADVStarted))
        {
            err = StartAdvertising();
            SuccessOrExit(err);
        }
        else
        {
            mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
        }
    }
    // Otherwise, stop advertising if it is enabled.
    else if ((mFlags.Has(Flags::kBEKENBLEADVStarted)) || (mFlags.Has(Flags::kBEKENBLEADVStop)))
    {
        err = StopAdvertising();
        SuccessOrExit(err);
        ChipLogProgress(DeviceLayer, "Stopped Advertising");
    }

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
        mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
    }
}

void BLEManagerImpl::DriveBLEState(intptr_t arg)
{
    sInstance.DriveBLEState();
}

void BLEManagerImpl::DriveBLEExtPerf(intptr_t arg)
{
    int arg_int = static_cast<int>(arg);
    int event   = arg_int & 0xFFU;
    switch (event)
    {
    case DriveBLEExtPerfEvt_DISCONNECT: {
        uint8_t conn_indx = (arg_int >> 8) & 0xFFU;
        sInstance.CloseConnection(conn_indx);
    }
    break;
    default:
        break;
    }
}

/*******************************************************************************
 * FreeRTOS Task Management Functions
 *******************************************************************************/
void BLEManagerImpl::ble_adv_timer_timeout_handle(TimerHandle_t xTimer)
{
    if (sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled))
    {
        ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop Fast advertisement");

        sInstance.mFlags.Clear(Flags::kFastAdvertisingEnabled);
        // Stop advertising, change interval and restart it;
        sInstance.StopAdvertising();
    }
    else if (sInstance._IsAdvertisingEnabled())
    {
        // Advertisement time expired. Stop advertising
        ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop slow advertisement");
        sInstance.mFlags.Clear(Flags::kSlowAdvertisingEnabled);
        sInstance.StopAdvertising();
    }
}

void BLEManagerImpl::CancelBleAdvTimeoutTimer(void)
{
    if (xTimerIsTimerActive(bleFastAdvTimer))
    {
        if (xTimerStop(bleFastAdvTimer, 0) == pdFAIL)
        {
            ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer");
            sInstance.mFlags.Clear(Flags::kBEKENBLEAdvTimerRun);
        }
    }
}

void BLEManagerImpl::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs)
{
    CancelBleAdvTimeoutTimer();
    // timer is not active, change its period to required value (== restart).
    // FreeRTOS- Block for a maximum of 100 ticks if the change period command
    // cannot immediately be sent to the timer command queue.
    if (xTimerChangePeriod(bleFastAdvTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
    {
        ChipLogError(DeviceLayer, "Failed to start BledAdv timeout timer");
    }
    else
    {
        xTimerStart(bleFastAdvTimer, BEKEN_WAIT_FOREVER);
        sInstance.mFlags.Set(Flags::kBEKENBLEAdvTimerRun);
    }
}

CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId)
{
    CHIPoBLEConState * bleConnState = GetConnectionState(conId, false);

    if (bleConnState != NULL)
    {
        bleConnState->subscribed = 1;
        return CHIP_NO_ERROR;
    }

    return CHIP_ERROR_NO_MEMORY;
}

bool BLEManagerImpl::UnsetSubscribed(uint16_t conId)
{
    CHIPoBLEConState * bleConnState = GetConnectionState(conId, false);

    if (bleConnState != NULL)
    {
        bleConnState->subscribed = 0;
        return true;
    }

    return false;
}

bool BLEManagerImpl::IsSubscribed(uint16_t conId)
{
    CHIPoBLEConState * bleConnState = GetConnectionState(conId, false);

    if (bleConnState != NULL)
    {
        if (bleConnState->subscribed)
        {
            return true;
        }
    }
    return false;
}

void BLEManagerImpl::HandleRXCharWrite(uint8_t * p_value, uint16_t len, uint8_t conn_id)
{
    CHIP_ERROR err         = CHIP_NO_ERROR;
    PacketBufferHandle buf = System::PacketBufferHandle::New(len, 0);
    memcpy(buf->Start(), p_value, len);
    buf->SetDataLength(len);

    // Post an event to the Chip queue to deliver the data into the Chip stack.
    {
        ChipDeviceEvent event;
        event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
        event.CHIPoBLEWriteReceived.ConId = (uint16_t) conn_id;
        event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
        PlatformMgr().PostEventOrDie(&event);
    }

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
    }
}

void BLEManagerImpl::HandleTXCharConfirm(CHIPoBLEConState * conState, int status)
{
    // If the confirmation was successful...
    if (status == 0)
    {
        // Post an event to the Chip queue to process the indicate confirmation.
        ChipDeviceEvent event;
        event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
        event.CHIPoBLEIndicateConfirm.ConId = conState->conn_idx;
        PlatformMgr().PostEventOrDie(&event);
    }
    else
    {
        ChipDeviceEvent event;
        event.Type                           = DeviceEventType::kCHIPoBLEConnectionError;
        event.CHIPoBLEConnectionError.ConId  = conState->conn_idx;
        event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
        PlatformMgr().PostEventOrDie(&event);
    }
}

void BLEManagerImpl::beken_ble_cmd_cb(ble_cmd_t cmd, ble_cmd_param_t * param)
{
    ChipLogProgress(DeviceLayer, "cmd:%d idx:%d status:%d\r\n", cmd, param->cmd_idx, param->status);
    switch (cmd)
    {
    case BLE_CREATE_ADV:
        sInstance.mFlags.Set(Flags::kBEKENBLEADVCreate);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;
    case BLE_SET_ADV_DATA:
        sInstance.mFlags.Set(Flags::kBEKENBLEADVSetData);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;
    case BLE_SET_RSP_DATA:
        sInstance.mFlags.Set(Flags::kBEKENBLEADVSetRsp);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;
    case BLE_START_ADV: {
        uint32_t bleAdvTimeoutMs;
        sInstance.mFlags.Set(Flags::kBEKENBLEADVStarted);
        // if (sInstance.mFlags.Has(Flags::kAdvertisingIsFastADV)){
        bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME;
        //}else{
        //    bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT;
        //}
        StartBleAdvTimeoutTimer(bleAdvTimeoutMs);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }
    break;
    case BLE_STOP_ADV:
        sInstance.mFlags.Clear(Flags::kBEKENBLEADVStarted);
        ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
        CancelBleAdvTimeoutTimer();
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;
    case BLE_DELETE_ADV:
        sInstance.mFlags.Clear(Flags::kBEKENBLEADVCreate);
        sInstance.mFlags.Clear(Flags::kBEKENBLEADVSetData);
        sInstance.mFlags.Clear(Flags::kBEKENBLEADVSetRsp);
        sInstance.mFlags.Clear(Flags::kBEKENBLEADVStarted);
        sInstance.adv_actv_idx = kUnusedIndex;
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;
    case BLE_CONN_DIS_CONN:
        break;
    default:
        break;
    }
}

#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
void BLEManagerImpl::HandleC3CharRead(void * param)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    chip::System::PacketBufferHandle bufferHandle;
    ble_read_req_t * r_req = (ble_read_req_t *) param;

    AdditionalDataPayloadGeneratorParams additionalDataPayloadParams;
    BitFlags<AdditionalDataFields> additionalDataFields;

#if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID)
    uint8_t rotatingDeviceIdUniqueId[ConfigurationManager::kRotatingDeviceIDUniqueIDLength] = {};
    MutableByteSpan rotatingDeviceIdUniqueIdSpan(rotatingDeviceIdUniqueId);

    err = DeviceLayer::GetDeviceInstanceInfoProvider()->GetRotatingDeviceIdUniqueId(rotatingDeviceIdUniqueIdSpan);
    SuccessOrExit(err);
    err = ConfigurationMgr().GetLifetimeCounter(additionalDataPayloadParams.rotatingDeviceIdLifetimeCounter);
    SuccessOrExit(err);
    additionalDataPayloadParams.rotatingDeviceIdUniqueId = rotatingDeviceIdUniqueIdSpan;
    additionalDataFields.Set(AdditionalDataFields::RotatingDeviceId);
#endif /* CHIP_ENABLE_ROTATING_DEVICE_ID */

    err = AdditionalDataPayloadGenerator().generateAdditionalDataPayload(additionalDataPayloadParams, bufferHandle,
                                                                         additionalDataFields);
    SuccessOrExit(err);
    if (r_req->value == NULL)
    {
        ChipLogError(DeviceLayer, "param->value == NULL");
        return;
    }
    memcpy(r_req->value, bufferHandle->Start(), bufferHandle->DataLength());
    r_req->length = bufferHandle->DataLength();
exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data");
    }
    return;
}
#endif

void BLEManagerImpl::ble_event_notice(ble_notice_t notice, void * param)
{
    /// BLEManagerImpl * blemgr = static_cast<BLEManagerImpl *>(param);
    static int conn_idx = 0; // TODO. will improve this when driver notify the status and channel to app.
    switch (notice)
    {
    case BLE_5_STACK_OK: {
        ChipLogProgress(DeviceLayer, "ble stack ok");
        sInstance.mFlags.Set(Flags::kAMEBABLEStackInitialized);
    }
    break;
    case BLE_5_WRITE_EVENT: {
        ble_write_req_t * w_req = (ble_write_req_t *) param;
        ChipLogProgress(DeviceLayer, "write_cb:conn_idx:%d, prf_id:%d, add_id:%d, len:%d, data[0]:%02x\r\n", w_req->conn_idx,
                        w_req->prf_id, w_req->att_idx, w_req->len, w_req->value[0]);
        if (w_req->att_idx == SVR_FFF6_TX_VALUE)
        {
            sInstance.HandleRXCharWrite((uint8_t *) &w_req->value[0], w_req->len, w_req->conn_idx);
        }
        else if (w_req->att_idx == SVR_FFF6_TX_CFG)
        {
            int notificationsEnabled = w_req->value[0] | (w_req->value[0] << 8);
            sInstance.HandleTXCharCCCDWrite(w_req->conn_idx, notificationsEnabled);
        }
        else if (w_req->att_idx == SVR_FFF6_RX_VALUE)
        {
            sInstance.HandleRXCharWrite((uint8_t *) &w_req->value[0], w_req->len, w_req->conn_idx);
        }
        break;
    }
    case BLE_5_READ_EVENT: {
        ble_read_req_t * r_req = (ble_read_req_t *) param;
        ChipLogProgress(DeviceLayer, "read_cb:conn_idx:%d, prf_id:%d, add_id:%d\r\n", r_req->conn_idx, r_req->prf_id,
                        r_req->att_idx);
        if (r_req->att_idx == SVR_FFF6_RX_VALUE)
        {
            sInstance.HandleTXCharRead(param);
        }
        if (r_req->att_idx == SVR_FFF6_TX_CFG)
        {
            sInstance.HandleTXCharCCCDRead(param);
        }
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
        if (r_req->att_idx == SVR_FFF6_C3_VALUE)
        {
            ChipLogProgress(DeviceLayer, "SVR_FFF6_OPT_VALUE!!!!\r\n");
            sInstance.HandleTXCharRead((void *) param);
        }
#endif
        break;
    }
    case BLE_5_TX_DONE: {
        ChipLogProgress(DeviceLayer, "BLE_5_TX_DONE");
#if 0
        tx_done_rsp_t* txd_rsp = (tx_done_rsp_t*)param;
        if(txd_rsp) {
            CHIPoBLEConState * conState = sInstance.GetConnectionState(txd_rsp->conn_idx,false);
            if (conState != NULL)
            {
                sInstance.HandleTXCharConfirm(conState, txd_rsp->status);
            }
        }
#endif
        CHIPoBLEConState * conState = sInstance.GetConnectionState(conn_idx, false);
        if (conState != NULL)
        {
            sInstance.HandleTXCharConfirm(conState, 0);
        }
    }
    break;
    case BLE_5_MTU_CHANGE: {
        ble_mtu_change_t * m_ind = (ble_mtu_change_t *) param;
        ChipLogProgress(DeviceLayer, "m_ind:conn_idx:%d, mtu_size:%d\r\n", m_ind->conn_idx, m_ind->mtu_size);
        CHIPoBLEConState * conState = sInstance.GetConnectionState(m_ind->conn_idx);
        if (conState != NULL)
        {
            conState->mtu = (m_ind->mtu_size >= (1 << 10)) ? ((1 << 10) - 1) : m_ind->mtu_size;
        }
        break;
    }
    case BLE_5_CONNECT_EVENT: {
        ble_conn_ind_t * c_ind = (ble_conn_ind_t *) param;
        ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", c_ind->conn_idx);
        ChipLogProgress(DeviceLayer, "c_ind:conn_idx:%d, addr_type:%d, peer_addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n",
                        c_ind->conn_idx, c_ind->peer_addr_type, c_ind->peer_addr[0], c_ind->peer_addr[1], c_ind->peer_addr[2],
                        c_ind->peer_addr[3], c_ind->peer_addr[4], c_ind->peer_addr[5]);
        sInstance.mFlags.Clear(Flags::kBEKENBLEADVStarted);
        CHIPoBLEConState * bleConnState = sInstance.GetConnectionState(c_ind->conn_idx, true);
        if (bleConnState == NULL)
        {
            ChipLogError(DeviceLayer, "BLE_5_CONNECT_EVENT failed");
            int ext_evt = DriveBLEExtPerfEvt_DISCONNECT | (c_ind->conn_idx << 8);
            PlatformMgr().ScheduleWork(DriveBLEExtPerf, ext_evt);
        }
        conn_idx = c_ind->conn_idx;
        break;
    }
    case BLE_5_DISCONNECT_EVENT: {
        ble_discon_ind_t * d_ind = (ble_discon_ind_t *) param;
        ChipLogProgress(DeviceLayer, "d_ind:conn_idx:%d,reason:%d\r\n", d_ind->conn_idx, d_ind->reason);
        sInstance.HandleGAPDisconnect(d_ind->conn_idx, d_ind->reason);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;
    }
    case BLE_5_ATT_INFO_REQ: {
        ble_att_info_req_t * a_ind = (ble_att_info_req_t *) param;
        ChipLogProgress(DeviceLayer, "a_ind:conn_idx:%d\r\n", a_ind->conn_idx);
        if (SVR_FFF6_RX_VALUE == a_ind->att_idx)
        {
            a_ind->length = 512;
            a_ind->status = BK_ERR_BLE_SUCCESS;
        }
        else if (SVR_FFF6_TX_CFG == a_ind->att_idx)
        {
            a_ind->length = 2;
            a_ind->status = BK_ERR_BLE_SUCCESS;
        }
        break;
    }
    case BLE_5_CREATE_DB: {
        ble_create_db_t * cd_ind = (ble_create_db_t *) param;
        ChipLogProgress(DeviceLayer, "cd_ind:prf_id:%d, status:%d\r\n", cd_ind->prf_id, cd_ind->status);
        sInstance.mFlags.Set(Flags::kBekenBLESGATTSReady);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;
    }
    default: {
        ChipLogProgress(DeviceLayer, "Unhandled event:%x", notice);
    }
    break;
    }
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
