From 7e7944a05475c2c87b67d3ba465ac149675c6918 Mon Sep 17 00:00:00 2001 From: Martin Girardot Date: Tue, 16 Jul 2024 11:12:55 +0200 Subject: [PATCH] [NXP][platform][rw61x] Switch to using BLE mgr impl files from common nxp folder Signed-off-by: Martin Girardot --- .../ble_zephyr/BLEAdvertisingArbiter.cpp | 138 +++ .../common/ble_zephyr/BLEAdvertisingArbiter.h | 107 +++ .../nxp/common/ble_zephyr/BLEManagerImpl.cpp | 849 ++++++++++++++++++ .../nxp/common/ble_zephyr/BLEManagerImpl.h | 176 +++- src/platform/nxp/rt/rw61x/BUILD.gn | 12 +- 5 files changed, 1271 insertions(+), 11 deletions(-) create mode 100644 src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp create mode 100644 src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h create mode 100644 src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp 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 00000000000000..e977708fe4862a --- /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 +#include +#include + +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(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(¶ms, 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 00000000000000..9c00edbb8e746d --- /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 + +#include +#include + +#include + +/** + * @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 advertisingData; ///< Advertising data fields + Span 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 00000000000000..0b986033054fbe --- /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 + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + +#include "BLEManagerImpl.h" + +#include +#include +#include +#include +#include +#include +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +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 advertisingData; + static std::array scanResponseData; + static_assert(sizeof(serviceData) == 10, "Unexpected size of BLE advertising data!"); + + const char * name = bt_get_name(); + const uint8_t nameSize = static_cast(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(advertisingData); + mAdvertisingRequest.scanResponseData = nameSize ? Span(scanResponseData) : Span{}; + + 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; + 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 411392aa3c6a8c..e80faebe45abc1 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 +#include +#include + #include -#include #include #include + +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 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 0e3558b8bf916a..7337f896c8ddcc 100644 --- a/src/platform/nxp/rt/rw61x/BUILD.gn +++ b/src/platform/nxp/rt/rw61x/BUILD.gn @@ -83,20 +83,20 @@ static_library("nxp_platform") { 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" ]