[NXP][platform][rw61x] Switch to using BLE mgr impl files from common nxp folder (#34349)

Signed-off-by: Martin Girardot <martin.girardot@nxp.com>
diff --git a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp
new file mode 100644
index 0000000..e977708
--- /dev/null
+++ b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp
@@ -0,0 +1,138 @@
+/*
+ *
+ *    Copyright (c) 2023-2024 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "BLEAdvertisingArbiter.h"
+
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <system/SystemError.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace BLEAdvertisingArbiter {
+namespace {
+
+// List of advertising requests ordered by priority
+sys_slist_t sRequests;
+
+// Cast an intrusive list node to the containing request object
+const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node)
+{
+    return *static_cast<const BLEAdvertisingArbiter::Request *>(node);
+}
+
+// Notify application about stopped advertising if the callback has been provided
+void NotifyAdvertisingStopped(const sys_snode_t * node)
+{
+    VerifyOrReturn(node);
+
+    const Request & request = ToRequest(node);
+
+    if (request.onStopped != nullptr)
+    {
+        request.onStopped();
+    }
+}
+
+// Restart advertising using the top-priority request
+CHIP_ERROR RestartAdvertising()
+{
+    // Note: bt_le_adv_stop() returns success when the advertising was not started
+    ReturnErrorOnFailure(MapErrorZephyr(bt_le_adv_stop()));
+    ReturnErrorCodeIf(sys_slist_is_empty(&sRequests), CHIP_NO_ERROR);
+
+    const Request & top          = ToRequest(sys_slist_peek_head(&sRequests));
+    const bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr);
+    const int result = bt_le_adv_start(&params, top.advertisingData.data(), top.advertisingData.size(), top.scanResponseData.data(),
+                                       top.scanResponseData.size());
+
+    if (top.onStarted != nullptr)
+    {
+        top.onStarted(result);
+    }
+
+    return MapErrorZephyr(result);
+}
+
+} // namespace
+
+CHIP_ERROR InsertRequest(Request & request)
+{
+    CancelRequest(request);
+
+    sys_snode_t * prev = nullptr;
+    sys_snode_t * node = nullptr;
+
+    // Find position of the request in the list that preserves ordering by priority
+    SYS_SLIST_FOR_EACH_NODE(&sRequests, node)
+    {
+        if (request.priority < ToRequest(node).priority)
+        {
+            break;
+        }
+
+        prev = node;
+    }
+
+    if (prev == nullptr)
+    {
+        NotifyAdvertisingStopped(sys_slist_peek_head(&sRequests));
+        sys_slist_prepend(&sRequests, &request);
+    }
+    else
+    {
+        sys_slist_insert(&sRequests, prev, &request);
+    }
+
+    // If the request is top-priority, restart the advertising
+    if (sys_slist_peek_head(&sRequests) == &request)
+    {
+        return RestartAdvertising();
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+void CancelRequest(Request & request)
+{
+    const bool isTopPriority = (sys_slist_peek_head(&sRequests) == &request);
+    VerifyOrReturn(sys_slist_find_and_remove(&sRequests, &request));
+
+    // If cancelled request was top-priority, restart the advertising.
+    if (isTopPriority)
+    {
+        RestartAdvertising();
+    }
+}
+
+} // namespace BLEAdvertisingArbiter
+
+/**
+ * This implements a mapping function for CHIP System Layer errors that allows mapping integers in the number space of the
+ * Zephyr OS user API stack errors into the POSIX range.
+ *
+ *  @param[in] aError  The native Zephyr API error to map.
+ *
+ *  @return The mapped POSIX error.
+ */
+DLL_EXPORT CHIP_ERROR MapErrorZephyr(int aError)
+{
+    return chip::System::Internal::MapErrorPOSIX(-aError);
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h
new file mode 100644
index 0000000..9c00edb
--- /dev/null
+++ b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h
@@ -0,0 +1,107 @@
+/*
+ *
+ *    Copyright (c) 2023-2024 Project CHIP Authors
+ *
+ *    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.
+ */
+
+#pragma once
+
+#include <lib/support/Span.h>
+
+#include <zephyr/bluetooth/bluetooth.h>
+#include <zephyr/sys/slist.h>
+
+#include <cstdint>
+
+/**
+ * @file
+ *   Bluetooth LE advertising arbiter.
+ *
+ * The purpose for this module is to coordinate BLE advertising between
+ * different application components.
+ *
+ * An application component that wants to advertise BLE services is expected to
+ * define a request with a desired priority, and pass it to the BLE advertising
+ * arbiter. If there are multiple components that request BLE advertising at the
+ * same time, the arbiter selects the one with the highest priority (represented
+ * by the lowest numeric value) and starts the BLE advertising using parameters
+ * defined in the winning request.
+ *
+ * The BLE arbiter does not take ownership of a submitted request, so the
+ * request object must be sustained until it is cancelled by the application.
+ */
+
+namespace chip {
+namespace DeviceLayer {
+namespace BLEAdvertisingArbiter {
+
+using OnAdvertisingStarted = void (*)(int result);
+using OnAdvertisingStopped = void (*)();
+
+struct Request : public sys_snode_t
+{
+    uint8_t priority;                     ///< Advertising request priority. Lower value means higher priority
+    uint32_t options;                     ///< Advertising options: bitmask of BT_LE_ADV_OPT_XXX constants from Zephyr
+    uint16_t minInterval;                 ///< Minimum advertising interval in 0.625 ms units
+    uint16_t maxInterval;                 ///< Maximum advertising interval in 0.625 ms units
+    Span<const bt_data> advertisingData;  ///< Advertising data fields
+    Span<const bt_data> scanResponseData; ///< Scan response data fields
+    OnAdvertisingStarted onStarted;       ///< (Optional) Callback invoked when the request becomes top-priority.
+    OnAdvertisingStopped onStopped;       ///< (Optional) Callback invoked when the request stops being top-priority.
+};
+
+/**
+ * @brief Request BLE advertising
+ *
+ * Add the request to the internal list of competing requests. If the request
+ * has higher priority than other requests in the list, restart the BLE
+ * advertising immediately using parameters defined in the new request.
+ *
+ * Inserting a request object that is already registered at the advertising
+ * arbiter automatically cancels the previous request.
+ *
+ * @note This method does not take ownership of the request object so the object
+ *       must not get destroyed before it is cancelled.
+ *
+ * @param request   Reference to advertising request that contains priority and
+ *                  other advertising parameters.
+ * @return error    If the request is top-priority and failed to restart the
+ *                  advertising.
+ * @return success  Otherwise.
+ */
+CHIP_ERROR InsertRequest(Request & request);
+
+/**
+ * @brief Cancel BLE advertising request
+ *
+ * Remove the request from the internal list of competing requests. If the
+ * request is the winning (top-priority) one at the time of calling this
+ * function, restart the BLE advertising using parameters defined in the 2nd
+ * top-priority request in the list, or stop the BLE advertising completely if
+ * this is the last request in the list.
+ *
+ * An attempt to cancel a request that has not been registered at the
+ * advertising arbiter is a no-op. That is, it returns immediately.
+ *
+ * @param request   Reference to advertising request that contains priority and
+ *                  other advertising parameters.
+ */
+void CancelRequest(Request & request);
+
+} // namespace BLEAdvertisingArbiter
+
+extern CHIP_ERROR MapErrorZephyr(int code);
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp
new file mode 100644
index 0000000..0b98603
--- /dev/null
+++ b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp
@@ -0,0 +1,849 @@
+/*
+ *
+ *    Copyright (c) 2020-2022, 2024 Project CHIP Authors
+ *
+ *    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 Zephyr platforms.
+ */
+
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include "BLEManagerImpl.h"
+
+#include <ble/CHIPBleServiceData.h>
+#include <lib/support/CHIPMemString.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <platform/DeviceInstanceInfoProvider.h>
+#include <platform/internal/BLEManager.h>
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+#include <setup_payload/AdditionalDataPayloadGenerator.h>
+#endif
+
+#include <zephyr/bluetooth/addr.h>
+#include <zephyr/bluetooth/gatt.h>
+#include <zephyr/bluetooth/hci.h>
+#include <zephyr/random/random.h>
+#include <zephyr/sys/byteorder.h>
+#include <zephyr/sys/util.h>
+
+#include <array>
+
+using namespace ::chip;
+using namespace ::chip::Ble;
+using namespace ::chip::System;
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+namespace {
+
+constexpr uint32_t kAdvertisingOptions = BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME;
+constexpr uint8_t kAdvertisingFlags    = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR;
+
+const bt_uuid_128 UUID128_CHIPoBLEChar_RX =
+    BT_UUID_INIT_128(0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18);
+const bt_uuid_128 UUID128_CHIPoBLEChar_TX =
+    BT_UUID_INIT_128(0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18);
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+const bt_uuid_128 UUID128_CHIPoBLEChar_C3 =
+    BT_UUID_INIT_128(0x04, 0x8F, 0x21, 0x83, 0x8A, 0x74, 0x7D, 0xB8, 0xF2, 0x45, 0x72, 0x87, 0x38, 0x02, 0x63, 0x64);
+#endif
+
+bt_uuid_16 UUID16_CHIPoBLEService = BT_UUID_INIT_16(0xFFF6);
+
+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 } };
+
+_bt_gatt_ccc CHIPoBLEChar_TX_CCC = BT_GATT_CCC_INITIALIZER(nullptr, BLEManagerImpl::HandleTXCCCWrite, nullptr);
+
+// clang-format off
+
+bt_gatt_attr sChipoBleAttributes[] = {
+    BT_GATT_PRIMARY_SERVICE(&UUID16_CHIPoBLEService.uuid),
+        BT_GATT_CHARACTERISTIC(&UUID128_CHIPoBLEChar_RX.uuid,
+                               BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
+                               BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
+                               nullptr, BLEManagerImpl::HandleRXWrite, nullptr),
+        BT_GATT_CHARACTERISTIC(&UUID128_CHIPoBLEChar_TX.uuid,
+                               BT_GATT_CHRC_INDICATE,
+                               BT_GATT_PERM_NONE,
+                               nullptr, nullptr, nullptr),
+        BT_GATT_CCC_MANAGED(&CHIPoBLEChar_TX_CCC, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+        BT_GATT_CHARACTERISTIC(&UUID128_CHIPoBLEChar_C3.uuid,
+                               BT_GATT_CHRC_READ,
+                               BT_GATT_PERM_READ,
+                               BLEManagerImpl::HandleC3Read, nullptr, nullptr),
+#endif
+};
+
+bt_gatt_service sChipoBleService = BT_GATT_SERVICE(sChipoBleAttributes);
+
+// clang-format on
+
+// Index of the CCC descriptor in the CHIPoBLE_Service array of attributes.
+// This value should be adjusted accordingly if the service declaration changes.
+constexpr int kCHIPoBLE_CCC_AttributeIndex = 3;
+
+CHIP_ERROR InitRandomStaticAddress()
+{
+    // Generate a random static address for the default identity.
+    // This must be done before bt_enable() as after that updating the default identity is not possible.
+    int error = 0;
+    bt_addr_le_t addr;
+
+    // generating the address
+    addr.type = BT_ADDR_LE_RANDOM;
+    error     = sys_csrand_get(addr.a.val, sizeof(addr.a.val));
+    BT_ADDR_SET_STATIC(&addr.a);
+
+    if (error)
+    {
+        ChipLogError(DeviceLayer, "Failed to create BLE address: %d", error);
+        return MapErrorZephyr(error);
+    }
+
+    error = bt_id_create(&addr, nullptr);
+
+    if (error < 0)
+    {
+        ChipLogError(DeviceLayer, "Failed to create BLE identity: %d", error);
+        return MapErrorZephyr(error);
+    }
+
+    ChipLogProgress(DeviceLayer, "BLE address: %02X:%02X:%02X:%02X:%02X:%02X", addr.a.val[5], addr.a.val[4], addr.a.val[3],
+                    addr.a.val[2], addr.a.val[1], addr.a.val[0]);
+    return CHIP_NO_ERROR;
+}
+
+} // unnamed namespace
+
+BLEManagerImpl BLEManagerImpl::sInstance;
+
+CHIP_ERROR BLEManagerImpl::_Init()
+{
+    mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
+    mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
+    mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+    mGAPConns = 0;
+
+    memset(mSubscribedConns, 0, sizeof(mSubscribedConns));
+
+    ReturnErrorOnFailure(InitRandomStaticAddress());
+    int err = bt_enable(NULL);
+    VerifyOrReturnError(err == 0, MapErrorZephyr(err));
+
+    memset(&mConnCallbacks, 0, sizeof(mConnCallbacks));
+    mConnCallbacks.connected    = HandleConnect;
+    mConnCallbacks.disconnected = HandleDisconnect;
+
+    bt_conn_cb_register(&mConnCallbacks);
+
+    // Initialize the CHIP BleLayer.
+    ReturnErrorOnFailure(BleLayer::Init(this, this, &DeviceLayer::SystemLayer()));
+
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+
+    return CHIP_NO_ERROR;
+}
+
+void BLEManagerImpl::DriveBLEState(intptr_t arg)
+{
+    BLEMgrImpl().DriveBLEState();
+}
+
+void BLEManagerImpl::DriveBLEState()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    // Perform any initialization actions that must occur after the CHIP task is running.
+    if (!mFlags.Has(Flags::kAsyncInitCompleted))
+    {
+        mFlags.Set(Flags::kAsyncInitCompleted);
+    }
+
+    // If the application has enabled CHIPoBLE and BLE advertising...
+    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
+        mFlags.Has(Flags::kAdvertisingEnabled)
+#if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
+        // and no connections are active...
+        && (NumConnections() == 0)
+#endif
+    )
+    {
+        // Start/re-start advertising if not already advertising, or if the
+        // advertising state needs to be refreshed.
+        if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
+        {
+            mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
+            err = StartAdvertising();
+            SuccessOrExit(err);
+        }
+    }
+    else
+    {
+        if (mFlags.Has(Flags::kAdvertising))
+        {
+            err = StopAdvertising();
+            SuccessOrExit(err);
+        }
+
+        // If no connections are active unregister also CHIPoBLE GATT service
+        if (NumConnections() == 0 && mFlags.Has(Flags::kChipoBleGattServiceRegister))
+        {
+            // Unregister CHIPoBLE service to not allow discovering it when pairing is disabled.
+            if (bt_gatt_service_unregister(&sChipoBleService) != 0)
+            {
+                ChipLogError(DeviceLayer, "Failed to unregister CHIPoBLE GATT service");
+            }
+            else
+            {
+                mFlags.Clear(Flags::kChipoBleGattServiceRegister);
+            }
+        }
+    }
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format());
+        mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
+    }
+}
+
+struct BLEManagerImpl::ServiceData
+{
+    uint8_t uuid[2];
+    ChipBLEDeviceIdentificationInfo deviceIdInfo;
+} __attribute__((packed));
+
+inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest()
+{
+    static ServiceData serviceData;
+    static std::array<bt_data, 2> advertisingData;
+    static std::array<bt_data, 1> scanResponseData;
+    static_assert(sizeof(serviceData) == 10, "Unexpected size of BLE advertising data!");
+
+    const char * name      = bt_get_name();
+    const uint8_t nameSize = static_cast<uint8_t>(strlen(name));
+
+    Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val);
+    ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo));
+
+    advertisingData[0]  = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags));
+    advertisingData[1]  = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData));
+    scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize);
+
+    mAdvertisingRequest.priority         = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY;
+    mAdvertisingRequest.options          = kAdvertisingOptions;
+    mAdvertisingRequest.minInterval      = mFlags.Has(Flags::kFastAdvertisingEnabled)
+             ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN
+             : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
+    mAdvertisingRequest.maxInterval      = mFlags.Has(Flags::kFastAdvertisingEnabled)
+             ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX
+             : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
+    mAdvertisingRequest.advertisingData  = Span<bt_data>(advertisingData);
+    mAdvertisingRequest.scanResponseData = nameSize ? Span<bt_data>(scanResponseData) : Span<bt_data>{};
+
+    mAdvertisingRequest.onStarted = [](int rc) {
+        if (rc == 0)
+        {
+            ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
+        }
+        else
+        {
+            ChipLogError(DeviceLayer, "Failed to start CHIPoBLE advertising: %d", rc);
+        }
+    };
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::StartAdvertising()
+{
+    // Prepare advertising request
+    ReturnErrorOnFailure(PrepareAdvertisingRequest());
+
+    // Register dynamically CHIPoBLE GATT service
+    if (!mFlags.Has(Flags::kChipoBleGattServiceRegister))
+    {
+        int err = bt_gatt_service_register(&sChipoBleService);
+
+        if (err != 0)
+            ChipLogError(DeviceLayer, "Failed to register CHIPoBLE GATT service");
+
+        VerifyOrReturnError(err == 0, MapErrorZephyr(err));
+
+        mFlags.Set(Flags::kChipoBleGattServiceRegister);
+    }
+
+    // Initialize C3 characteristic data
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    ReturnErrorOnFailure(PrepareC3CharData());
+#endif
+
+    // Request advertising
+    ReturnErrorOnFailure(BLEAdvertisingArbiter::InsertRequest(mAdvertisingRequest));
+
+    // Transition to the Advertising state...
+    if (!mFlags.Has(Flags::kAdvertising))
+    {
+        mFlags.Set(Flags::kAdvertising);
+
+        // Post a CHIPoBLEAdvertisingChange(Started) event.
+        {
+            ChipDeviceEvent advChange;
+            advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
+            advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
+            ReturnErrorOnFailure(PlatformMgr().PostEvent(&advChange));
+        }
+
+        if (mFlags.Has(Flags::kFastAdvertisingEnabled))
+        {
+            // Start timer to change advertising interval.
+            DeviceLayer::SystemLayer().StartTimer(
+                System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME),
+                HandleBLEAdvertisementIntervalChange, this);
+        }
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::StopAdvertising()
+{
+    BLEAdvertisingArbiter::CancelRequest(mAdvertisingRequest);
+
+    // Transition to the not Advertising state...
+    if (mFlags.Has(Flags::kAdvertising))
+    {
+        mFlags.Clear(Flags::kAdvertising);
+        mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+
+        ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
+
+        // Post a CHIPoBLEAdvertisingChange(Stopped) event.
+        {
+            ChipDeviceEvent advChange;
+            advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
+            advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
+            ReturnErrorOnFailure(PlatformMgr().PostEvent(&advChange));
+        }
+
+        // Cancel timer event changing CHIPoBLE advertisement interval
+        DeviceLayer::SystemLayer().CancelTimer(HandleBLEAdvertisementIntervalChange, this);
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
+{
+    if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
+    {
+        ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off");
+
+        mFlags.Set(Flags::kAdvertisingEnabled, val);
+        PlatformMgr().ScheduleWork(DriveBLEState, 0);
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+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)
+{
+    Platform::CopyString(buf, bufSize, bt_get_name());
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
+{
+    ChipLogDetail(DeviceLayer, "Device name set to: %s", deviceName);
+    return MapErrorZephyr(bt_set_name(deviceName));
+}
+
+CHIP_ERROR BLEManagerImpl::HandleGAPConnect(const ChipDeviceEvent * event)
+{
+    const BleConnEventType * connEvent = &event->Platform.BleConnEvent;
+
+    if (connEvent->HciResult == BT_HCI_ERR_SUCCESS)
+    {
+        ChipLogProgress(DeviceLayer, "BLE connection established (ConnId: 0x%02x)", bt_conn_index(connEvent->BtConn));
+        mGAPConns++;
+    }
+    else
+    {
+        ChipLogError(DeviceLayer, "BLE connection failed (reason: 0x%02x)", connEvent->HciResult);
+    }
+
+    ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), CONFIG_BT_MAX_CONN);
+
+    mFlags.Set(Flags::kAdvertisingRefreshNeeded);
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+
+    bt_conn_unref(connEvent->BtConn);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event)
+{
+    const BleConnEventType * connEvent = &event->Platform.BleConnEvent;
+
+    ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (reason 0x%02x)", connEvent->HciResult);
+
+    mGAPConns--;
+
+    // If indications were enabled for this connection, record that they are now disabled and
+    // notify the BLE Layer of a disconnect.
+    if (UnsetSubscribed(connEvent->BtConn))
+    {
+        CHIP_ERROR disconReason;
+        switch (connEvent->HciResult)
+        {
+        case BT_HCI_ERR_REMOTE_USER_TERM_CONN:
+            // Do not treat proper connection termination as an error and exit.
+            VerifyOrExit(!ConfigurationMgr().IsFullyProvisioned(), );
+            disconReason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
+            break;
+        case BT_HCI_ERR_LOCALHOST_TERM_CONN:
+            disconReason = BLE_ERROR_APP_CLOSED_CONNECTION;
+            break;
+        default:
+            disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
+            break;
+        }
+        HandleConnectionError(connEvent->BtConn, disconReason);
+    }
+
+exit:
+    // Unref bt_conn before scheduling DriveBLEState.
+    bt_conn_unref(connEvent->BtConn);
+
+    ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), CONFIG_BT_MAX_CONN);
+
+    ChipDeviceEvent disconnectEvent;
+    disconnectEvent.Type = DeviceEventType::kCHIPoBLEConnectionClosed;
+    ReturnErrorOnFailure(PlatformMgr().PostEvent(&disconnectEvent));
+
+    // Force a reconfiguration of advertising in case we switched to non-connectable mode when
+    // the BLE connection was established.
+    mFlags.Set(Flags::kAdvertisingRefreshNeeded);
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event)
+{
+    const BleCCCWriteEventType * writeEvent = &event->Platform.BleCCCWriteEvent;
+
+    ChipLogDetail(DeviceLayer, "ConnId: 0x%02x, New CCCD value: 0x%04x", bt_conn_index(writeEvent->BtConn), writeEvent->Value);
+
+    // If the client has requested to enable indications and if it is not yet subscribed
+    if (writeEvent->Value == BT_GATT_CCC_INDICATE && SetSubscribed(writeEvent->BtConn))
+    {
+        // Alert the BLE layer that CHIPoBLE "subscribe" has been received and increment the bt_conn reference counter.
+        HandleSubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
+
+        ChipLogProgress(DeviceLayer, "CHIPoBLE connection established (ConnId: 0x%02x, GATT MTU: %u)",
+                        bt_conn_index(writeEvent->BtConn), GetMTU(writeEvent->BtConn));
+
+        // Post a CHIPoBLEConnectionEstablished event to the DeviceLayer and the application.
+        {
+            ChipDeviceEvent conEstEvent;
+            conEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
+            ReturnErrorOnFailure(PlatformMgr().PostEvent(&conEstEvent));
+        }
+    }
+    else
+    {
+        if (UnsetSubscribed(writeEvent->BtConn))
+        {
+            HandleUnsubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
+        }
+    }
+
+    bt_conn_unref(writeEvent->BtConn);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::HandleRXCharWrite(const ChipDeviceEvent * event)
+{
+    const BleC1WriteEventType * c1WriteEvent = &event->Platform.BleC1WriteEvent;
+
+    ChipLogDetail(DeviceLayer, "Write request received for CHIPoBLE RX characteristic (ConnId 0x%02x)",
+                  bt_conn_index(c1WriteEvent->BtConn));
+
+    HandleWriteReceived(c1WriteEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
+                        PacketBufferHandle::Adopt(c1WriteEvent->Data));
+    bt_conn_unref(c1WriteEvent->BtConn);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::HandleTXCharComplete(const ChipDeviceEvent * event)
+{
+    const BleC2IndDoneEventType * c2IndDoneEvent = &event->Platform.BleC2IndDoneEvent;
+
+    ChipLogDetail(DeviceLayer, "Indication for CHIPoBLE TX characteristic done (ConnId 0x%02x, result 0x%02x)",
+                  bt_conn_index(c2IndDoneEvent->BtConn), c2IndDoneEvent->Result);
+
+    // Signal the BLE Layer that the outstanding indication is complete.
+    HandleIndicationConfirmation(c2IndDoneEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
+    bt_conn_unref(c2IndDoneEvent->BtConn);
+
+    return CHIP_NO_ERROR;
+}
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+CHIP_ERROR BLEManagerImpl::PrepareC3CharData()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    BitFlags<AdditionalDataFields> additionalDataFields;
+    AdditionalDataPayloadGeneratorParams additionalDataPayloadParams;
+
+#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 && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) */
+
+    err = AdditionalDataPayloadGenerator().generateAdditionalDataPayload(additionalDataPayloadParams, c3CharDataBufferHandle,
+                                                                         additionalDataFields);
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data (%s)", __func__);
+    }
+
+    return err;
+}
+#endif
+
+void BLEManagerImpl::HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param)
+{
+    BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising);
+    ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to slow");
+}
+
+void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    switch (event->Type)
+    {
+    case DeviceEventType::kPlatformZephyrBleConnected:
+        err = HandleGAPConnect(event);
+        break;
+
+    case DeviceEventType::kPlatformZephyrBleDisconnected:
+        err = HandleGAPDisconnect(event);
+        break;
+
+    case DeviceEventType::kPlatformZephyrBleCCCWrite:
+        err = HandleTXCharCCCDWrite(event);
+        break;
+
+    case DeviceEventType::kPlatformZephyrBleC1WriteEvent:
+        err = HandleRXCharWrite(event);
+        break;
+
+    case DeviceEventType::kPlatformZephyrBleC2IndDoneEvent:
+        err = HandleTXCharComplete(event);
+        break;
+
+    default:
+        break;
+    }
+
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format());
+        mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
+        PlatformMgr().ScheduleWork(DriveBLEState, 0);
+    }
+}
+
+uint16_t BLEManagerImpl::_NumConnections(void)
+{
+    return mGAPConns;
+}
+
+bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
+{
+    ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (ConnId %02x)", bt_conn_index(conId));
+    return bt_conn_disconnect(conId, BT_HCI_ERR_REMOTE_USER_TERM_CONN) == 0;
+}
+
+uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
+{
+    return bt_gatt_get_mtu(conId);
+}
+
+bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+    ChipLogDetail(DeviceLayer, "BLE central not implemented");
+    return false;
+}
+
+bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+    ChipLogDetail(DeviceLayer, "BLE central not implemented");
+    return false;
+}
+
+bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                    PacketBufferHandle pBuf)
+{
+    CHIP_ERROR err                   = CHIP_NO_ERROR;
+    int status                       = 0;
+    uint8_t index                    = bt_conn_index(conId);
+    bt_gatt_indicate_params * params = &mIndicateParams[index];
+
+    VerifyOrExit(IsSubscribed(conId) == true, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+    ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE TX characteristic (ConnId %02x, len %u)", index,
+                  pBuf->DataLength());
+
+    params->uuid = nullptr;
+    params->attr = &sChipoBleAttributes[kCHIPoBLE_CCC_AttributeIndex];
+    params->func = HandleTXIndicated;
+    params->data = pBuf->Start();
+    params->len  = pBuf->DataLength();
+
+    status = bt_gatt_indicate(conId, params);
+    VerifyOrExit(status == 0, err = MapErrorZephyr(status));
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %" CHIP_ERROR_FORMAT, err.Format());
+    }
+
+    return err == CHIP_NO_ERROR;
+}
+
+bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                      PacketBufferHandle pBuf)
+{
+    ChipLogDetail(DeviceLayer, "BLE central not implemented");
+    return false;
+}
+
+bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                     PacketBufferHandle pBuf)
+{
+    ChipLogDetail(DeviceLayer, "BLE central not implemented");
+    return false;
+}
+
+bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
+                                      const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+    ChipLogDetail(DeviceLayer, "BLE central not implemented");
+    return false;
+}
+
+void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
+{
+    CloseConnection(conId);
+}
+
+bool BLEManagerImpl::IsSubscribed(bt_conn * conn)
+{
+    return mSubscribedConns[bt_conn_index(conn)];
+}
+
+bool BLEManagerImpl::SetSubscribed(bt_conn * conn)
+{
+    uint8_t index           = bt_conn_index(conn);
+    bool isSubscribed       = mSubscribedConns[index];
+    mSubscribedConns[index] = true;
+
+    // If we were not subscribed previously, increment the reference counter of the connection.
+    if (!isSubscribed)
+    {
+        bt_conn_ref(conn);
+    }
+
+    return !isSubscribed;
+}
+
+bool BLEManagerImpl::UnsetSubscribed(bt_conn * conn)
+{
+    uint8_t index           = bt_conn_index(conn);
+    bool isSubscribed       = mSubscribedConns[index];
+    mSubscribedConns[index] = false;
+
+    // If we were subscribed previously, decrement the reference counter of the connection.
+    if (isSubscribed)
+    {
+        bt_conn_unref(conn);
+    }
+
+    return isSubscribed;
+}
+
+ssize_t BLEManagerImpl::HandleRXWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, const void * buf, uint16_t len,
+                                      uint16_t offset, uint8_t flags)
+{
+    ChipDeviceEvent event;
+    PacketBufferHandle packetBuf = PacketBufferHandle::NewWithData(buf, len);
+
+    if (!packetBuf.IsNull())
+    {
+        // Arrange to post a CHIPoBLERXWriteEvent event to the CHIP queue.
+        event.Type                            = DeviceEventType::kPlatformZephyrBleC1WriteEvent;
+        event.Platform.BleC1WriteEvent.BtConn = bt_conn_ref(conId);
+        event.Platform.BleC1WriteEvent.Data   = std::move(packetBuf).UnsafeRelease();
+    }
+
+    // If we failed to allocate a buffer, post a kPlatformZephyrBleOutOfBuffersEvent event.
+    else
+    {
+        event.Type = DeviceEventType::kPlatformZephyrBleOutOfBuffersEvent;
+    }
+
+    PlatformMgr().PostEventOrDie(&event);
+
+    return len;
+}
+
+ssize_t BLEManagerImpl::HandleTXCCCWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, uint16_t value)
+{
+    ChipDeviceEvent event;
+
+    if (value != BT_GATT_CCC_INDICATE && value != 0)
+    {
+        return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
+    }
+
+    event.Type                             = DeviceEventType::kPlatformZephyrBleCCCWrite;
+    event.Platform.BleCCCWriteEvent.BtConn = bt_conn_ref(conId);
+    event.Platform.BleCCCWriteEvent.Value  = value;
+
+    PlatformMgr().PostEventOrDie(&event);
+
+    return sizeof(value);
+}
+
+void BLEManagerImpl::HandleTXIndicated(struct bt_conn * conId, bt_gatt_indicate_params *, uint8_t err)
+{
+    ChipDeviceEvent event;
+
+    event.Type                              = DeviceEventType::kPlatformZephyrBleC2IndDoneEvent;
+    event.Platform.BleC2IndDoneEvent.BtConn = bt_conn_ref(conId);
+    event.Platform.BleC2IndDoneEvent.Result = err;
+
+    PlatformMgr().PostEventOrDie(&event);
+}
+
+void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err)
+{
+    ChipDeviceEvent event;
+
+    PlatformMgr().LockChipStack();
+
+    // Don't handle BLE connecting events when it is not related to CHIPoBLE
+    VerifyOrExit(sInstance.mFlags.Has(Flags::kChipoBleGattServiceRegister), );
+
+    event.Type                            = DeviceEventType::kPlatformZephyrBleConnected;
+    event.Platform.BleConnEvent.BtConn    = bt_conn_ref(conId);
+    event.Platform.BleConnEvent.HciResult = err;
+
+    PlatformMgr().PostEventOrDie(&event);
+
+exit:
+    PlatformMgr().UnlockChipStack();
+}
+
+void BLEManagerImpl::HandleDisconnect(struct bt_conn * conId, uint8_t reason)
+{
+    ChipDeviceEvent event;
+
+    PlatformMgr().LockChipStack();
+
+    // Don't handle BLE disconnecting events when it is not related to CHIPoBLE
+    VerifyOrExit(sInstance.mFlags.Has(Flags::kChipoBleGattServiceRegister), );
+
+    event.Type                            = DeviceEventType::kPlatformZephyrBleDisconnected;
+    event.Platform.BleConnEvent.BtConn    = bt_conn_ref(conId);
+    event.Platform.BleConnEvent.HciResult = reason;
+
+    PlatformMgr().PostEventOrDie(&event);
+
+exit:
+    PlatformMgr().UnlockChipStack();
+}
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+ssize_t BLEManagerImpl::HandleC3Read(struct bt_conn * conId, const struct bt_gatt_attr * attr, void * buf, uint16_t len,
+                                     uint16_t offset)
+{
+    ChipLogDetail(DeviceLayer, "Read request received for CHIPoBLE C3 (ConnId 0x%02x)", bt_conn_index(conId));
+
+    if (sInstance.c3CharDataBufferHandle.IsNull())
+    {
+        return 0;
+    }
+
+    return bt_gatt_attr_read(conId, attr, buf, len, offset, sInstance.c3CharDataBufferHandle->Start(),
+                             sInstance.c3CharDataBufferHandle->DataLength());
+}
+#endif
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
diff --git a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h
index 411392a..e80faeb 100644
--- a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h
+++ b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h
@@ -1,8 +1,6 @@
 /*
  *
- *    Copyright (c) 2020-2021 Project CHIP Authors
- *    Copyright (c) 2020 Nest Labs, Inc.
- *    All rights reserved.
+ *    Copyright (c) 2020-2021, 2024 Project CHIP Authors
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -20,12 +18,180 @@
 /**
  *    @file
  *          Provides an implementation of the BLEManager singleton object
- *          for the nxp platforms.
+ *          for the NXP platforms.
  */
 
 #pragma once
 
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include "BLEAdvertisingArbiter.h"
+
+#include <zephyr/bluetooth/bluetooth.h>
+#include <zephyr/bluetooth/conn.h>
+#include <zephyr/bluetooth/gatt.h>
+
 #include <lib/support/CHIPMemString.h>
-#include <platform/Zephyr/BLEManagerImpl.h>
 #include <sys/atomic.h>
 #include <toolchain.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+using namespace chip::Ble;
+
+/**
+ * Concrete implementation of the BLEManager singleton object for the Zephyr platforms.
+ */
+class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePlatformDelegate, private BleApplicationDelegate
+{
+    // Allow the BLEManager interface class to delegate method calls to
+    // the implementation methods provided by this class.
+    friend BLEManager;
+
+private:
+    // ===== Members that implement the BLEManager internal interface.
+
+    CHIP_ERROR _Init(void);
+    void _Shutdown() {}
+    bool _IsAdvertisingEnabled(void);
+    CHIP_ERROR _SetAdvertisingEnabled(bool val);
+    bool _IsAdvertising(void);
+    CHIP_ERROR _SetAdvertisingMode(BLEAdvertisingMode mode);
+    CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize);
+    CHIP_ERROR _SetDeviceName(const char * deviceName);
+    uint16_t _NumConnections(void);
+    void _OnPlatformEvent(const ChipDeviceEvent * event);
+    BleLayer * _GetBleLayer(void);
+
+    // ===== Members that implement virtual methods on BlePlatformDelegate.
+
+    bool SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId);
+    bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId);
+    bool CloseConnection(BLE_CONNECTION_OBJECT conId);
+    uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const;
+    bool SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                        PacketBufferHandle pBuf);
+    bool SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                          PacketBufferHandle pBuf);
+    bool SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                         PacketBufferHandle pBuf);
+    bool SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, const ChipBleUUID * svcId,
+                          const ChipBleUUID * charId);
+
+    // ===== Members that implement virtual methods on BleApplicationDelegate.
+
+    void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId);
+
+    // ===== Private members reserved for use by this class only.
+
+    enum class Flags : uint8_t
+    {
+        kAsyncInitCompleted     = 0x0001, /**< One-time asynchronous initialization actions have been performed. */
+        kAdvertisingEnabled     = 0x0002, /**< The application has enabled CHIPoBLE advertising. */
+        kFastAdvertisingEnabled = 0x0004, /**< The application has enabled fast advertising. */
+        kAdvertising            = 0x0008, /**< The system is currently CHIPoBLE advertising. */
+        kAdvertisingRefreshNeeded =
+            0x0010, /**< The advertising state/configuration has changed, but the SoftDevice has yet to be updated. */
+        kChipoBleGattServiceRegister = 0x0020, /**< The system has currently CHIPoBLE GATT service registered. */
+    };
+
+    struct ServiceData;
+
+    BitFlags<Flags> mFlags;
+    uint16_t mGAPConns;
+    CHIPoBLEServiceMode mServiceMode;
+    bool mSubscribedConns[CONFIG_BT_MAX_CONN];
+    bt_gatt_indicate_params mIndicateParams[CONFIG_BT_MAX_CONN];
+    bt_conn_cb mConnCallbacks;
+    BLEAdvertisingArbiter::Request mAdvertisingRequest = {};
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    PacketBufferHandle c3CharDataBufferHandle;
+#endif
+
+    void DriveBLEState(void);
+    CHIP_ERROR PrepareAdvertisingRequest();
+    CHIP_ERROR StartAdvertising(void);
+    CHIP_ERROR StopAdvertising(void);
+    CHIP_ERROR HandleGAPConnect(const ChipDeviceEvent * event);
+    CHIP_ERROR HandleGAPDisconnect(const ChipDeviceEvent * event);
+    CHIP_ERROR HandleRXCharWrite(const ChipDeviceEvent * event);
+    CHIP_ERROR HandleTXCharCCCDWrite(const ChipDeviceEvent * event);
+    CHIP_ERROR HandleTXCharComplete(const ChipDeviceEvent * event);
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    CHIP_ERROR PrepareC3CharData();
+#endif
+    bool IsSubscribed(bt_conn * conn);
+    bool SetSubscribed(bt_conn * conn);
+    bool UnsetSubscribed(bt_conn * conn);
+    uint32_t GetAdvertisingInterval();
+
+    static void DriveBLEState(intptr_t arg);
+
+    // Below callbacks run from the system workqueue context and have a limited stack capacity.
+    static void HandleTXIndicated(bt_conn * conn, bt_gatt_indicate_params * attr, uint8_t err);
+    static void HandleConnect(bt_conn * conn, uint8_t err);
+    static void HandleDisconnect(bt_conn * conn, uint8_t reason);
+    static void HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param);
+
+    // ===== Members for internal use by the following friends.
+
+    friend BLEManager & BLEMgr(void);
+    friend BLEManagerImpl & BLEMgrImpl(void);
+
+    static BLEManagerImpl sInstance;
+
+public:
+    // Below callbacks are public in order to be visible from the global scope.
+    static ssize_t HandleRXWrite(bt_conn * conn, const bt_gatt_attr * attr, const void * buf, uint16_t len, uint16_t offset,
+                                 uint8_t flags);
+    static ssize_t HandleTXCCCWrite(bt_conn * conn, const bt_gatt_attr * attr, uint16_t value);
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    static ssize_t HandleC3Read(struct bt_conn * conn, const struct bt_gatt_attr * attr, void * buf, uint16_t len, uint16_t offset);
+#endif
+};
+
+/**
+ * Returns a reference to the public interface of the BLEManager singleton object.
+ *
+ * Internal components should use this to access features of the BLEManager object
+ * that are common to all platforms.
+ */
+inline BLEManager & BLEMgr(void)
+{
+    return BLEManagerImpl::sInstance;
+}
+
+/**
+ * Returns the platform-specific implementation of the BLEManager singleton object.
+ *
+ * Internal components can use this to gain access to features of the BLEManager
+ * that are specific to the Zephyr platforms.
+ */
+inline BLEManagerImpl & BLEMgrImpl(void)
+{
+    return BLEManagerImpl::sInstance;
+}
+
+inline BleLayer * BLEManagerImpl::_GetBleLayer()
+{
+    return this;
+}
+
+inline bool BLEManagerImpl::_IsAdvertisingEnabled(void)
+{
+    return mFlags.Has(Flags::kAdvertisingEnabled);
+}
+
+inline bool BLEManagerImpl::_IsAdvertising(void)
+{
+    return mFlags.Has(Flags::kAdvertising);
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
diff --git a/src/platform/nxp/rt/rw61x/BUILD.gn b/src/platform/nxp/rt/rw61x/BUILD.gn
index 0e3558b..7337f89 100644
--- a/src/platform/nxp/rt/rw61x/BUILD.gn
+++ b/src/platform/nxp/rt/rw61x/BUILD.gn
@@ -83,20 +83,20 @@
     sources += [ "../../common/NXPConfigKS.cpp" ]
   }
 
-  public_deps = [ "${chip_root}/src/platform:platform_base" ]
-
-  deps += [ "${chip_root}/src/platform/logging:headers" ]
-
   if (chip_enable_ble) {
     sources += [
       # Adding random file which defines the function sys_csrand_get which is called by BLEManagerImpl from Zephyr
       "${nxp_sdk_build_root}/${nxp_sdk_name}/sdk_hook/zephyr/random/random.cpp",
-      "../../../Zephyr/BLEAdvertisingArbiter.cpp",
-      "../../../Zephyr/BLEManagerImpl.cpp",
+      "../../common/ble_zephyr/BLEAdvertisingArbiter.cpp",
+      "../../common/ble_zephyr/BLEManagerImpl.cpp",
       "../../common/ble_zephyr/BLEManagerImpl.h",
     ]
   }
 
+  public_deps = [ "${chip_root}/src/platform:platform_base" ]
+
+  deps += [ "${chip_root}/src/platform/logging:headers" ]
+
   # define CHIP_PLAT_NVM_SUPPORT - See NXPConfig.cpp for definition
   if (rt_nvm_component == "nvm_fwk") {
     defines += [ "CHIP_PLAT_NVM_SUPPORT=1" ]