diff --git a/config/beken/.gn b/config/beken/.gn new file mode 100644 index 00000000000000..11170e233304da --- /dev/null +++ b/config/beken/.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2020 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. + +import("//build_overrides/build.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "risc-v" + target_os = "freertos" + + import("//args.gni") +} diff --git a/config/beken/BUILD.gn b/config/beken/BUILD.gn new file mode 100644 index 00000000000000..5589c3a897cfd1 --- /dev/null +++ b/config/beken/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2020 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. + +# Options from standalone-chip.mk that differ from configure defaults. These +# options are used from examples/. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +#import("${chip_root}/build/chip/tests.gni") + +group("beken") { + deps = [ "${chip_root}/src/lib" ] +} +group("default") { + deps = [ ":beken" ] +} diff --git a/config/beken/args.gni b/config/beken/args.gni new file mode 100755 index 00000000000000..b3ee09f91afa28 --- /dev/null +++ b/config/beken/args.gni @@ -0,0 +1,38 @@ +# Copyright (c) 2020 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. + +# Options from standalone-chip.mk that differ from configure defaults. These +# options are used from examples/. + +chip_device_platform = "beken" + +chip_project_config_include = "" +chip_system_project_config_include = "" +chip_ble_project_config_include = "" + +mbedtls_target = "//mbedtls:mbedtls" +lwip_platform = "external" + +chip_build_tests = false + +chip_inet_config_enable_tcp_endpoint = true +chip_inet_config_enable_udp_endpoint = true + +chip_config_network_layer_ble = true +chip_config_memory_management = "platform" +chip_enable_additional_data_advertising = true +chip_enable_rotating_device_id = true +chip_enable_ota_requestor = true + +custom_toolchain = "//third_party/connectedhomeip/config/beken/toolchain:beken" diff --git a/config/beken/build b/config/beken/build new file mode 120000 index 00000000000000..d56ed62ae4d1ff --- /dev/null +++ b/config/beken/build @@ -0,0 +1 @@ +third_party/connectedhomeip/build \ No newline at end of file diff --git a/config/beken/build_overrides b/config/beken/build_overrides new file mode 120000 index 00000000000000..aea3e8d3b72a17 --- /dev/null +++ b/config/beken/build_overrides @@ -0,0 +1 @@ +../../examples/build_overrides \ No newline at end of file diff --git a/config/beken/mbedtls/BUILD.gn b/config/beken/mbedtls/BUILD.gn new file mode 100644 index 00000000000000..f33d684b620bfe --- /dev/null +++ b/config/beken/mbedtls/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2020 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. + +# Options from standalone-chip.mk that differ from configure defaults. These +# options are used from examples/. + +import("//build_overrides/chip.gni") + +# Ameba has its own mbedtls, so nothing to do, just provide a target +group("mbedtls") { +} diff --git a/config/beken/third_party/connectedhomeip b/config/beken/third_party/connectedhomeip new file mode 120000 index 00000000000000..a8a4f8c2127bf7 --- /dev/null +++ b/config/beken/third_party/connectedhomeip @@ -0,0 +1 @@ +../../.. \ No newline at end of file diff --git a/config/beken/toolchain/BUILD.gn b/config/beken/toolchain/BUILD.gn new file mode 100755 index 00000000000000..c7d3cf0bcbe3d1 --- /dev/null +++ b/config/beken/toolchain/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2020 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. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +#import("${build_root}/toolchain/arm_gcc/arm_toolchain.gni") +import("${build_root}/toolchain/gcc_toolchain.gni") +declare_args() { + beken_ar = "" + beken_cc = "" + beken_cxx = "" +} + +gcc_toolchain("beken") { + ar = beken_ar + cc = beken_cc + cxx = beken_cxx + + toolchain_args = { + current_os = "freertos" + is_clang = false + import("${chip_root}/src/platform/Beken/args.gni") + } +} diff --git a/examples/lighting-app/beken/README.md b/examples/lighting-app/beken/README.md new file mode 100755 index 00000000000000..12fa6683d162e6 --- /dev/null +++ b/examples/lighting-app/beken/README.md @@ -0,0 +1,85 @@ +# Matter BEKEN Lighting Example + +This example demonstrates the Matter Lighting application on BEKEN platforms. + +--- + +- [Matter BEKEN Lighting Example](#matter-BEKEN-lighting-example) + - [Supported Devices](#supported-devices) + - [Building the Example Application](#building-the-example-application) + - [Commissioning over BLE using chip-tool](#commissioning-over-ble-using-chip-tool) + +--- + +## Supported Devices + +The demo application is intended to work on following categories of BEKEN +devices: + +- BK7235 EVB + +## Building the Example Application + +Building the example application requires the use of the BEKEN ARMINO IoT +Development Framework ([BK-ARMINO](https://github.com/zhengyaohan/armino)). + +- Setting up the build environment, recommended with Ubuntu 20.04 LTS + + Armino sdk download + + $ cd ~ + $ git clone git@github.com:zhengyaohan/armino.git + $ git checkout matter + + Toolchain + [download](http://dl.bekencorp.com/tools/toolchain/risc-v_20220418.tar.gz) + and install, the toolchain should be installed to "/opt/risc-v" + + $ sudo tar xvzf {abs-path-to-download}/risc-v_20220418.tar.gz -C /opt + $ sudo mv /opt/risc-v_20220418 /opt/risc-v + $ sudo chown -R $USER:$USER /opt/risc-v + + + Software dependency install + + $ sudo dpkg --add-architecture i386 + $ sudo apt-get update + $ sudo apt-get install build-essential cmake python3 python3-pip doxygen ninja-build libc6:i386 libstdc++6:i386 libncurses5-dev lib32z1 -y + $ sudo pip3 install sphinx_rtd_theme future breathe blockdiag sphinxcontrib-seqdiag sphinxcontrib-actdiag sphinxcontrib-nwdiag sphinxcontrib.blockdiag + $ sudo ln -s /usr/bin/python3 /usr/bin/python + + To activate connectedhomeip files. + + $ cd {abs-path-to-connectedhomeip} + $ source ./scripts/bootstrap.sh + $ source ./scripts/activate.sh + + Link connectedhomeip into ARMINO. + + $ cd {abs-path-to-ARMINO} + $ ln -sfv {abs-path-to-connectedhomeip} components/matter/ + +- build project matter,and flash image file + + $ cd {abs-path-to-ARMINO} + $ make bk7235 PROJECT=matter + + the output bin file is {abs-path-to-ARMINO}/build/matter/bk7235/all-app.bin. + you can use + [WINDOWS BEKEN FLASH WRITE TOOL](http://dl.bekencorp.com:8192/tools/flash/BEKEN_WRITER_EN_V2.6.28_20220326.zip) + to flash the demo application onto the device. + +## Commissioning over BLE using chip-tool + +- Please build the standalone chip-tool as described [here](../../chip-tool) +- Commissioning the WiFi Lighting devices + + $ ./out/debug/chip-tool pairing ble-wifi 12345 20202021 3840 + +## Cluster Control + +After successful commissioning, use the OnOff cluster command to control the +OnOff attribute. This allows you to toggle a parameter implemented by the device +to be On or Off. + + $ ./out/debug/chip-tool onoff on 12345 1 diff --git a/examples/lighting-app/beken/main/CHIPDeviceManager.cpp b/examples/lighting-app/beken/main/CHIPDeviceManager.cpp new file mode 100644 index 00000000000000..525c645927c4a5 --- /dev/null +++ b/examples/lighting-app/beken/main/CHIPDeviceManager.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2020 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 + * This file implements the CHIP Device Interface that is used by + * applications to interact with the CHIP stack + * + */ + +#include + +#include "CHIPDeviceManager.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace ::chip; + +namespace chip { + +namespace DeviceManager { + +using namespace ::chip::DeviceLayer; + +void CHIPDeviceManager::CommonDeviceEventHandler(const ChipDeviceEvent * event, intptr_t arg) +{ + CHIPDeviceManagerCallbacks * cb = reinterpret_cast(arg); + if (cb != nullptr) + { + cb->DeviceEventCallback(event, reinterpret_cast(cb)); + } +} + +CHIP_ERROR CHIPDeviceManager::Init(CHIPDeviceManagerCallbacks * cb) +{ + CHIP_ERROR err; + mCB = cb; + + err = PlatformMgr().InitChipStack(); + SuccessOrExit(err); + + if (CONFIG_NETWORK_LAYER_BLE) + { + ConnectivityMgr().SetBLEAdvertisingEnabled(true); + } + + err = Platform::MemoryInit(); + SuccessOrExit(err); + + PlatformMgr().AddEventHandler(CHIPDeviceManager::CommonDeviceEventHandler, reinterpret_cast(cb)); + + // // Start a task to run the CHIP Device event loop. + err = PlatformMgr().StartEventLoopTask(); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(Zcl, "StartEventLoopTask() - ERROR!\r\n"); + } + else + { + ChipLogProgress(Zcl, "StartEventLoopTask() - OK\r\n"); + } + +exit: + return err; +} +} // namespace DeviceManager +} // namespace chip + +void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type, + uint16_t size, uint8_t * value) +{ + chip::DeviceManager::CHIPDeviceManagerCallbacks * cb = + chip::DeviceManager::CHIPDeviceManager::GetInstance().GetCHIPDeviceManagerCallbacks(); + + EndpointId endpointId = attributePath.mEndpointId; + ClusterId clusterId = attributePath.mClusterId; + AttributeId attributeId = attributePath.mAttributeId; + + if (clusterId == ZCL_ON_OFF_CLUSTER_ID) + { + if (attributeId != ZCL_ON_OFF_ATTRIBUTE_ID) + { + ChipLogProgress(Zcl, "Unknown attribute ID: %" PRIx32, attributeId); + return; + } + } + else if (clusterId == ZCL_LEVEL_CONTROL_CLUSTER_ID) + { + if (attributeId != ZCL_CURRENT_LEVEL_ATTRIBUTE_ID) + { + ChipLogProgress(Zcl, "Unknown attribute ID: %" PRIx32, attributeId); + return; + } + if (size == 1) + { + // ChipLogProgress(Zcl, "New level: %u ", *value); + } + else + { + ChipLogError(Zcl, "wrong length for level: %d\n", size); + } + } + else if (clusterId == ZCL_COLOR_CONTROL_CLUSTER_ID) + { + uint8_t hue, saturation; + + if ((attributeId != ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID) && + (attributeId != ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID)) + { + ChipLogProgress(Zcl, "Unknown attribute ID: %" PRIx32, attributeId); + return; + } + + if (attributeId == ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID) + { + hue = *value; + emberAfReadServerAttribute(endpointId, ZCL_COLOR_CONTROL_CLUSTER_ID, ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID, + &saturation, sizeof(uint8_t)); + } + if (attributeId == ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID) + { + saturation = *value; + emberAfReadServerAttribute(endpointId, ZCL_COLOR_CONTROL_CLUSTER_ID, ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID, &hue, + sizeof(uint8_t)); + } + ChipLogProgress(Zcl, "New hue: %d, New saturation: %d ", hue, saturation); + } + else if (clusterId == ZCL_IDENTIFY_CLUSTER_ID) + { + if (attributeId == ZCL_IDENTIFY_TIME_ATTRIBUTE_ID) + { + if (cb != nullptr) + { + cb->PostAttributeChangeCallback(endpointId, clusterId, attributeId, mask, type, size, value); + } + ChipLogProgress(Zcl, "ZCL_IDENTIFY_TIME_ATTRIBUTE_ID value: %u ", *value); + } + } + else + { + // ChipLogProgress(Zcl, "Unknown cluster ID: %" PRIx32, clusterId); + return; + } +} diff --git a/examples/lighting-app/beken/main/DeviceCallbacks.cpp b/examples/lighting-app/beken/main/DeviceCallbacks.cpp new file mode 100644 index 00000000000000..2341fd39f23a4a --- /dev/null +++ b/examples/lighting-app/beken/main/DeviceCallbacks.cpp @@ -0,0 +1,186 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file DeviceCallbacks.cpp + * + * Implements all the callbacks to the application from the CHIP Stack + * + **/ +#include "DeviceCallbacks.h" + +#include "CHIPDeviceManager.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char * TAG = "app-devicecallbacks"; + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::System; +using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceManager; +using namespace ::chip::Logging; + +uint32_t identifyTimerCount; +constexpr uint32_t kIdentifyTimerDelayMS = 250; + +void DeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg) +{ + ChipLogProgress(Zcl, "DeviceEventCallback, event->Type:%d \r\n", event->Type); + switch (event->Type) + { + case DeviceEventType::kInternetConnectivityChange: + OnInternetConnectivityChange(event); + break; + + // case DeviceEventType::kSessionEstablished: + // OnSessionEstablished(event); + // break; + case DeviceEventType::kInterfaceIpAddressChanged: + ChipLogProgress(Zcl, "IP(%s) changed event", + (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV4_Assigned) ? "IPv4" : "IPv6"); + if ((event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV4_Assigned) || + (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned)) + { + // MDNS server restart on any ip assignment: if link local ipv6 is configured, that + // will not trigger a 'internet connectivity change' as there is no internet + // connectivity. MDNS still wants to refresh its listening interfaces to include the + // newly selected address. + chip::app::DnssdServer::Instance().StartServer(); + } + break; + case DeviceEventType::kCHIPoBLEConnectionEstablished: + ChipLogProgress(Zcl, "CHIPoBLE connection established"); + break; + case DeviceEventType::kCHIPoBLEConnectionClosed: + ChipLogProgress(Zcl, "CHIPoBLE disconnected"); + break; + case DeviceEventType::kCommissioningComplete: + ChipLogProgress(Zcl, "Commissioning complete"); + break; + } +} + +void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) +{ + if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established) + { + ChipLogProgress(Zcl, "Server ready at:%d", CHIP_PORT); + // chip::app::DnssdServer::Instance().StartServer(); + } + else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) + { + ChipLogProgress(Zcl, "Lost IPv4 connectivity..."); + } + if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established) + { + ChipLogProgress(Zcl, "IPv6 Server ready..."); + chip::app::DnssdServer::Instance().StartServer(); + } + else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) + { + ChipLogProgress(Zcl, "Lost IPv6 connectivity..."); + } +} + +void DeviceCallbacks::OnSessionEstablished(const ChipDeviceEvent * event) +{ + if (event->SessionEstablished.IsCommissioner) + { + ChipLogProgress(Zcl, "Commissioner detected!"); + } +} + +void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, uint8_t mask, + uint8_t type, uint16_t size, uint8_t * value) +{ + switch (clusterId) + { + case ZCL_ON_OFF_CLUSTER_ID: + OnOnOffPostAttributeChangeCallback(endpointId, attributeId, value); + break; + + case ZCL_IDENTIFY_CLUSTER_ID: + OnIdentifyPostAttributeChangeCallback(endpointId, attributeId, value); + break; + + default: + ChipLogProgress(Zcl, "Unknown cluster ID: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); + break; + } +} + +void DeviceCallbacks::OnOnOffPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + VerifyOrExit(attributeId == ZCL_ON_OFF_ATTRIBUTE_ID, + ChipLogError(DeviceLayer, TAG, "Unhandled Attribute ID: '0x%04x", attributeId)); + VerifyOrExit(endpointId == 1 || endpointId == 2, + ChipLogError(DeviceLayer, TAG, "Unexpected EndPoint ID: `0x%02x'", endpointId)); + + // At this point we can assume that value points to a bool value. + // statusLED1.Set(*value); + +exit: + return; +} + +void IdentifyTimerHandler(Layer * systemLayer, void * appState) +{ + // statusLED1.Animate(); + + if (identifyTimerCount) + { + systemLayer->StartTimer(Clock::Milliseconds32(kIdentifyTimerDelayMS), IdentifyTimerHandler, appState); + // Decrement the timer count. + identifyTimerCount--; + } +} + +void DeviceCallbacks::OnIdentifyPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + VerifyOrExit(attributeId == ZCL_IDENTIFY_TIME_ATTRIBUTE_ID, + ChipLogError(DeviceLayer, "[%s] Unhandled Attribute ID: '0x%04x", TAG, attributeId)); + VerifyOrExit(endpointId == 1, ChipLogError(DeviceLayer, "[%s] Unexpected EndPoint ID: `0x%02x'", TAG, endpointId)); + + // timerCount represents the number of callback executions before we stop the timer. + // value is expressed in seconds and the timer is fired every 250ms, so just multiply value by 4. + // Also, we want timerCount to be odd number, so the ligth state ends in the same state it starts. + identifyTimerCount = (*value) * 4; + + DeviceLayer::SystemLayer().CancelTimer(IdentifyTimerHandler, this); + DeviceLayer::SystemLayer().StartTimer(Clock::Milliseconds32(kIdentifyTimerDelayMS), IdentifyTimerHandler, this); + +exit: + return; +} + +bool emberAfBasicClusterMfgSpecificPingCallback(chip::app::CommandHandler * commandObj) +{ + emberAfSendDefaultResponse(emberAfCurrentCommand(), EMBER_ZCL_STATUS_SUCCESS); + return true; +} diff --git a/examples/lighting-app/beken/main/DsoHack.cpp b/examples/lighting-app/beken/main/DsoHack.cpp new file mode 100644 index 00000000000000..2378086f551b8a --- /dev/null +++ b/examples/lighting-app/beken/main/DsoHack.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021 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. + */ + +// This hack is needed because Beken SDK is not linking against libstdc++ correctly. +extern "C" { +void * __dso_handle = 0; +} diff --git a/examples/lighting-app/beken/main/chipinterface.cpp b/examples/lighting-app/beken/main/chipinterface.cpp new file mode 100644 index 00000000000000..fbb9043fe26e79 --- /dev/null +++ b/examples/lighting-app/beken/main/chipinterface.cpp @@ -0,0 +1,390 @@ +/* + * + * Copyright (c) 2020 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 "CHIPDeviceManager.h" +#include "DeviceCallbacks.h" +#include "Server.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//#if CONFIG_ENABLE_OTA_REQUESTOR +#include "app/clusters/ota-requestor/DefaultOTARequestorStorage.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#endif + +// using chip::OTAImageProcessorImpl; +using chip::BDXDownloader; +using chip::ByteSpan; +using chip::DefaultOTARequestor; +using chip::EndpointId; +using chip::FabricIndex; +using chip::GetRequestorInstance; +using chip::NodeId; +using chip::OnDeviceConnected; +using chip::OnDeviceConnectionFailure; +using chip::OTADownloader; +using chip::PeerId; +using chip::Server; +using chip::VendorId; +using chip::Callback::Callback; +using chip::System::Layer; +using chip::Transport::PeerAddress; +using namespace chip::Messaging; +using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands; + +using namespace ::chip; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceManager; +using namespace ::chip::DeviceLayer; + +namespace { +constexpr EndpointId kNetworkCommissioningEndpointMain = 0; +constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE; + +app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(kNetworkCommissioningEndpointMain /* Endpoint Id */, + &(NetworkCommissioning::BekenWiFiDriver::GetInstance())); +} // namespace + +static DeviceCallbacks EchoCallbacks; +DefaultOTARequestor gRequestorCore; +DefaultOTARequestorStorage gRequestorStorage; +ExtendedOTARequestorDriver gRequestorUser; +BDXDownloader gDownloader; +OTAImageProcessorImpl gImageProcessor; +chip::ota::DefaultOTARequestorUserConsent gUserConsentProvider; +static chip::ota::UserConsentState gUserConsentState = chip::ota::UserConsentState::kGranted; + +// need to check CONFIG_RENDEZVOUS_MODE +bool isRendezvousBLE() +{ + RendezvousInformationFlags flags = RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE); + return flags.Has(RendezvousInformationFlag::kBLE); +} + +//#if CONFIG_ENABLE_OTA_REQUESTOR +extern "C" void QueryImageCmdHandler() +{ + ChipLogProgress(DeviceLayer, "Calling QueryImageCmdHandler"); + PlatformMgr().ScheduleWork([](intptr_t) { GetRequestorInstance()->TriggerImmediateQuery(); }); +} + +extern "C" void ApplyUpdateCmdHandler() +{ + ChipLogProgress(DeviceLayer, "Calling ApplyUpdateCmdHandler"); + PlatformMgr().ScheduleWork([](intptr_t) { GetRequestorInstance()->ApplyUpdate(); }); +} + +extern "C" void NotifyUpdateAppliedHandler(uint32_t version) +{ + ChipLogProgress(DeviceLayer, "NotifyUpdateApplied"); + PlatformMgr().ScheduleWork([](intptr_t) { GetRequestorInstance()->NotifyUpdateApplied(); }); +} + +extern "C" void BkQueryImageCmdHandler(char * pcWriteBuffer, int xWriteBufferLen, int argc, char ** argv) +{ + uint32_t dwLoop = 0; + uint32_t nodeId = 0; + uint32_t fabricId = 0; + + char cmd0 = 0; + char cmd1 = 0; + + for (dwLoop = 0; dwLoop < argc; dwLoop++) + { + ChipLogProgress(DeviceLayer, "QueryImageArgument %d = %s\r\n", dwLoop + 1, argv[dwLoop]); + } + + if (argc == 3) + { + cmd0 = argv[1][0] - 0x30; + cmd1 = argv[1][1] - 0x30; + nodeId = (uint32_t)(cmd0 * 10 + cmd1); + + cmd0 = argv[2][0] - 0x30; + cmd1 = argv[2][1] - 0x30; + fabricId = (uint32_t)(cmd0 * 10 + cmd1); + ChipLogProgress(DeviceLayer, "nodeId %lu,fabricId %lu\r\n", nodeId, fabricId); + } + else + { + ChipLogProgress(DeviceLayer, "cmd param error "); + return; + } + + QueryImageCmdHandler(); + ChipLogProgress(DeviceLayer, "QueryImageCmdHandler begin"); + + return; +} + +extern "C" void BkApplyUpdateCmdHandler(char * pcWriteBuffer, int xWriteBufferLen, int argc, char ** argv) +{ + // ApplyUpdateCmdHandler(); + ChipLogProgress(DeviceLayer, "ApplyUpdateCmdHandler send request"); + + return; +} + +extern "C" void BkNotifyUpdateApplied(char * pcWriteBuffer, int xWriteBufferLen, int argc, char ** argv) +{ + uint32_t dwLoop = 0; + uint32_t version = 0; + + char cmd0 = 0; + char cmd1 = 0; + + for (dwLoop = 0; dwLoop < argc; dwLoop++) + { + ChipLogProgress(DeviceLayer, "NotifyUpdateApplied %d = %s\r\n", dwLoop + 1, argv[dwLoop]); + } + + if (argc == 2) + { + cmd0 = argv[1][0] - 0x30; + cmd1 = argv[1][1] - 0x30; + version = (uint32_t)(cmd0 * 10 + cmd1); + + ChipLogProgress(DeviceLayer, "version %lu \r\n", version); + } + else + { + ChipLogProgress(DeviceLayer, "cmd param error "); + return; + } + + NotifyUpdateAppliedHandler(version); + ChipLogProgress(DeviceLayer, "NotifyUpdateApplied send request"); + + return; +} + +static void InitOTARequestor(void) +{ + // Initialize and interconnect the Requestor and Image Processor objects -- START + SetRequestorInstance(&gRequestorCore); + + gRequestorStorage.Init(Server::GetInstance().GetPersistentStorage()); + + // Set server instance used for session establishment + gRequestorCore.Init(Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + + gImageProcessor.SetOTADownloader(&gDownloader); + + // Connect the Downloader and Image Processor objects + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + if (gUserConsentState != chip::ota::UserConsentState::kUnknown) + { + gUserConsentProvider.SetUserConsentState(gUserConsentState); + gRequestorUser.SetUserConsentDelegate(&gUserConsentProvider); + } + + // Initialize and interconnect the Requestor and Image Processor objects -- END +} +//#endif // CONFIG_ENABLE_OTA_REQUESTOR + +void OnIdentifyStart(Identify *) +{ + ChipLogProgress(Zcl, "OnIdentifyStart"); +} + +void OnIdentifyStop(Identify *) +{ + ChipLogProgress(Zcl, "OnIdentifyStop"); +} + +void OnTriggerEffect(Identify * identify) +{ + switch (identify->mCurrentEffectIdentifier) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE"); + break; + default: + ChipLogProgress(Zcl, "No identifier effect"); + return; + } +} + +static Identify gIdentify1 = { + chip::EndpointId{ 1 }, OnIdentifyStart, OnIdentifyStop, EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED, OnTriggerEffect, +}; + +// Warkaround for ld error:undefined reference to '__sync_synchronize' +// refer to https://stackoverflow.com/questions/64658430/gnu-arm-embedded-toolchain-undefined-reference-to-sync-synchronize +extern "C" void __sync_synchronize() {} + +extern "C" unsigned int __atomic_fetch_add_4(volatile void * ptr, unsigned int val, int memorder) +{ + return (*(unsigned int *) ptr + val); +} + +extern "C" bool __atomic_compare_exchange_4(volatile void * pulDestination, void * ulComparand, unsigned int desired, bool weak, + int success_memorder, int failure_memorder) +{ + bool ulReturnValue; + if (*(unsigned int *) pulDestination == *(unsigned int *) ulComparand) + { + *(unsigned int *) pulDestination = desired; + ulReturnValue = true; + } + else + { + *(unsigned int *) ulComparand = *(unsigned int *) pulDestination; + ulReturnValue = false; + } + return ulReturnValue; +} + +extern "C" unsigned int __atomic_fetch_sub_4(volatile void * ptr, unsigned int val, int memorder) +{ + return (*(unsigned int *) ptr + val); +} +extern "C" bool __atomic_compare_exchange_1(volatile void * pulDestination, void * ulComparand, unsigned char desired, bool weak, + int success_memorder, int failure_memorder) +{ + bool ulReturnValue; + if (*(unsigned char *) pulDestination == *(unsigned char *) ulComparand) + { + *(unsigned char *) pulDestination = desired; + ulReturnValue = true; + } + else + { + *(unsigned char *) ulComparand = *(unsigned char *) pulDestination; + ulReturnValue = false; + } + return ulReturnValue; +} + +extern "C" unsigned int __atomic_fetch_and_4(volatile void * pulDestination, unsigned int ulValue, int memorder) +{ + unsigned int ulCurrent; + + ulCurrent = *(unsigned int *) pulDestination; + *(unsigned int *) pulDestination &= ulValue; + return ulCurrent; +} + +extern "C" bool __sync_bool_compare_and_swap_4(volatile void * ptr, unsigned int oldval, unsigned int newval) +{ + if (*(unsigned int *) ptr == oldval) + { + *(unsigned int *) ptr = newval; + return true; + } + else + { + return false; + } +} + +extern "C" bool __sync_bool_compare_and_swap_1(volatile void * ptr, unsigned char oldval, unsigned char newval) +{ + if (*(unsigned char *) ptr == oldval) + { + *(unsigned char *) ptr = newval; + return true; + } + else + { + return false; + } +} + +/* stub for __libc_init_array */ +extern "C" void _fini(void) {} +extern "C" void _init(void) +{ + ; +} + +static void InitServer(intptr_t context) +{ + // Init ZCL Data Model and CHIP App Server + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + chip::Server::GetInstance().Init(initParams); + + // Initialize device attestation config + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); + sWiFiNetworkCommissioningInstance.Init(); + InitOTARequestor(); + PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); +} + +extern "C" void ChipTest(void) +{ + ChipLogProgress(DeviceLayer, "Lighting App Demo!"); + CHIP_ERROR err = CHIP_NO_ERROR; + + // initPref(); + + CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance(); + err = deviceMgr.Init(&EchoCallbacks); // start the CHIP task + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "DeviceManagerInit() - ERROR!\r\n"); + } + else + { + ChipLogProgress(DeviceLayer, "DeviceManagerInit() - OK\r\n"); + } + chip::DeviceLayer::PlatformMgr().ScheduleWork(InitServer, 0); + + while (true) + vTaskDelay(pdMS_TO_TICKS(50)); // Just server the application event handler + ChipLogProgress(SoftwareUpdate, "Exited"); + return; +} + +bool lowPowerClusterSleep() +{ + return true; +} diff --git a/examples/lighting-app/beken/main/include/CHIPDeviceManager.h b/examples/lighting-app/beken/main/include/CHIPDeviceManager.h new file mode 100644 index 00000000000000..d7b7d41f6513b6 --- /dev/null +++ b/examples/lighting-app/beken/main/include/CHIPDeviceManager.h @@ -0,0 +1,124 @@ +/* + * + * Copyright (c) 2020 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 + * This file contains definitions for the CHIP DeviceManager Interface + * + * This object will co-ordinate multiple activities such as + * initialisation, rendezvous, session mgmt and other such + * activities within the CHIP stack. This is a singleton object. + */ + +#pragma once + +#include +#include +#include + +#include + +#include +#include + +#include + +namespace chip { +namespace DeviceManager { + +/** + * @brief + * This class provides a skeleton for all the callback functions. The functions will be + * called by other objects within the CHIP stack for specific events. + * Applications interested in receiving specific callbacks can specialize this class and handle + * these events in their implementation of this class. + */ +class CHIPDeviceManagerCallbacks +{ +public: + /** + * @brief + * Called when CHIP Device events (PublicEventTypes) are triggered. + * + * @param event ChipDeviceEvent that occurred + * @param arg arguments specific to the event, if any + */ + virtual void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) {} + + /** + * @brief + * Called after an attribute has been changed + * + * @param endpoint endpoint id + * @param clusterID cluster id + * @param attributeId attribute id that was changed + * @param mask mask of the attribute + * @param manufacturerCode manufacturer code + * @param type attribute type + * @param size size of the attribute + * @param value pointer to the new value + */ + virtual void PostAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) + {} + virtual ~CHIPDeviceManagerCallbacks() {} +}; + +/** + * @brief + * A common class that drives other components of the CHIP stack + */ +class DLL_EXPORT CHIPDeviceManager +{ +public: + CHIPDeviceManager(const CHIPDeviceManager &) = delete; + CHIPDeviceManager(const CHIPDeviceManager &&) = delete; + CHIPDeviceManager & operator=(const CHIPDeviceManager &) = delete; + + static CHIPDeviceManager & GetInstance() + { + static CHIPDeviceManager instance; + return instance; + } + + /** + * @brief + * Initialise CHIPDeviceManager + * + * @param cb Application's instance of the CHIPDeviceManagerCallbacks for consuming events + */ + CHIP_ERROR Init(CHIPDeviceManagerCallbacks * cb); + + /** + * @brief + * Fetch a pointer to the registered CHIPDeviceManagerCallbacks object. + * + */ + CHIPDeviceManagerCallbacks * GetCHIPDeviceManagerCallbacks() { return mCB; } + + /** + * Use internally for registration of the ChipDeviceEvents + */ + static void CommonDeviceEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + +private: + CHIPDeviceManagerCallbacks * mCB = nullptr; + CHIPDeviceManager() {} +}; + +} // namespace DeviceManager +} // namespace chip diff --git a/examples/lighting-app/beken/main/include/DeviceCallbacks.h b/examples/lighting-app/beken/main/include/DeviceCallbacks.h new file mode 100644 index 00000000000000..10ac917c02890a --- /dev/null +++ b/examples/lighting-app/beken/main/include/DeviceCallbacks.h @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file DeviceCallbacks.h + * + * Implementations for the DeviceManager callbacks for this application + * + **/ + +#pragma once + +#include "CHIPDeviceManager.h" +#include +#include +#include + +class DeviceCallbacks : public chip::DeviceManager::CHIPDeviceManagerCallbacks +{ +public: + void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) override; + void PostAttributeChangeCallback(chip::EndpointId endpointId, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) override; + +private: + void OnInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnSessionEstablished(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnOnOffPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); + void OnIdentifyPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); +}; diff --git a/scripts/tools/check_includes_config.py b/scripts/tools/check_includes_config.py index 2dffe78715f760..30b66bcd01fddd 100644 --- a/scripts/tools/check_includes_config.py +++ b/scripts/tools/check_includes_config.py @@ -39,6 +39,7 @@ '/darwin/', '/platform/Ameba/', '/platform/android/', + '/platform/Beken/', '/platform/CYW30739/', '/platform/Darwin/', '/platform/EFR32/', diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index b8b20ee5739379..31e25b41a6a5df 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -262,6 +262,12 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "CHIP_DEVICE_LAYER_TARGET_ZEPHYR=1", "CHIP_DEVICE_LAYER_TARGET=Zephyr", ] + } else if (chip_device_platform == "beken") { + defines += [ + "CHIP_DEVICE_LAYER_TARGET_BEKEN=1", + "CHIP_DEVICE_LAYER_TARGET=Beken", + "CHIP_DEVICE_CONFIG_ENABLE_WIFI=${chip_enable_wifi}", + ] } if (chip_device_config_device_software_version_string != "") { @@ -431,6 +437,8 @@ if (chip_device_platform != "none") { _platform_target = "nxp/mw320" } else if (chip_device_platform == "zephyr") { _platform_target = "Zephyr" + } else if (chip_device_platform == "beken") { + _platform_target = "Beken" } else { assert(false, "Unknown chip_device_platform: ${chip_device_platform}") } diff --git a/src/platform/Beken/BLEManagerImpl.cpp b/src/platform/Beken/BLEManagerImpl.cpp new file mode 100644 index 00000000000000..4e98402f713a2f --- /dev/null +++ b/src/platform/Beken/BLEManagerImpl.cpp @@ -0,0 +1,1296 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the BLEManager singleton object + * for the Beken platforms. + */ + +/* this file behaves like a config.h, comes first */ +#include +#include +#include +#include +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING +#include +#endif +#include "stdio.h" +#include "timers.h" +#include + +// BK7231n BLE related header files +#include "matter_pal.h" + +/******************************************************************************* + * Local data types + *******************************************************************************/ +using namespace ::chip; +using namespace ::chip::Ble; + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +namespace { + +/******************************************************************************* + * Macros & Constants definitions + *******************************************************************************/ +#ifndef MAX_ADV_DATA_LEN +#define MAX_ADV_DATA_LEN 31 +#endif +#define CHIP_ADV_DATA_TYPE_FLAGS 0x01 +#define CHIP_ADV_DATA_FLAGS 0x06 + +/* advertising configuration */ +#define CHIP_ADV_SHORT_UUID_LEN (2) + +/* FreeRTOS sw timer */ +TimerHandle_t bleFastAdvTimer; + +enum +{ + DriveBLEExtPerfEvt_DISCONNECT = 0, +}; + +const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, + 0x9D, 0x11 } }; +const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, + 0x9D, 0x12 } }; +static const uint8_t _svc_uuid[16] = { 0xF6, 0xFF, 0, 0, 0x0, 0x0, 0, 0, 0, 0, 0x0, 0x0, 0, 0, 0, 0 }; + +#define UUID_CHIPoBLECharact_RX \ + { \ + 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 \ + } +//#define UUID_CHIPoBLECharact_RX { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, 0x11 +//} +#define ChipUUID_CHIPoBLECharact_TX \ + { \ + 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 \ + } +//#define ChipUUID_CHIPoBLECharact_TX { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, +//0x12 } +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING +#define UUID_CHIPoBLEChar_C3 \ + { \ + 0x04, 0x8F, 0x21, 0x83, 0x8A, 0x74, 0x7D, 0xB8, 0xF2, 0x45, 0x72, 0x87, 0x38, 0x02, 0x63, 0x64 \ + } +#endif +#define BEKEN_ATT_DECL_PRIMARY_SERVICE_128 \ + { \ + 0x00, 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \ + } +#define BEKEN_ATT_DECL_CHARACTERISTIC_128 \ + { \ + 0x03, 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \ + } +#define BEKEN_ATT_DESC_CLIENT_CHAR_CFG_128 \ + { \ + 0x02, 0x29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \ + } + +enum +{ + SVR_FFF6_IDX_SVC, + SVR_FFF6_RX_DECL, + SVR_FFF6_RX_VALUE, + SVR_FFF6_TX_DECL, + SVR_FFF6_TX_VALUE, +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + SVR_FFF6_C3_VALUE, +#endif + SVR_FFF6_TX_CFG, + SVR_FFF6_MAX, +}; + +ble_attm_desc_t svr_fff6_att_db[SVR_FFF6_MAX] = { + // Service Declaration + [SVR_FFF6_IDX_SVC] = { BEKEN_ATT_DECL_PRIMARY_SERVICE_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 2 }, + + // Level Characteristic Declaration + [SVR_FFF6_RX_DECL] = { BEKEN_ATT_DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 0 }, + // Level Characteristic Value BK_PERM_RIGHT_ENABLE WRITE_REQ_POS RI_POS UUID_LEN_POS BK_PERM_RIGHT_UUID_128 + [SVR_FFF6_RX_VALUE] = { UUID_CHIPoBLECharact_RX, BK_BLE_PERM_SET(WRITE_REQ, ENABLE), + BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_128), 512 }, + + /// RD_POS NTF_POS + [SVR_FFF6_TX_DECL] = { BEKEN_ATT_DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE) | BK_BLE_PERM_SET(NTF, ENABLE), 0, 0 }, + //// UUID_LEN_POS BK_PERM_RIGHT_UUID_128 RD_POS + [SVR_FFF6_TX_VALUE] = { ChipUUID_CHIPoBLECharact_TX, BK_BLE_PERM_SET(RD, ENABLE) | BK_BLE_PERM_SET(NTF, ENABLE), + BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_128), 512 }, +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + [SVR_FFF6_C3_VALUE] = { UUID_CHIPoBLEChar_C3, BK_BLE_PERM_SET(RD, ENABLE), + BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_128), 512 }, +#endif + [SVR_FFF6_TX_CFG] = { BEKEN_ATT_DESC_CLIENT_CHAR_CFG_128, BK_BLE_PERM_SET(RD, ENABLE) | BK_BLE_PERM_SET(WRITE_REQ, ENABLE), 0, + 2 }, +}; + +/// const static uint8_t svr_fff6_att_db_item = SVR_FFF6_MAX; +} // namespace + +BLEManagerImpl BLEManagerImpl::sInstance; + +int BLEManagerImpl::beken_ble_init(void) +{ + int status; + + struct bk_ble_db_cfg ble_db_cfg; + + ble_db_cfg.att_db = svr_fff6_att_db; + ble_db_cfg.att_db_nb = SVR_FFF6_MAX; + ble_db_cfg.prf_task_id = 0; + ble_db_cfg.start_hdl = 0; + ble_db_cfg.svc_perm = BK_BLE_PERM_SET(SVC_UUID_LEN, UUID_16); + memcpy(&(ble_db_cfg.uuid[0]), &_svc_uuid[0], 16); + status = bk_ble_create_db(&ble_db_cfg); + + if (status != BK_ERR_BLE_SUCCESS) + { + return -1; + } + return 0; +} + +CHIP_ERROR BLEManagerImpl::_Init() +{ + CHIP_ERROR err; + + // Initialize the CHIP BleLayer. + err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer()); + SuccessOrExit(err); + + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; + memset(mBleConnections, 0, sizeof(mBleConnections)); + // Check if BLE stack is initialized + VerifyOrExit(!mFlags.Has(Flags::kAMEBABLEStackInitialized), err = CHIP_ERROR_INCORRECT_STATE); + bk_ble_set_notice_cb(ble_event_notice); + + // Set related flags + mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); + mFlags.Set(Flags::kAMEBABLEStackInitialized); + mFlags.Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? true : false); + mFlags.Set(Flags::kFastAdvertisingEnabled); + mFlags.Set(Flags::kSlowAdvertisingEnabled); + if (!mFlags.Has(Flags::kBEKENBLEAdvTimer)) + { + uint32_t bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME; + bleFastAdvTimer = xTimerCreate("", (bleAdvTimeoutMs / 2), pdFALSE, NULL, ble_adv_timer_timeout_handle); + mFlags.Set(Flags::kBEKENBLEAdvTimer); + } + + PlatformMgr().ScheduleWork(DriveBLEState, 0); + +exit: + return err; +} + +void BLEManagerImpl::HandleTXCharRead(void * param) +{ + CHIPoBLEConState * conState; + ble_read_req_t * r_req = (ble_read_req_t *) param; + if (param == NULL) + { + ChipLogError(DeviceLayer, "HandleTXCharRead failed: %p", param); + } + r_req->length = 0; +} + +void BLEManagerImpl::HandleTXCharCCCDRead(void * param) +{ + CHIPoBLEConState * conState; + ble_read_req_t * r_req = (ble_read_req_t *) param; + conState = GetConnectionState(r_req->conn_idx); + + if (param == NULL) + { + ChipLogError(DeviceLayer, "HandleTXCharCCCDRead failed"); + return; + } + + if (conState != NULL) + { + r_req->value[0] = conState->subscribed ? 1 : 0; + r_req->value[1] = 0; + r_req->length = 2; + } + else + { + ChipLogError(DeviceLayer, "conState failed: %p", conState); + r_req->length = 0; + } +} + +void BLEManagerImpl::HandleTXCharCCCDWrite(int conn_id, int notificationsEnabled, int indicationsEnabled) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // If the client has requested to enabled indications/notifications + if (indicationsEnabled || notificationsEnabled) + { + // If indications are not already enabled for the connection... + if (!IsSubscribed(conn_id)) + { + // Record that indications have been enabled for this connection. + err = SetSubscribed(conn_id); + VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR); + SuccessOrExit(err); + } + } + else + { + // If indications had previously been enabled for this connection, record that they are no longer enabled. + UnsetSubscribed(conn_id); + } + + // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on + // whether the client is enabling or disabling indications. + { + ChipDeviceEvent event; + event.Type = (indicationsEnabled || notificationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe + : DeviceEventType::kCHIPoBLEUnsubscribe; + event.CHIPoBLESubscribe.ConId = conn_id; + PlatformMgr().PostEventOrDie(&event); + } + + ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", + (indicationsEnabled || notificationsEnabled) ? "subscribe" : "unsubscribe"); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err)); + } + + return; +} + +CHIP_ERROR BLEManagerImpl::HandleTXComplete(int conn_id) +{ + // Post an event to the Chip queue to process the indicate confirmation. + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm; + event.CHIPoBLEIndicateConfirm.ConId = conn_id; + PlatformMgr().PostEventOrDie(&event); + return CHIP_NO_ERROR; +} + +uint16_t BLEManagerImpl::_NumConnections(void) +{ + uint16_t numCons = 0; + + for (uint8_t i = 0; i < kMaxConnections; i++) + { + if (mBleConnections[i].allocated == 1) + { + numCons += 1; + } + } + + return numCons; +} + +CHIP_ERROR BLEManagerImpl::HandleGAPConnect(uint16_t conn_id) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + // Track the number of active GAP connections. + mNumGAPCons++; + err = SetSubscribed(conn_id); + VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR); + SuccessOrExit(err); + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(uint16_t conn_id, uint16_t disc_cause) +{ + // Update the number of GAP connections. + if (mNumGAPCons > 0) + { + mNumGAPCons--; + } + + if (RemoveConnection(conn_id)) + { + CHIP_ERROR disconReason; + switch (disc_cause) + { + case 0x13: + case 0x08: + disconReason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED; + break; + case 0x16: + disconReason = BLE_ERROR_APP_CLOSED_CONNECTION; + break; + default: + disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT; + break; + } + HandleConnectionError(conn_id, disconReason); + } + + // Force a reconfiguration of advertising in case we switched to non-connectable mode when + // the BLE connection was established. + mFlags.Set(Flags::kAdvertisingRefreshNeeded); + return CHIP_NO_ERROR; +} + +bool BLEManagerImpl::RemoveConnection(uint8_t connectionHandle) +{ + CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle); + bool status = false; + + if (bleConnState != NULL) + { + bleConnState->Reset(); + memset(bleConnState, 0, sizeof(CHIPoBLEConState)); + status = true; + } + return status; +} + +BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint8_t connectionHandle, bool allocate) +{ + uint8_t freeIndex = kMaxConnections; + + for (uint8_t i = 0; i < kMaxConnections; i++) + { + if (mBleConnections[i].allocated == 1) + { + if (mBleConnections[i].conn_idx == connectionHandle) + { + return &mBleConnections[i]; + } + } + + else if (i < freeIndex) + { + freeIndex = i; + } + } + + if (allocate) + { + if (freeIndex < kMaxConnections) + { + mBleConnections[freeIndex].Set(connectionHandle); + return &mBleConnections[freeIndex]; + } + + ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState"); + } + + return NULL; +} + +CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (val != mServiceMode) + { + mServiceMode = val; + PlatformMgr().ScheduleWork(DriveBLEState, 0); + } + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (mFlags.Has(Flags::kAdvertisingEnabled) != val) + { + mFlags.Set(Flags::kAdvertisingEnabled, val); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + } + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) +{ + switch (mode) + { + case BLEAdvertisingMode::kFastAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, true); + break; + case BLEAdvertisingMode::kSlowAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, false); + break; + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + mFlags.Set(Flags::kAdvertisingRefreshNeeded); + + PlatformMgr().ScheduleWork(DriveBLEState, 0); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize) +{ + if (strlen(mDeviceName) >= bufSize) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + strcpy(buf, mDeviceName); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (deviceName != NULL && deviceName[0] != 0) + { + VerifyOrExit(strlen(deviceName) >= kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT); + strcpy(mDeviceName, deviceName); + mFlags.Set(Flags::kDeviceNameSet); + ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", deviceName); + } + else + { + mDeviceName[0] = 0; + mFlags.Clear(Flags::kDeviceNameSet); + } + +exit: + return err; +} + +void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) +{ + switch (event->Type) + { + // Platform specific events + case DeviceEventType::kCHIPoBLESubscribe: + HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + { + ChipDeviceEvent connEstEvent; + connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; + PlatformMgr().PostEventOrDie(&connEstEvent); + } + break; + + case DeviceEventType::kCHIPoBLEUnsubscribe: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe"); + HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + } + break; + + case DeviceEventType::kCHIPoBLEWriteReceived: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived"); + HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX, + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); + } + break; + + case DeviceEventType::kCHIPoBLEConnectionError: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError"); + HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason); + } + break; + + case DeviceEventType::kCHIPoBLEIndicateConfirm: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm"); + HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + } + break; + + case DeviceEventType::kServiceProvisioningChange: + case DeviceEventType::kWiFiConnectivityChange: + +// If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, when there is a change to the device's provisioning state and device +// is now fully provisioned, the CHIPoBLE advertising will be disabled. +#if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + if (ConfigurationMgr().IsFullyProvisioned()) + { + mFlags.Clear(Flags::kAdvertisingEnabled); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned"); + } +#endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + ChipLogProgress(DeviceLayer, "Updating advertising data"); + StartAdvertising(); + break; + + default: + ChipLogProgress(DeviceLayer, "_OnPlatformEvent default: event->Type = %d", event->Type); + break; + } +} + +bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported"); + return false; +} + +bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported"); + return false; +} + +bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) +{ + CHIP_ERROR err; + ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId); + uint32_t delay_time = 20; + int ret; + + do + { + ret = bk_ble_disconnect(conId, beken_ble_cmd_cb); + if (BK_ERR_BLE_SUCCESS == ret) + { + break; + } + + rtos_delay_milliseconds(10); + delay_time--; + } while (delay_time); + // Beken Ble close function + err = MapBLEError(ret); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "bk_ble_disconnect() failed: %s", ErrorStr(err)); + } + + return false; +} + +uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const +{ + CHIPoBLEConState * conState = const_cast(this)->GetConnectionState(conId); + return (conState != NULL) ? conState->mtu : 0; +} + +bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle pBuf) +{ + ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported"); + return false; +} + +bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle pBuf) +{ + ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported"); + return false; +} + +bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, + const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported"); + return false; +} + +void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) +{ + // Nothing to do +} + +bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle data) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + int ret; + + VerifyOrExit(IsSubscribed(conId), err = CHIP_ERROR_INVALID_ARGUMENT); + ret = bk_ble_send_noti_value(data->DataLength(), data->Start(), 0, SVR_FFF6_TX_VALUE); + err = MapBLEError(ret); +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err)); + return false; + } + + return true; +} + +/******************************************************************************* + * Private functions + *******************************************************************************/ + +CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // If the device name is not specified, generate a CHIP-standard name based on the bottom digits of the Chip device id. + uint16_t discriminator; + SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); + + if (!mFlags.Has(Flags::kDeviceNameSet)) + { + snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator); + mDeviceName[kMaxDeviceNameLength] = 0; + } + + // Configure the BLE device name. + sInstance.mFlags.Set(Flags::kDeviceNameDefSet); + bk_ble_appm_set_dev_name(kMaxDeviceNameLength, (uint8_t *) mDeviceName); +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::StartAdvertising(void) +{ + ble_err_t bk_err; + CHIP_ERROR err = CHIP_NO_ERROR; + + ChipLogProgress(DeviceLayer, "StartAdvertising..."); + ChipLogProgress(DeviceLayer, "BLE flag = %x", mFlags.Raw()); + if ((!mFlags.Has(Flags::kDeviceNameSet)) && (!mFlags.Has(Flags::kDeviceNameDefSet))) + { + err = sInstance.ConfigureAdvertisingData(); + SuccessOrExit(err); + } + // Post a CHIPoBLEAdvertisingChange(Stopped) event. + if (mFlags.Has(Flags::kBEKENBLEADVStop)) + { + bk_ble_delete_advertising(adv_actv_idx, beken_ble_cmd_cb); + mFlags.Clear(Flags::kBEKENBLEADVStop); + ChipDeviceEvent advChange; + advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; + advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped; + PlatformMgr().PostEventOrDie(&advChange); + goto exit; + } + else if (!mFlags.Has(Flags::kBEKENBLEADVCreate)) + { + ChipLogProgress(DeviceLayer, "BLE ADVCreate..."); + uint16_t adv_int_min; + uint16_t adv_int_max; + ble_adv_param_t adv_param; + + memset(&adv_param, 0, sizeof(adv_param)); + + if (mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + adv_int_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN; + adv_int_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX; + mFlags.Set(Flags::kAdvertisingIsFastADV); + } + else + { + adv_int_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; + adv_int_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; + mFlags.Clear(Flags::kAdvertisingIsFastADV); + } + + adv_actv_idx = bk_ble_get_idle_actv_idx_handle(); + if (UNKNOW_ACT_IDX == adv_actv_idx) + { + ChipLogError(DeviceLayer, "adv act-idx:%d error", adv_actv_idx); + return MapBLEError(-1); + } + adv_param.chnl_map = 7; + adv_param.adv_intv_max = 160; + adv_param.adv_intv_min = 160; + adv_param.own_addr_type = 0; + adv_param.adv_type = 0; + adv_param.adv_prop = 3; + adv_param.prim_phy = 1; + // bk_ble_create_advertising(adv_actv_idx, 7, adv_int_min, adv_int_max, beken_ble_cmd_cb); + bk_err = bk_ble_create_advertising(adv_actv_idx, &adv_param, beken_ble_cmd_cb); + if (bk_err != BK_OK) + { + ChipLogProgress(DeviceLayer, "BLE ADVCreate ret= %x.", bk_err); + } + ChipLogProgress(DeviceLayer, "BLE ADVCreate ret= %x. adv_actv_idx = %x", bk_err, adv_actv_idx); + sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded); + goto exit; + } + else if (!mFlags.Has(Flags::kBEKENBLEADVSetData)) + { + ChipLogProgress(DeviceLayer, "BLE SetData..."); + ChipBLEDeviceIdentificationInfo deviceIdInfo; + uint8_t advData[MAX_ADV_DATA_LEN] = { 0 }; + uint8_t index = 0; + /**************** Prepare advertising data *******************************************/ + memset(advData, 0, sizeof(advData)); + advData[index++] = 0x02; // length + advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags + advData[index++] = CHIP_ADV_DATA_FLAGS; // AD value + advData[index++] = static_cast(sizeof(deviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1); + ; // length + advData[index++] = 0x16; // AD type: (Service Data - 16-bit UUID) + advData[index++] = static_cast(_svc_uuid[0] & 0xFF); // AD value + advData[index++] = static_cast(_svc_uuid[1] & 0xFF); // AD value + err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "GetBLEDeviceIdentificationInfo(): %s", ErrorStr(err)); + ExitNow(); + } + +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + deviceIdInfo.SetAdditionalDataFlag(true); +#endif + VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG); + + memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo)); + index = static_cast(index + sizeof(deviceIdInfo)); + bk_ble_set_adv_data(adv_actv_idx, advData, index, beken_ble_cmd_cb); + goto exit; + } + else if (!mFlags.Has(Flags::kBEKENBLEADVSetRsp)) + { + /// uint8_t advData[MAX_ADV_DATA_LEN] = { 0 }; + /// bk_ble_set_scan_rsp_data(adv_actv_idx, advData, 0xF, beken_ble_cmd_cb); + sInstance.mFlags.Set(Flags::kBEKENBLEADVSetRsp); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + goto exit; + } + else if (!mFlags.Has(Flags::kBEKENBLEADVStarted)) + { + ChipLogProgress(DeviceLayer, "BLE Started..."); + bk_ble_start_advertising(adv_actv_idx, 0, beken_ble_cmd_cb); + goto exit; + } + + if (mFlags.Has(Flags::kBEKENBLEADVStarted)) + { + ChipDeviceEvent advChange; + advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; + advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started; + PlatformMgr().PostEventOrDie(&advChange); + } + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::StopAdvertising(void) +{ + // Change flag status to the 'not Advertising state' + if ((mFlags.Has(Flags::kBEKENBLEADVStarted)) && (!mFlags.Has(Flags::kBEKENBLEADVStop))) + { + mFlags.Set(Flags::kBEKENBLEADVStop); + bk_ble_stop_advertising(adv_actv_idx, beken_ble_cmd_cb); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopping"); + goto exit; + } + + // Post a CHIPoBLEAdvertisingChange(Stopped) event. + if (mFlags.Has(Flags::kBEKENBLEADVStop)) + { + bk_ble_delete_advertising(adv_actv_idx, beken_ble_cmd_cb); + mFlags.Clear(Flags::kBEKENBLEADVStop); + ChipDeviceEvent advChange; + advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; + advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped; + PlatformMgr().PostEventOrDie(&advChange); + } +exit: + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) +{ + switch (bleErr) + { + case BK_ERR_BLE_SUCCESS: + return CHIP_NO_ERROR; + default: + return CHIP_ERROR_INCORRECT_STATE; + } +} + +void BLEManagerImpl::DriveBLEState(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Check if BLE stack is initialized + VerifyOrExit(mFlags.Has(Flags::kAMEBABLEStackInitialized), /* */); + if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled) + { + if (!mFlags.Has(Flags::kBekenBLESGATTSReady)) + { + beken_ble_init(); + goto exit; + } + } + +// If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled and the device is fully provisioned, the CHIPoBLE +// advertising will be disabled. +#if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + if (ConfigurationMgr().IsFullyProvisioned()) + { + mFlags.Clear(Flags::kAdvertisingEnabled); + mFlags.Clear(Flags::kAdvertisingRefreshNeeded); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned"); + } +#endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + + if ((!mFlags.Has(Flags::kFastAdvertisingEnabled)) && (!mFlags.Has(Flags::kSlowAdvertisingEnabled))) + { + mFlags.Clear(Flags::kAdvertisingEnabled); + mFlags.Clear(Flags::kAdvertisingRefreshNeeded); + } + + if (mFlags.Has(Flags::kAdvertisingRefreshNeeded)) + { + if (mFlags.Has(Flags::kBEKENBLEADVStarted)) + { + err = StopAdvertising(); + SuccessOrExit(err); + goto exit; + } + else if (mFlags.Has(Flags::kBEKENBLEADVStarted)) + { + bk_ble_delete_advertising(adv_actv_idx, beken_ble_cmd_cb); + goto exit; + } + } + + // Start advertising if needed... + if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && + ((mFlags.Has(Flags::kAdvertisingEnabled)) || (mFlags.Has(Flags::kAdvertisingRefreshNeeded)))) + { + // Start/re-start advertising if not already started, or if there is a pending change + // to the advertising configuration. + if (!mFlags.Has(Flags::kBEKENBLEADVStarted)) + { + err = StartAdvertising(); + SuccessOrExit(err); + } + else + { + mFlags.Clear(Flags::kAdvertisingRefreshNeeded); + } + } + // Otherwise, stop advertising if it is enabled. + else if ((mFlags.Has(Flags::kBEKENBLEADVStarted)) || (mFlags.Has(Flags::kBEKENBLEADVStop))) + { + err = StopAdvertising(); + SuccessOrExit(err); + ChipLogProgress(DeviceLayer, "Stopped Advertising"); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + } +} + +void BLEManagerImpl::DriveBLEState(intptr_t arg) +{ + sInstance.DriveBLEState(); +} + +void BLEManagerImpl::DriveBLEExtPerf(intptr_t arg) +{ + int arg_int = static_cast(arg); + int event = arg_int & 0xFFU; + switch (event) + { + case DriveBLEExtPerfEvt_DISCONNECT: { + uint8_t conn_indx = (arg_int >> 8) & 0xFFU; + sInstance.CloseConnection(conn_indx); + } + break; + default: + break; + } +} + +/******************************************************************************* + * FreeRTOS Task Management Functions + *******************************************************************************/ +void BLEManagerImpl::ble_adv_timer_timeout_handle(TimerHandle_t xTimer) +{ + if (sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop Fast advertisement"); + + sInstance.mFlags.Clear(Flags::kFastAdvertisingEnabled); + // Stop advertising, change interval and restart it; + sInstance.StopAdvertising(); + } + else if (sInstance._IsAdvertisingEnabled()) + { + // Advertisement time expired. Stop advertising + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop slow advertisement"); + sInstance.mFlags.Clear(Flags::kSlowAdvertisingEnabled); + sInstance.StopAdvertising(); + } +} + +void BLEManagerImpl::CancelBleAdvTimeoutTimer(void) +{ + if (xTimerIsTimerActive(bleFastAdvTimer)) + { + if (xTimerStop(bleFastAdvTimer, 0) == pdFAIL) + { + ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer"); + sInstance.mFlags.Clear(Flags::kBEKENBLEAdvTimerRun); + } + } +} + +void BLEManagerImpl::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs) +{ + CancelBleAdvTimeoutTimer(); + // timer is not active, change its period to required value (== restart). + // FreeRTOS- Block for a maximum of 100 ticks if the change period command + // cannot immediately be sent to the timer command queue. + if (xTimerChangePeriod(bleFastAdvTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) + { + ChipLogError(DeviceLayer, "Failed to start BledAdv timeout timer"); + } + else + { + xTimerStart(bleFastAdvTimer, BEKEN_WAIT_FOREVER); + sInstance.mFlags.Set(Flags::kBEKENBLEAdvTimerRun); + } +} + +CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId) +{ + CHIPoBLEConState * bleConnState = GetConnectionState(conId, false); + + if (bleConnState != NULL) + { + bleConnState->subscribed = 1; + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_NO_MEMORY; +} + +bool BLEManagerImpl::UnsetSubscribed(uint16_t conId) +{ + CHIPoBLEConState * bleConnState = GetConnectionState(conId, false); + + if (bleConnState != NULL) + { + bleConnState->subscribed = 0; + return true; + } + + return false; +} + +bool BLEManagerImpl::IsSubscribed(uint16_t conId) +{ + CHIPoBLEConState * bleConnState = GetConnectionState(conId, false); + + if (bleConnState != NULL) + { + if (bleConnState->subscribed) + { + return true; + } + } + return false; +} + +void BLEManagerImpl::HandleRXCharWrite(uint8_t * p_value, uint16_t len, uint8_t conn_id) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + PacketBufferHandle buf = System::PacketBufferHandle::New(len, 0); + memcpy(buf->Start(), p_value, len); + buf->SetDataLength(len); + + // Post an event to the Chip queue to deliver the data into the Chip stack. + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEWriteReceived; + event.CHIPoBLEWriteReceived.ConId = (uint16_t) conn_id; + event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease(); + PlatformMgr().PostEventOrDie(&event); + } + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err)); + } +} + +void BLEManagerImpl::HandleTXCharConfirm(CHIPoBLEConState * conState, int status) +{ + // If the confirmation was successful... + if (status == 0) + { + // Post an event to the Chip queue to process the indicate confirmation. + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm; + event.CHIPoBLEIndicateConfirm.ConId = conState->conn_idx; + PlatformMgr().PostEventOrDie(&event); + } + else + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEConnectionError; + event.CHIPoBLEConnectionError.ConId = conState->conn_idx; + event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT; + PlatformMgr().PostEventOrDie(&event); + } +} + +void BLEManagerImpl::beken_ble_cmd_cb(ble_cmd_t cmd, ble_cmd_param_t * param) +{ + ChipLogProgress(DeviceLayer, "cmd:%d idx:%d status:%d\r\n", cmd, param->cmd_idx, param->status); + switch (cmd) + { + case BLE_CREATE_ADV: + sInstance.mFlags.Set(Flags::kBEKENBLEADVCreate); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + break; + case BLE_SET_ADV_DATA: + sInstance.mFlags.Set(Flags::kBEKENBLEADVSetData); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + break; + case BLE_SET_RSP_DATA: + sInstance.mFlags.Set(Flags::kBEKENBLEADVSetRsp); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + break; + case BLE_START_ADV: { + uint32_t bleAdvTimeoutMs; + sInstance.mFlags.Set(Flags::kBEKENBLEADVStarted); + // if (sInstance.mFlags.Has(Flags::kAdvertisingIsFastADV)){ + bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME; + //}else{ + // bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT; + //} + StartBleAdvTimeoutTimer(bleAdvTimeoutMs); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + } + break; + case BLE_STOP_ADV: + sInstance.mFlags.Clear(Flags::kBEKENBLEADVStarted); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); + CancelBleAdvTimeoutTimer(); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + break; + case BLE_DELETE_ADV: + sInstance.mFlags.Clear(Flags::kBEKENBLEADVCreate); + sInstance.mFlags.Clear(Flags::kBEKENBLEADVSetData); + sInstance.mFlags.Clear(Flags::kBEKENBLEADVSetRsp); + sInstance.mFlags.Clear(Flags::kBEKENBLEADVStarted); + sInstance.adv_actv_idx = kUnusedIndex; + PlatformMgr().ScheduleWork(DriveBLEState, 0); + break; + case BLE_CONN_DIS_CONN: + break; + default: + break; + } +} + +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING +void BLEManagerImpl::HandleC3CharRead(void * param) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + chip::System::PacketBufferHandle bufferHandle; + ble_read_req_t * r_req = (ble_read_req_t *) param; + + AdditionalDataPayloadGeneratorParams additionalDataPayloadParams; + BitFlags additionalDataFields; + +#if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) + uint8_t rotatingDeviceIdUniqueId[ConfigurationManager::kRotatingDeviceIDUniqueIDLength] = {}; + MutableByteSpan rotatingDeviceIdUniqueIdSpan(rotatingDeviceIdUniqueId); + + err = DeviceLayer::GetDeviceInstanceInfoProvider()->GetRotatingDeviceIdUniqueId(rotatingDeviceIdUniqueIdSpan); + SuccessOrExit(err); + err = ConfigurationMgr().GetLifetimeCounter(additionalDataPayloadParams.rotatingDeviceIdLifetimeCounter); + SuccessOrExit(err); + additionalDataPayloadParams.rotatingDeviceIdUniqueId = rotatingDeviceIdUniqueIdSpan; + additionalDataFields.Set(AdditionalDataFields::RotatingDeviceId); +#endif /* CHIP_ENABLE_ROTATING_DEVICE_ID */ + + err = AdditionalDataPayloadGenerator().generateAdditionalDataPayload(additionalDataPayloadParams, bufferHandle, + additionalDataFields); + SuccessOrExit(err); + if (r_req->value == NULL) + { + ChipLogError(DeviceLayer, "param->value == NULL"); + return; + } + memcpy(r_req->value, bufferHandle->Start(), bufferHandle->DataLength()); + r_req->length = bufferHandle->DataLength(); +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data"); + } + return; +} +#endif + +void BLEManagerImpl::ble_event_notice(ble_notice_t notice, void * param) +{ + /// BLEManagerImpl * blemgr = static_cast(param); + static int conn_idx = 0; // TODO. will improve this when driver notify the status and channel to app. + switch (notice) + { + case BLE_5_STACK_OK: { + ChipLogProgress(DeviceLayer, "ble stack ok"); + sInstance.mFlags.Set(Flags::kAMEBABLEStackInitialized); + } + break; + case BLE_5_WRITE_EVENT: { + ble_write_req_t * w_req = (ble_write_req_t *) param; + ChipLogProgress(DeviceLayer, "write_cb:conn_idx:%d, prf_id:%d, add_id:%d, len:%d, data[0]:%02x\r\n", w_req->conn_idx, + w_req->prf_id, w_req->att_idx, w_req->len, w_req->value[0]); + if (w_req->att_idx == SVR_FFF6_TX_VALUE) + { + sInstance.HandleRXCharWrite((uint8_t *) &w_req->value[0], w_req->len, w_req->conn_idx); + } + else if (w_req->att_idx == SVR_FFF6_TX_CFG) + { + int notificationsEnabled = w_req->value[0] | (w_req->value[0] << 8); + sInstance.HandleTXCharCCCDWrite(w_req->conn_idx, notificationsEnabled); + } + else if (w_req->att_idx == SVR_FFF6_RX_VALUE) + { + sInstance.HandleRXCharWrite((uint8_t *) &w_req->value[0], w_req->len, w_req->conn_idx); + } + break; + } + case BLE_5_READ_EVENT: { + ble_read_req_t * r_req = (ble_read_req_t *) param; + ChipLogProgress(DeviceLayer, "read_cb:conn_idx:%d, prf_id:%d, add_id:%d\r\n", r_req->conn_idx, r_req->prf_id, + r_req->att_idx); + if (r_req->att_idx == SVR_FFF6_RX_VALUE) + { + sInstance.HandleTXCharRead(param); + } + if (r_req->att_idx == SVR_FFF6_TX_CFG) + { + sInstance.HandleTXCharCCCDRead(param); + } +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + if (r_req->att_idx == SVR_FFF6_C3_VALUE) + { + ChipLogProgress(DeviceLayer, "SVR_FFF6_OPT_VALUE!!!!\r\n"); + sInstance.HandleTXCharRead((void *) param); + } +#endif + break; + } + case BLE_5_TX_DONE: { + ChipLogProgress(DeviceLayer, "BLE_5_TX_DONE"); +#if 0 + tx_done_rsp_t* txd_rsp = (tx_done_rsp_t*)param; + if(txd_rsp) { + CHIPoBLEConState * conState = sInstance.GetConnectionState(txd_rsp->conn_idx,false); + if (conState != NULL) + { + sInstance.HandleTXCharConfirm(conState, txd_rsp->status); + } + } +#endif + CHIPoBLEConState * conState = sInstance.GetConnectionState(conn_idx, false); + if (conState != NULL) + { + sInstance.HandleTXCharConfirm(conState, 0); + } + } + break; + case BLE_5_MTU_CHANGE: { + ble_mtu_change_t * m_ind = (ble_mtu_change_t *) param; + ChipLogProgress(DeviceLayer, "m_ind:conn_idx:%d, mtu_size:%d\r\n", m_ind->conn_idx, m_ind->mtu_size); + CHIPoBLEConState * conState = sInstance.GetConnectionState(m_ind->conn_idx); + if (conState != NULL) + { + conState->mtu = (m_ind->mtu_size >= (1 << 10)) ? ((1 << 10) - 1) : m_ind->mtu_size; + } + break; + } + case BLE_5_CONNECT_EVENT: { + ble_conn_ind_t * c_ind = (ble_conn_ind_t *) param; + ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", c_ind->conn_idx); + ChipLogProgress(DeviceLayer, "c_ind:conn_idx:%d, addr_type:%d, peer_addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n", + c_ind->conn_idx, c_ind->peer_addr_type, c_ind->peer_addr[0], c_ind->peer_addr[1], c_ind->peer_addr[2], + c_ind->peer_addr[3], c_ind->peer_addr[4], c_ind->peer_addr[5]); + sInstance.mFlags.Clear(Flags::kBEKENBLEADVStarted); + CHIPoBLEConState * bleConnState = sInstance.GetConnectionState(c_ind->conn_idx, true); + if (bleConnState == NULL) + { + ChipLogError(DeviceLayer, "BLE_5_CONNECT_EVENT failed"); + int ext_evt = DriveBLEExtPerfEvt_DISCONNECT | (c_ind->conn_idx << 8); + PlatformMgr().ScheduleWork(DriveBLEExtPerf, ext_evt); + } + conn_idx = c_ind->conn_idx; + break; + } + case BLE_5_DISCONNECT_EVENT: { + ble_discon_ind_t * d_ind = (ble_discon_ind_t *) param; + ChipLogProgress(DeviceLayer, "d_ind:conn_idx:%d,reason:%d\r\n", d_ind->conn_idx, d_ind->reason); + sInstance.HandleGAPDisconnect(d_ind->conn_idx, d_ind->reason); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + break; + } + case BLE_5_ATT_INFO_REQ: { + ble_att_info_req_t * a_ind = (ble_att_info_req_t *) param; + ChipLogProgress(DeviceLayer, "a_ind:conn_idx:%d\r\n", a_ind->conn_idx); + if (SVR_FFF6_RX_VALUE == a_ind->att_idx) + { + a_ind->length = 512; + a_ind->status = BK_ERR_BLE_SUCCESS; + } + else if (SVR_FFF6_TX_CFG == a_ind->att_idx) + { + a_ind->length = 2; + a_ind->status = BK_ERR_BLE_SUCCESS; + } + break; + } + case BLE_5_CREATE_DB: { + ble_create_db_t * cd_ind = (ble_create_db_t *) param; + ChipLogProgress(DeviceLayer, "cd_ind:prf_id:%d, status:%d\r\n", cd_ind->prf_id, cd_ind->status); + sInstance.mFlags.Set(Flags::kBekenBLESGATTSReady); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + break; + } + default: { + ChipLogProgress(DeviceLayer, "Unhandled event:%x", notice); + } + break; + } +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/Beken/BLEManagerImpl.h b/src/platform/Beken/BLEManagerImpl.h new file mode 100644 index 00000000000000..02a01c050d25f1 --- /dev/null +++ b/src/platform/Beken/BLEManagerImpl.h @@ -0,0 +1,232 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include "FreeRTOS.h" +#include "event_groups.h" + +#include "matter_pal.h" + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +using namespace chip::Ble; + +/** + * Concrete implementation of the BLEManager singleton object for the Ameba 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); + CHIP_ERROR _Shutdown() { return CHIP_NO_ERROR; } + CHIPoBLEServiceMode _GetCHIPoBLEServiceMode(void); + CHIP_ERROR _SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val); + 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 Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + bool CloseConnection(BLE_CONNECTION_OBJECT conId) override; + uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override; + bool SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle pBuf) override; + bool SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle pBuf) override; + bool SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle pBuf) override; + bool SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + + // ===== Members that implement virtual methods on BleApplicationDelegate. + + void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override; + + // ===== Members for internal use by the following friends. + + friend BLEManager & BLEMgr(void); + friend BLEManagerImpl & BLEMgrImpl(void); + + static BLEManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + enum class Flags : uint32_t + { + kAdvertisingEnabled = 0x0001, + kAdvertisingRefreshNeeded = 0x0002, + kFastAdvertisingEnabled = 0x0004, + kSlowAdvertisingEnabled = 0x0008, + kAdvertisingIsFastADV = 0x0010, + kAMEBABLEStackInitialized = 0x0020, + kDeviceNameSet = 0x0040, + kDeviceNameDefSet = 0x0080, + + kBekenBLESGATTSReady = 0x00100, + kBEKENBLEADVCreate = 0x00200, + kBEKENBLEADVSetData = 0x00400, + kBEKENBLEADVSetRsp = 0x00800, + kBEKENBLEADVStarted = 0x01000, + kBEKENBLEADVStop = 0x02000, + kBEKENBLEADVDelet = 0x04000, + kBEKENBLEAdvTimer = 0x08000, + kBEKENBLEAdvTimerRun = 0x10000, + }; + + BitFlags mFlags; + + enum + { + kMaxConnections = BLE_LAYER_NUM_BLE_ENDPOINTS, + kMaxDeviceNameLength = 16, + kUnusedIndex = 0xFF, + }; + + struct CHIPoBLEConState + { + uint8_t conn_idx; + uint16_t mtu : 16; + uint16_t allocated : 1; + uint16_t subscribed : 1; + uint16_t unused : 6; + void Set(uint16_t conId) + { + conn_idx = conId; + mtu = 0; + allocated = 1; + subscribed = 0; + unused = 0; + } + void Reset() + { + conn_idx = kUnusedIndex; + mtu = 0; + allocated = 0; + subscribed = 0; + unused = 0; + } + }; + CHIPoBLEConState mBleConnections[kMaxConnections]; + + CHIPoBLEServiceMode mServiceMode; + + uint16_t mNumGAPCons; + uint16_t mTXCharCCCDAttrHandle; + char mDeviceName[kMaxDeviceNameLength + 1]; + CHIP_ERROR MapBLEError(int bleErr); + + void DriveBLEState(void); + CHIP_ERROR StartAdvertising(void); + CHIP_ERROR StopAdvertising(void); + CHIP_ERROR ConfigureAdvertisingData(void); + + void HandleRXCharWrite(uint8_t *, uint16_t, uint8_t); + void HandleTXCharRead(void * param); + void HandleTXCharCCCDRead(void * param); + void HandleTXCharCCCDWrite(int, int, int ind = 0); + void HandleTXCharConfirm(CHIPoBLEConState * conState, int status); + CHIP_ERROR HandleTXComplete(int); + CHIP_ERROR HandleGAPConnect(uint16_t); + CHIP_ERROR HandleGAPDisconnect(uint16_t, uint16_t); + CHIP_ERROR SetSubscribed(uint16_t conId); + bool UnsetSubscribed(uint16_t conId); + bool IsSubscribed(uint16_t conId); + + bool RemoveConnection(uint8_t connectionHandle); + + uint8_t adv_actv_idx; + BLEManagerImpl::CHIPoBLEConState * GetConnectionState(uint8_t connectionHandle, bool allocate = false); + static void ble_event_notice(ble_notice_t notice, void * param); + static void beken_ble_cmd_cb(ble_cmd_t cmd, ble_cmd_param_t * param); + static void DriveBLEState(intptr_t arg); + static void DriveBLEExtPerf(intptr_t arg); + static int beken_ble_init(void); + static void ble_adv_timer_timeout_handle(TimerHandle_t xTimer); + static void CancelBleAdvTimeoutTimer(void); + static void StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs); +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + void HandleC3CharRead(void * param); +#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 platforms. + */ +inline BLEManagerImpl & BLEMgrImpl(void) +{ + return BLEManagerImpl::sInstance; +} + +inline BleLayer * BLEManagerImpl::_GetBleLayer() +{ + return this; +} + +inline BLEManager::CHIPoBLEServiceMode BLEManagerImpl::_GetCHIPoBLEServiceMode(void) +{ + return mServiceMode; +} + +inline bool BLEManagerImpl::_IsAdvertisingEnabled(void) +{ + return mFlags.Has(Flags::kAdvertisingEnabled); +} + +inline bool BLEManagerImpl::_IsAdvertising(void) +{ + return mFlags.Has(Flags::kBEKENBLEADVStarted); +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/Beken/BUILD.gn b/src/platform/Beken/BUILD.gn new file mode 100755 index 00000000000000..f341ffb4ebc023 --- /dev/null +++ b/src/platform/Beken/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2021 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. + +import("//build_overrides/chip.gni") + +import("${chip_root}/src/platform/device.gni") + +assert(chip_device_platform == "beken") + +static_library("Beken") { + sources = [ + "../SingletonConfigurationManager.cpp", + "BLEManagerImpl.cpp", + "BLEManagerImpl.h", + "BekenConfig.cpp", + "BekenConfig.h", + "CHIPDevicePlatformConfig.h", + "CHIPDevicePlatformEvent.h", + "CHIPMem-Platform.cpp", + "ConfigurationManagerImpl.cpp", + "ConfigurationManagerImpl.h", + "ConnectivityManagerImpl.cpp", + "ConnectivityManagerImpl.h", + + #"DeviceInfoProviderImpl.cpp", + #"DeviceInfoProviderImpl.h", + "DiagnosticDataProviderImpl.cpp", + "DiagnosticDataProviderImpl.h", + "KeyValueStoreManagerImpl.cpp", + "KeyValueStoreManagerImpl.h", + "Logging.cpp", + "LwIPCoreLock.cpp", + "NetworkCommissioningWiFiDriver.cpp", + "OTAImageProcessorImpl.cpp", + "OTAImageProcessorImpl.h", + "PlatformManagerImpl.cpp", + "PlatformManagerImpl.h", + "SoftwareUpdateManagerImpl.h", + "SystemPlatformConfig.h", + "SystemTimeSupport.cpp", + ] + + deps = [ + "${chip_root}/src/lib/dnssd:platform_header", + "${chip_root}/src/setup_payload", + ] + + public_deps = [ + "${chip_root}/src/crypto", + "${chip_root}/src/platform:platform_base", + ] +} diff --git a/src/platform/Beken/BekenConfig.cpp b/src/platform/Beken/BekenConfig.cpp new file mode 100644 index 00000000000000..df34a3be61024b --- /dev/null +++ b/src/platform/Beken/BekenConfig.cpp @@ -0,0 +1,316 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include +#include +#include +#include +#include +#include + +#include "matter_pal.h" + +enum +{ + kPrefsTypeBoolean = 1, + kPrefsTypeInteger = 2, + kPrefsTypeString = 3, + kPrefsTypeBuffer = 4, + kPrefsTypeBinary = 5 +}; + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +// *** CAUTION ***: Changing the names or namespaces of these values will *break* existing devices. + +// NVS namespaces used to store device configuration information. +const char BekenConfig::kConfigNamespace_ChipFactory[] = "chip-factory"; +const char BekenConfig::kConfigNamespace_ChipConfig[] = "chip-config"; +const char BekenConfig::kConfigNamespace_ChipCounters[] = "chip-counters"; + +// Keys stored in the chip-factory namespace +const BekenConfig::Key BekenConfig::kConfigKey_SerialNum = { kConfigNamespace_ChipFactory, "serial-num" }; +const BekenConfig::Key BekenConfig::kConfigKey_MfrDeviceId = { kConfigNamespace_ChipFactory, "device-id" }; +const BekenConfig::Key BekenConfig::kConfigKey_MfrDeviceCert = { kConfigNamespace_ChipFactory, "device-cert" }; +const BekenConfig::Key BekenConfig::kConfigKey_MfrDeviceICACerts = { kConfigNamespace_ChipFactory, "device-ca-certs" }; +const BekenConfig::Key BekenConfig::kConfigKey_MfrDevicePrivateKey = { kConfigNamespace_ChipFactory, "device-key" }; +const BekenConfig::Key BekenConfig::kConfigKey_HardwareVersion = { kConfigNamespace_ChipFactory, "hardware-ver" }; +const BekenConfig::Key BekenConfig::kConfigKey_ManufacturingDate = { kConfigNamespace_ChipFactory, "mfg-date" }; +const BekenConfig::Key BekenConfig::kConfigKey_SetupPinCode = { kConfigNamespace_ChipFactory, "pin-code" }; +const BekenConfig::Key BekenConfig::kConfigKey_SetupDiscriminator = { kConfigNamespace_ChipFactory, "discriminator" }; +const BekenConfig::Key BekenConfig::kConfigKey_Spake2pIterationCount = { kConfigNamespace_ChipFactory, "iteration-count" }; +const BekenConfig::Key BekenConfig::kConfigKey_Spake2pSalt = { kConfigNamespace_ChipFactory, "salt" }; +const BekenConfig::Key BekenConfig::kConfigKey_Spake2pVerifier = { kConfigNamespace_ChipFactory, "verifier" }; +const BekenConfig::Key BekenConfig::kConfigKey_UniqueId = { kConfigNamespace_ChipFactory, "uniqueId" }; + +// Keys stored in the chip-config namespace +const BekenConfig::Key BekenConfig::kConfigKey_FabricId = { kConfigNamespace_ChipConfig, "fabric-id" }; +const BekenConfig::Key BekenConfig::kConfigKey_ServiceConfig = { kConfigNamespace_ChipConfig, "service-config" }; +const BekenConfig::Key BekenConfig::kConfigKey_PairedAccountId = { kConfigNamespace_ChipConfig, "account-id" }; +const BekenConfig::Key BekenConfig::kConfigKey_ServiceId = { kConfigNamespace_ChipConfig, "service-id" }; +const BekenConfig::Key BekenConfig::kConfigKey_GroupKeyIndex = { kConfigNamespace_ChipConfig, "group-key-index" }; +const BekenConfig::Key BekenConfig::kConfigKey_LastUsedEpochKeyId = { kConfigNamespace_ChipConfig, "last-ek-id" }; +const BekenConfig::Key BekenConfig::kConfigKey_FailSafeArmed = { kConfigNamespace_ChipConfig, "fail-safe-armed" }; +const BekenConfig::Key BekenConfig::kConfigKey_WiFiStationSecType = { kConfigNamespace_ChipConfig, "sta-sec-type" }; +const BekenConfig::Key BekenConfig::kConfigKey_OperationalDeviceId = { kConfigNamespace_ChipConfig, "op-device-id" }; +const BekenConfig::Key BekenConfig::kConfigKey_OperationalDeviceCert = { kConfigNamespace_ChipConfig, "op-device-cert" }; +const BekenConfig::Key BekenConfig::kConfigKey_OperationalDeviceICACerts = { kConfigNamespace_ChipConfig, "op-device-ca-certs" }; +const BekenConfig::Key BekenConfig::kConfigKey_OperationalDevicePrivateKey = { kConfigNamespace_ChipConfig, "op-device-key" }; +const BekenConfig::Key BekenConfig::kConfigKey_RegulatoryLocation = { kConfigNamespace_ChipConfig, "regulatory-location" }; +const BekenConfig::Key BekenConfig::kConfigKey_CountryCode = { kConfigNamespace_ChipConfig, "country-code" }; +const BekenConfig::Key BekenConfig::kConfigKey_Breadcrumb = { kConfigNamespace_ChipConfig, "breadcrumb" }; + +// Keys stored in the Chip-counters namespace +const BekenConfig::Key BekenConfig::kCounterKey_RebootCount = { kConfigNamespace_ChipCounters, "reboot-count" }; +const BekenConfig::Key BekenConfig::kCounterKey_UpTime = { kConfigNamespace_ChipCounters, "up-time" }; +const BekenConfig::Key BekenConfig::kCounterKey_TotalOperationalHours = { kConfigNamespace_ChipCounters, "total-hours" }; +const BekenConfig::Key BekenConfig::kCounterKey_BootReason = { kConfigNamespace_ChipCounters, "boot-reason" }; + +CHIP_ERROR BekenConfig::ReadConfigValue(Key key, bool & val) +{ + uint32_t success = 0; + uint32_t out_length = 0; + uint8_t intval = 0; + success = bk_read_data(key.Namespace, key.Name, (char *) &intval, 1, &out_length); + + if (kNoErr != success) + ChipLogProgress(DeviceLayer, "bk_read_data: %s %s failed\n", (char *) key.Namespace, (char *) key.Name); + + val = (intval != 0); + if (kNoErr == success) + return CHIP_NO_ERROR; + else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +} + +CHIP_ERROR BekenConfig::ReadConfigValue(Key key, uint32_t & val) +{ + uint32_t success = 0; + uint32_t out_length = 0; + uint32_t temp_data = 0; + + success = bk_read_data(key.Namespace, key.Name, (char *) &temp_data, sizeof(uint32_t), &out_length); + + if (kNoErr != success) + ChipLogProgress(DeviceLayer, "bk_read_data: %s %s failed\n", (char *) key.Namespace, (char *) key.Name); + val = temp_data; + + if (kNoErr == success) + return CHIP_NO_ERROR; + else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +} + +CHIP_ERROR BekenConfig::ReadConfigValue(Key key, uint64_t & val) +{ + uint32_t success = 0; + uint32_t out_length = 0; + uint64_t temp_data = 0; + + success = bk_read_data(key.Namespace, key.Name, (char *) &temp_data, sizeof(uint64_t), &out_length); + + if (kNoErr != success) + ChipLogProgress(DeviceLayer, "bk_read_data: %s %s failed\n", (char *) key.Namespace, (char *) key.Name); + val = temp_data; + + if (kNoErr == success) + return CHIP_NO_ERROR; + else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +} + +CHIP_ERROR BekenConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) +{ + uint32_t success = 0; + uint32_t out_length = 0; + + success = bk_read_data(key.Namespace, key.Name, buf, bufSize, &out_length); + outLen = out_length; + + if (kNoErr != success) + ChipLogProgress(DeviceLayer, "bk_read_data: %s %s failed\n", (char *) key.Namespace, (char *) key.Name); + + if (kNoErr == success) + { + return CHIP_NO_ERROR; + } + else + { + outLen = 0; + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } +} + +CHIP_ERROR BekenConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + uint32_t success = 0; + uint32_t out_length = 0; + + success = bk_read_data(key.Namespace, key.Name, (char *) buf, bufSize, &out_length); + outLen = out_length; + + if (kNoErr != success) + ChipLogProgress(DeviceLayer, "bk_read_data: %s %s failed\n", (char *) key.Namespace, (char *) key.Name); + + if (kNoErr == success) + { + return CHIP_NO_ERROR; + } + else + { + outLen = 0; + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } +} + +CHIP_ERROR BekenConfig::WriteConfigValue(Key key, bool val) +{ + uint32_t success = 0; + uint8_t value = 0; + + if (val == 1) + { + value = 1; + } + else + { + value = 0; + } + + success = bk_write_data(key.Namespace, key.Name, (char *) &value, 1); + if (kNoErr != success) + ChipLogError(DeviceLayer, "bk_write_data: %s %s %s failed\n", (char *) key.Namespace, (char *) key.Name, + value ? "true" : "false"); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenConfig::WriteConfigValue(Key key, uint32_t val) +{ + uint32_t success = 0; + + success = bk_write_data(key.Namespace, key.Name, (char *) &val, sizeof(val)); + if (kNoErr != success) + ChipLogError(DeviceLayer, "bk_write_data: %s %s = %lu(0x%lx) failed\n", (char *) key.Namespace, (char *) key.Name, val, + val); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenConfig::WriteConfigValue(Key key, uint64_t val) +{ + uint32_t success = 0; + + success = bk_write_data(key.Namespace, key.Name, (char *) &val, sizeof(val)); + if (kNoErr != success) + ChipLogError(DeviceLayer, "bk_write_data: %s %s = %llu(0x%llx) failed\n", (char *) key.Namespace, (char *) key.Name, val, + val); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenConfig::WriteConfigValueStr(Key key, const char * str) +{ + uint32_t success = 0; + + success = bk_write_data(key.Namespace, key.Name, (char *) str, strlen(str)); + if (kNoErr != success) + ChipLogError(DeviceLayer, "bk_write_data: %s %s %s failed\n", (char *) key.Namespace, (char *) key.Name, (char *) str); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen) +{ + uint32_t success = 0; + strLen = (strLen > strlen(str)) ? strlen(str) : strLen; + + success = bk_write_data(key.Namespace, key.Name, (char *) str, strLen); + if (kNoErr != success) + ChipLogError(DeviceLayer, "bk_write_data: %s %s %s failed\n", (char *) key.Namespace, (char *) key.Name, (char *) str); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) +{ + uint32_t success = 0; + + success = bk_write_data(key.Namespace, key.Name, (char *) data, dataLen); + if (kNoErr != success) + ChipLogError(DeviceLayer, "bk_write_data: %s %s failed \r\n", key.Namespace, key.Name); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenConfig::ClearConfigValue(Key key) +{ + uint32_t success = 0; + + success = bk_clean_data(key.Namespace, key.Name); + if (kNoErr != success) + ChipLogProgress(DeviceLayer, "%s : %s %s failed\n", __FUNCTION__, key.Namespace, key.Name); + return CHIP_NO_ERROR; +} + +bool BekenConfig::ConfigValueExists(Key key) +{ + if (kNoErr == bk_ensure_name_data(key.Namespace, key.Name)) + { + return 1; + } + else + { + return 0; + } +} + +CHIP_ERROR BekenConfig::EnsureNamespace(const char * ns) +{ + uint32_t success = 0; + + success = bk_ensure_namespace(ns); + if (kNoErr != success) + { + ChipLogError(DeviceLayer, "dct_register_module failed\n"); + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenConfig::ClearNamespace(const char * ns) +{ + uint32_t success = 0; + + success = bK_clear_namespace(ns); + if (success != 0) + { + ChipLogError(DeviceLayer, "ClearNamespace failed\n"); + } + return CHIP_NO_ERROR; +} + +void BekenConfig::RunConfigUnitTest() {} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/BekenConfig.h b/src/platform/Beken/BekenConfig.h new file mode 100755 index 00000000000000..bc9317a858df32 --- /dev/null +++ b/src/platform/Beken/BekenConfig.h @@ -0,0 +1,116 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +namespace chip { +namespace DeviceLayer { +namespace Internal { + +class BekenConfig +{ +public: + struct Key; + + // Maximum length of an NVS key name. + static constexpr size_t kMaxConfigKeyNameLength = 15; + + // NVS namespaces used to store device configuration information. + static const char kConfigNamespace_ChipFactory[]; + static const char kConfigNamespace_ChipConfig[]; + static const char kConfigNamespace_ChipCounters[]; + + // Key definitions for well-known keys. + static const Key kConfigKey_SerialNum; + static const Key kConfigKey_MfrDeviceId; + static const Key kConfigKey_MfrDeviceCert; + static const Key kConfigKey_MfrDeviceICACerts; + static const Key kConfigKey_MfrDevicePrivateKey; + static const Key kConfigKey_HardwareVersion; + static const Key kConfigKey_ManufacturingDate; + static const Key kConfigKey_SetupPinCode; + static const Key kConfigKey_FabricId; + static const Key kConfigKey_ServiceConfig; + static const Key kConfigKey_PairedAccountId; + static const Key kConfigKey_ServiceId; + static const Key kConfigKey_FabricSecret; + static const Key kConfigKey_GroupKeyIndex; + static const Key kConfigKey_LastUsedEpochKeyId; + static const Key kConfigKey_FailSafeArmed; + static const Key kConfigKey_WiFiStationSecType; + static const Key kConfigKey_OperationalDeviceId; + static const Key kConfigKey_OperationalDeviceCert; + static const Key kConfigKey_OperationalDeviceICACerts; + static const Key kConfigKey_OperationalDevicePrivateKey; + static const Key kConfigKey_SetupDiscriminator; + static const Key kConfigKey_RegulatoryLocation; + static const Key kConfigKey_CountryCode; + static const Key kConfigKey_Breadcrumb; + static const Key kConfigKey_Spake2pIterationCount; + static const Key kConfigKey_Spake2pSalt; + static const Key kConfigKey_Spake2pVerifier; + + // Counter keys + static const Key kConfigKey_UniqueId; + static const Key kCounterKey_RebootCount; + static const Key kCounterKey_UpTime; + static const Key kCounterKey_TotalOperationalHours; + static const Key kCounterKey_BootReason; + + static const char kGroupKeyNamePrefix[]; + + // Config value accessors. + static CHIP_ERROR ReadConfigValue(Key key, bool & val); + static CHIP_ERROR ReadConfigValue(Key key, uint32_t & val); + static CHIP_ERROR ReadConfigValue(Key key, uint64_t & val); + static CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen); + static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen); + static CHIP_ERROR WriteConfigValue(Key key, bool val); + static CHIP_ERROR WriteConfigValue(Key key, uint32_t val); + static CHIP_ERROR WriteConfigValue(Key key, uint64_t val); + static CHIP_ERROR WriteConfigValueStr(Key key, const char * str); + static CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen); + static CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen); + static CHIP_ERROR ClearConfigValue(Key key); + static bool ConfigValueExists(Key key); + + static CHIP_ERROR EnsureNamespace(const char * ns); + static CHIP_ERROR ClearNamespace(const char * ns); + + static void RunConfigUnitTest(void); +}; + +struct BekenConfig::Key +{ + const char * Namespace; + const char * Name; + + bool operator==(const Key & other) const; +}; + +inline bool BekenConfig::Key::operator==(const Key & other) const +{ + return strcmp(Namespace, other.Namespace) == 0 && strcmp(Name, other.Name) == 0; +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/BlePlatformConfig.h b/src/platform/Beken/BlePlatformConfig.h new file mode 100644 index 00000000000000..30446cbca23c74 --- /dev/null +++ b/src/platform/Beken/BlePlatformConfig.h @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific configuration overrides for the CHIP BLE + * Layer on Beken platform. + * + */ + +#pragma once + +// ==================== Platform Adaptations ==================== + +#define BLE_CONNECTION_OBJECT uint16_t +#define BLE_CONNECTION_UNINITIALIZED (0xFFFF) +#define BLE_MAX_RECEIVE_WINDOW_SIZE 5 + +#define BLE_CONFIG_ERROR_MIN 6000000 +#define BLE_CONFIG_ERROR_MAX 6000999 + +// ========== Platform-specific Configuration Overrides ========= + +/* none so far */ diff --git a/src/platform/Beken/CHIPDevicePlatformConfig.h b/src/platform/Beken/CHIPDevicePlatformConfig.h new file mode 100755 index 00000000000000..cc0996df75f511 --- /dev/null +++ b/src/platform/Beken/CHIPDevicePlatformConfig.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific configuration overrides for the chip Device Layer + * on Beken platform. + */ + +#pragma once + +// ==================== Platform Adaptations ==================== +#define CHIP_CONFIG_ERROR_CLASS 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0 +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 + +#if CHIP_ENABLE_OPENTHREAD +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD 1 +#endif + +#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 0 + +// ========== Platform-specific Configuration ========= + +// These are configuration options that are unique to the platform. +// These can be overridden by the application as needed. + +// ... + +// ========== Platform-specific Configuration Overrides ========= + +#ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE +#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE 8192 +#endif // CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE + +#ifndef CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE +#define CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE 4096 +#endif // CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE + +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY 0 +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY 0 +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL 0 +#define CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH 0 + +#define CHIP_DEVICE_LAYER_NONE 0 + +// Use a default pairing code if one hasn't been provisioned in flash. +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 + +#define CONFIG_RENDEZVOUS_MODE 6 +#define CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY 2 + +#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DISCOVERY 1 diff --git a/src/platform/Beken/CHIPDevicePlatformEvent.h b/src/platform/Beken/CHIPDevicePlatformEvent.h new file mode 100644 index 00000000000000..a7ae46c356c2ee --- /dev/null +++ b/src/platform/Beken/CHIPDevicePlatformEvent.h @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Defines platform-specific event types and data for the chip + * Device Layer on Beken platforms. + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace DeviceEventType { + +/** + * Enumerates platform-specific event types that are visible to the application. + */ +enum PublicPlatformSpecificEventTypes +{ + kBKSystemEvent = kRange_PublicPlatformSpecific, +}; + +/** + * Enumerates platform-specific event types that are internal to the chip Device Layer. + */ +enum InternalPlatformSpecificEventTypes +{ + kQorvoBLEConnected = kRange_InternalPlatformSpecific, + kQorvoBLEDisconnected, + kCHIPoBLECCCWriteEvent, + kCHIPoBLERXCharWriteEvent, + kCHIPoBLETXCharWriteEvent, + kRtkWiFiStationConnectedEvent, +}; + +} // namespace DeviceEventType + +/** + * Represents platform-specific event information. + */ +struct ChipDevicePlatformEvent final +{ + // TODO - add platform specific definition extension + union + { + struct + { + uint8_t dummy; + } QorvoBLEConnected; + struct + { + uint8_t dummy; + } CHIPoBLECCCWriteEvent; + struct + { + uint8_t dummy; + } CHIPoBLERXCharWriteEvent; + struct + { + uint8_t dummy; + } CHIPoBLETXCharWriteEvent; + struct + { + union + { + uint16_t WiFiStaDisconnected; + } Data; + } BKSystemEvent; + }; +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/CHIPMem-Platform.cpp b/src/platform/Beken/CHIPMem-Platform.cpp new file mode 100644 index 00000000000000..e58aeaeab2c8bc --- /dev/null +++ b/src/platform/Beken/CHIPMem-Platform.cpp @@ -0,0 +1,141 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Nest Labs, Inc. + * + * 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. + */ + +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file implements heap memory allocation APIs for CHIP. These functions are platform + * specific and might be C Standard Library heap functions re-direction in most of cases. + * + */ + +//#include +#include "matter_pal.h" +#include +#include + +#include +#include +#include +#include + +#if CHIP_CONFIG_MEMORY_MGMT_PLATFORM + +namespace chip { +namespace Platform { + +#define VERIFY_INITIALIZED() VerifyInitialized(__func__) + +static std::atomic_int memoryInitialized{ 0 }; + +static void VerifyInitialized(const char * func) +{ +#if 0 + if (!memoryInitialized) + { + fprintf(stderr, "ABORT: chip::Platform::%s() called before chip::Platform::MemoryInit()\n", func); + abort(); + } +#endif +} + +CHIP_ERROR MemoryAllocatorInit(void * buf, size_t bufSize) +{ +#ifndef NDEBUG + if (memoryInitialized++ > 0) + { + fprintf(stderr, "ABORT: chip::Platform::MemoryInit() called twice.\n"); + abort(); + } +#endif + return CHIP_NO_ERROR; +} + +void MemoryAllocatorShutdown() +{ +#ifndef NDEBUG + if (--memoryInitialized < 0) + { + fprintf(stderr, "ABORT: chip::Platform::MemoryShutdown() called twice.\n"); + abort(); + } +#endif +} + +void * MemoryAlloc(size_t size) +{ + void * ptr; + VERIFY_INITIALIZED(); + ptr = os_zalloc(size); // NULL; + return ptr; +} + +void * MemoryAlloc(size_t size, bool isLongTermAlloc) +{ + void * ptr; + VERIFY_INITIALIZED(); + ptr = os_zalloc(size); + return ptr; +} + +void * MemoryCalloc(size_t num, size_t size) +{ + VERIFY_INITIALIZED(); + void * ptr = os_zalloc(num * size); + return ptr; +} + +void * MemoryRealloc(void * p, size_t size) +{ + VERIFY_INITIALIZED(); + p = os_realloc(p, size); + return p; +} + +void MemoryFree(void * p) +{ + VERIFY_INITIALIZED(); + os_free(p); +} + +bool MemoryInternalCheckPointer(const void * p, size_t min_size) +{ + return (p != nullptr); +} + +} // namespace Platform +} // namespace chip + +#endif // CHIP_CONFIG_MEMORY_MGMT_PLATFORM diff --git a/src/platform/Beken/CHIPPlatformConfig.h b/src/platform/Beken/CHIPPlatformConfig.h new file mode 100644 index 00000000000000..3a8c6a156553a3 --- /dev/null +++ b/src/platform/Beken/CHIPPlatformConfig.h @@ -0,0 +1,116 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific configuration overrides for CHIP on + * Beken platforms. + */ + +#pragma once + +// ==================== General Platform Adaptations ==================== + +#define CHIP_CONFIG_ERROR_TYPE uint32_t +#define CHIP_CONFIG_ERROR_FORMAT PRId32 +#define CHIP_CONFIG_NO_ERROR 0 +#define CHIP_CONFIG_ERROR_MIN 4000000 +#define CHIP_CONFIG_ERROR_MAX 4000999 + +#define ASN1_CONFIG_ERROR_TYPE uint32_t +#define ASN1_CONFIG_NO_ERROR 0 +#define ASN1_CONFIG_ERROR_MIN 5000000 +#define ASN1_CONFIG_ERROR_MAX 5000999 + +#define CHIP_CONFIG_TIME_ENABLE_CLIENT 1 +#define CHIP_CONFIG_TIME_ENABLE_SERVER 0 + +#define ChipDie() abort() + +// ==================== Security Adaptations ==================== + +#define CHIP_CONFIG_USE_OPENSSL_ECC 0 +#define CHIP_CONFIG_USE_MICRO_ECC 0 + +#define CHIP_CONFIG_HASH_IMPLEMENTATION_OPENSSL 0 +#define CHIP_CONFIG_HASH_IMPLEMENTATION_MINCRYPT 1 + +#define CHIP_CONFIG_AES_IMPLEMENTATION_OPENSSL 0 +#define CHIP_CONFIG_AES_IMPLEMENTATION_AESNI 0 +#define CHIP_CONFIG_AES_IMPLEMENTATION_MBEDTLS 0 +#define CHIP_CONFIG_AES_IMPLEMENTATION_PLATFORM 1 + +#define CHIP_CONFIG_RNG_IMPLEMENTATION_OPENSSL 0 +#define CHIP_CONFIG_RNG_IMPLEMENTATION_CHIPDRBG 1 +#define CHIP_CONFIG_RNG_IMPLEMENTATION_PLATFORM 0 + +#define CHIP_CONFIG_ENABLE_PASE_INITIATOR 0 +#define CHIP_CONFIG_ENABLE_PASE_RESPONDER 1 +#define CHIP_CONFIG_ENABLE_CASE_INITIATOR 1 + +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG0 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG1 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG2 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG3 0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG4 1 + +#define CHIP_CONFIG_ENABLE_KEY_EXPORT_INITIATOR 0 + +#define CHIP_CONFIG_ENABLE_PROVISIONING_BUNDLE_SUPPORT 0 + +// ==================== General Configuration Overrides ==================== + +#ifndef CHIP_CONFIG_MAX_PEER_NODES +#define CHIP_CONFIG_MAX_PEER_NODES 16 +#endif // CHIP_CONFIG_MAX_PEER_NODES + +#ifndef CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS +#define CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS 16 +#endif // CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS + +#ifndef CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS +#define CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS 8 +#endif // CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS + +#ifndef CHIP_CONFIG_WRMP_TIMER_DEFAULT_PERIOD +#define CHIP_CONFIG_WRMP_TIMER_DEFAULT_PERIOD 50 +#endif // CHIP_CONFIG_WRMP_TIMER_DEFAULT_PERIOD + +#ifndef CHIP_LOG_FILTERING +#define CHIP_LOG_FILTERING 0 +#endif // CHIP_LOG_FILTERING + +#ifndef CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS +#define CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS 1 +#endif // CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS + +// ==================== Security Configuration Overrides ==================== + +#ifndef CHIP_CONFIG_MAX_APPLICATION_GROUPS +#define CHIP_CONFIG_MAX_APPLICATION_GROUPS 4 +#endif // CHIP_CONFIG_MAX_APPLICATION_GROUPS + +#ifndef CHIP_CONFIG_DEBUG_CERT_VALIDATION +#define CHIP_CONFIG_DEBUG_CERT_VALIDATION 0 +#endif // CHIP_CONFIG_DEBUG_CERT_VALIDATION + +#ifndef CHIP_CONFIG_ENABLE_CASE_RESPONDER +#define CHIP_CONFIG_ENABLE_CASE_RESPONDER 1 +#endif // CHIP_CONFIG_ENABLE_CASE_RESPONDER + +#define CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE 1 diff --git a/src/platform/Beken/ConfigurationManagerImpl.cpp b/src/platform/Beken/ConfigurationManagerImpl.cpp new file mode 100644 index 00000000000000..faa80a172422eb --- /dev/null +++ b/src/platform/Beken/ConfigurationManagerImpl.cpp @@ -0,0 +1,242 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides the implementation of the Device Layer ConfigurationManager object + * for the Beken. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include +#include +#include +#include +#include + +#include "matter_pal.h" + +namespace chip { +namespace DeviceLayer { + +using namespace chip::DeviceLayer::Internal; + +ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance() +{ + static ConfigurationManagerImpl sInstance; + return sInstance; +} + +CHIP_ERROR ConfigurationManagerImpl::Init() +{ + CHIP_ERROR err; + uint32_t rebootCount; + + ChipLogProgress(DeviceLayer, "ConfigurationManagerImpl::Init"); + // Force initialization of NVS namespaces if they doesn't already exist. + err = BekenConfig::EnsureNamespace(BekenConfig::kConfigNamespace_ChipFactory); + SuccessOrExit(err); + err = BekenConfig::EnsureNamespace(BekenConfig::kConfigNamespace_ChipConfig); + SuccessOrExit(err); + err = BekenConfig::EnsureNamespace(BekenConfig::kConfigNamespace_ChipCounters); + SuccessOrExit(err); + + if (BekenConfig::ConfigValueExists(BekenConfig::kCounterKey_RebootCount)) + { + err = GetRebootCount(rebootCount); + SuccessOrExit(err); + + err = StoreRebootCount(rebootCount + 1); + SuccessOrExit(err); + } + else + { + // The first boot after factory reset of the Node. + err = StoreRebootCount(1); + SuccessOrExit(err); + } + + if (!BekenConfig::ConfigValueExists(BekenConfig::kCounterKey_TotalOperationalHours)) + { + err = StoreTotalOperationalHours(0); + SuccessOrExit(err); + } + + if (!BekenConfig::ConfigValueExists(BekenConfig::kCounterKey_BootReason)) + { + err = StoreBootReason(to_underlying(BootReasonType::kUnspecified)); + SuccessOrExit(err); + } + + // Initialize the generic implementation base class. + err = Internal::GenericConfigurationManagerImpl::Init(); + SuccessOrExit(err); + + err = CHIP_NO_ERROR; +exit: + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount) +{ + return ReadConfigValue(BekenConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount) +{ + return WriteConfigValue(BekenConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + return ReadConfigValue(BekenConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours) +{ + return WriteConfigValue(BekenConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +CHIP_ERROR ConfigurationManagerImpl::GetBootReason(uint32_t & bootReason) +{ + return ReadConfigValue(BekenConfig::kCounterKey_BootReason, bootReason); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreBootReason(uint32_t bootReason) +{ + return WriteConfigValue(BekenConfig::kCounterKey_BootReason, bootReason); +} + +CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) +{ + bk_wifi_sta_get_mac(buf); + return CHIP_NO_ERROR; +} + +bool ConfigurationManagerImpl::CanFactoryReset() +{ + // TODO: query the application to determine if factory reset is allowed. + return true; +} + +void ConfigurationManagerImpl::InitiateFactoryReset() +{ + PlatformMgr().ScheduleWork(DoFactoryReset); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) +{ + BekenConfig::Key configKey{ BekenConfig::kConfigNamespace_ChipCounters, key }; + + CHIP_ERROR err = ReadConfigValue(configKey, value); + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) +{ + BekenConfig::Key configKey{ BekenConfig::kConfigNamespace_ChipCounters, key }; + return WriteConfigValue(configKey, value); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, bool & val) +{ + return BekenConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint32_t & val) +{ + return BekenConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint64_t & val) +{ + return BekenConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) +{ + return BekenConfig::ReadConfigValueStr(key, buf, bufSize, outLen); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + return BekenConfig::ReadConfigValueBin(key, buf, bufSize, outLen); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, bool val) +{ + return BekenConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint32_t val) +{ + return BekenConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint64_t val) +{ + return BekenConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str) +{ + return BekenConfig::WriteConfigValueStr(key, str); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str, size_t strLen) +{ + return BekenConfig::WriteConfigValueStr(key, str, strLen); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) +{ + return BekenConfig::WriteConfigValueBin(key, data, dataLen); +} + +void ConfigurationManagerImpl::RunConfigUnitTest(void) +{ + BekenConfig::RunConfigUnitTest(); +} + +void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) +{ + CHIP_ERROR err; + + ChipLogProgress(DeviceLayer, "Performing factory reset"); + + // Erase all values in the chip-config NVS namespace. + bk_erase_all(BK_PARTITION_MATTER_FLASH); + + // Restart the system. + ChipLogProgress(DeviceLayer, "System restarting"); + bk_reboot(); +} + +ConfigurationManager & ConfigurationMgrImpl() +{ + return ConfigurationManagerImpl::GetDefaultInstance(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/ConfigurationManagerImpl.h b/src/platform/Beken/ConfigurationManagerImpl.h new file mode 100644 index 00000000000000..969e2d4f7d3452 --- /dev/null +++ b/src/platform/Beken/ConfigurationManagerImpl.h @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the ConfigurationManager object + * for the Beken platform. + */ +#pragma once + +#include +#include +#include + +namespace chip { +namespace DeviceLayer { +/** + * Concrete implementation of the ConfigurationManager singleton object for the Beken platform. + */ +class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImpl +{ +public: + // This returns an instance of this class. + static ConfigurationManagerImpl & GetDefaultInstance(); + +private: + // ===== Members that implement the ConfigurationManager public interface. + + CHIP_ERROR Init(void); + CHIP_ERROR GetPrimaryWiFiMACAddress(uint8_t * buf); + bool CanFactoryReset(void); + void InitiateFactoryReset(void); + CHIP_ERROR ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value); + CHIP_ERROR WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value); + CHIP_ERROR GetRebootCount(uint32_t & rebootCount); + CHIP_ERROR StoreRebootCount(uint32_t rebootCount); + CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours); + CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours); + CHIP_ERROR GetBootReason(uint32_t & bootReason); + CHIP_ERROR StoreBootReason(uint32_t bootReason); + + // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>. + + // ===== Members that implement the GenericConfigurationManagerImpl protected interface. + CHIP_ERROR ReadConfigValue(Key key, bool & val); + CHIP_ERROR ReadConfigValue(Key key, uint32_t & val); + CHIP_ERROR ReadConfigValue(Key key, uint64_t & val); + CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen); + CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen); + CHIP_ERROR WriteConfigValue(Key key, bool val); + CHIP_ERROR WriteConfigValue(Key key, uint32_t val); + CHIP_ERROR WriteConfigValue(Key key, uint64_t val); + CHIP_ERROR WriteConfigValueStr(Key key, const char * str); + CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen); + CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen); + void RunConfigUnitTest(void); + + // ===== Private members reserved for use by this class only. + + static void DoFactoryReset(intptr_t arg); +}; + +/** + * Returns the platform-specific implementation of the ConfigurationManager object. + * + * Applications can use this to gain access to features of the ConfigurationManager + * that are specific to the selected platform. + */ +ConfigurationManager & ConfigurationMgrImpl(); + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/ConnectivityManagerImpl.cpp b/src/platform/Beken/ConnectivityManagerImpl.cpp new file mode 100644 index 00000000000000..f3dab2d3eea633 --- /dev/null +++ b/src/platform/Beken/ConnectivityManagerImpl.cpp @@ -0,0 +1,649 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include + +#include + +#if INET_CONFIG_ENABLE_TCP_ENDPOINT +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include "NetworkCommissioningDriver.h" + +#include "matter_pal.h" +#include + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::TLV; +using namespace ::chip::DeviceLayer::Internal; + +namespace chip { +namespace DeviceLayer { + +ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; +NetworkCommissioning::BekenWiFiDriver::WiFiNetwork mWifiNetconf; + +// ==================== ConnectivityManager Platform Internal Methods ==================== + +CHIP_ERROR ConnectivityManagerImpl::_Init() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + mLastStationConnectFailTime = System::Clock::kZero; + mLastAPDemandTime = System::Clock::kZero; + mWiFiStationMode = kWiFiStationMode_Disabled; + mWiFiStationState = kWiFiStationState_NotConnected; + mWiFiAPMode = kWiFiAPMode_Disabled; + mWiFiAPState = kWiFiAPState_NotActive; + mWiFiStationReconnectInterval = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL); + mWiFiAPIdleTimeout = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT); + mFlags.SetRaw(0); + + memset(&mWifiNetconf, 0x0, sizeof(mWifiNetconf)); + // If there is no persistent station provision... + if (!IsWiFiStationProvisioned()) + { + // If the code has been compiled with a default WiFi station provision, configure that now. +#if !defined(CONFIG_DEFAULT_WIFI_SSID) + printf("%s %d pls define CONFIG_DEFAULT_WIFI_SSID\r\n", __func__, __LINE__); +#else + if (CONFIG_DEFAULT_WIFI_SSID[0] != 0) + { + ChipLogProgress(DeviceLayer, "Setting default WiFi station configuration (SSID: %s)", CONFIG_DEFAULT_WIFI_SSID); + + // Set a default station configuration. + rtw_wifi_setting_t wifiConfig; + + // Set the wifi configuration + memset(&wifiConfig, 0, sizeof(wifiConfig)); + memcpy(wifiConfig.ssid, CONFIG_DEFAULT_WIFI_SSID, strlen(CONFIG_DEFAULT_WIFI_SSID) + 1); + memcpy(wifiConfig.password, CONFIG_DEFAULT_WIFI_PASSWORD, strlen(CONFIG_DEFAULT_WIFI_PASSWORD) + 1); + wifiConfig.mode = RTW_MODE_STA; + + // Configure the WiFi interface. + int err = CHIP_SetWiFiConfig(&wifiConfig); + if (err != 0) + { + ChipLogError(DeviceLayer, "_Init _SetWiFiConfig() failed: %d", err); + } + + // Enable WiFi station mode. + ReturnErrorOnFailure(SetWiFiStationMode(kWiFiStationMode_Enabled)); + } + + // Otherwise, ensure WiFi station mode is disabled. + else + { + ReturnErrorOnFailure(SetWiFiStationMode(kWiFiStationMode_Disabled)); + } +#endif + } + + // Force AP mode off for now. + + // Queue work items to bootstrap the AP and station state machines once the Chip event loop is running. + ReturnErrorOnFailure(DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL)); + ReturnErrorOnFailure(DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL)); + +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI + + return CHIP_NO_ERROR; +} + +void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) +{ + // Forward the event to the generic base classes as needed. +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + GenericConnectivityManagerImpl_Thread::_OnPlatformEvent(event); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + if (event->Type == DeviceEventType::kRtkWiFiStationConnectedEvent) + { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent WIFI_EVENT_STA_CONNECTED"); + if (mWiFiStationState == kWiFiStationState_Connecting) + { + NetworkCommissioning::BekenWiFiDriver::GetInstance().OnConnectWiFiNetwork(); + ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded); + } + DriveStationState(); + } +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode(void) +{ + // Enabled when platform instance initilazed + return kWiFiStationMode_Enabled; +} + +bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void) +{ + return GetWiFiStationMode() == kWiFiStationMode_Enabled; +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (mWiFiStationMode == kWiFiStationMode_Disabled && val == kWiFiStationMode_Enabled) + { + BK_LOG_ON_ERR(bk_event_register_cb(EVENT_MOD_WIFI, EVENT_ID_ALL, ConnectivityManagerImpl().wlan_event_cb, NULL)); + BK_LOG_ON_ERR(bk_event_register_cb(EVENT_MOD_NETIF, EVENT_ID_ALL, ConnectivityManagerImpl().netif_event_cb, NULL)); + ChangeWiFiStationState(kWiFiStationState_Connecting); + } + + if (val != kWiFiStationMode_ApplicationControlled) + { + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); + } + + if (mWiFiStationMode != val) + { + ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode), + WiFiStationModeToStr(val)); + } + + mWiFiStationMode = val; + +exit: + return err; +} + +bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void) +{ + if (mWifiNetconf.ssidLen == 0) + NetworkCommissioning::BekenWiFiDriver::GetInstance().GetSavedNetWorkConfig(&mWifiNetconf); + ChipLogError(DeviceLayer, "wifi ssid:%s\r\n", mWifiNetconf.ssid); + return (mWifiNetconf.ssidLen != 0) ? true : false; +} + +void ConnectivityManagerImpl::_ClearWiFiStationProvision(void) +{ + // TBD +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (mWiFiAPMode != val) + { + ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val)); + } + + mWiFiAPMode = val; + + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + +exit: + return err; +} + +void ConnectivityManagerImpl::_DemandStartWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + mLastAPDemandTime = System::SystemClock().GetMonotonicTimestamp(); + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + } +} + +void ConnectivityManagerImpl::_StopOnDemandWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + mLastAPDemandTime = System::Clock::kZero; + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + } +} + +void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + if (mWiFiAPState == kWiFiAPState_Activating || mWiFiAPState == kWiFiAPState_Active) + { + mLastAPDemandTime = System::SystemClock().GetMonotonicTimestamp(); + } + } +} + +void ConnectivityManagerImpl::_SetWiFiAPIdleTimeout(System::Clock::Timeout val) +{ + mWiFiAPIdleTimeout = val; + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); +} + +CHIP_ERROR ConnectivityManagerImpl::_GetAndLogWifiStatsCounters(void) +{ + return CHIP_NO_ERROR; +} + +void ConnectivityManagerImpl::_OnWiFiScanDone() +{ + // Schedule a call to DriveStationState method in case a station connect attempt was + // deferred because the scan was in progress. + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); +} + +void ConnectivityManagerImpl::_OnWiFiStationProvisionChange() +{ + // Schedule a call to the DriveStationState method to adjust the station state as needed. + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); +} + +// ==================== ConnectivityManager Private Methods ==================== +void ConnectivityManagerImpl::WiFiStationConnectedHandler() +{ + ChipDeviceEvent event; + memset(&event, 0, sizeof(event)); + event.Type = DeviceEventType::kRtkWiFiStationConnectedEvent; + PlatformMgr().PostEventOrDie(&event); +} + +static bool stationConnected = false; + +int ConnectivityManagerImpl::netif_event_cb(void * arg, event_module_t event_module, int event_id, void * event_data) +{ + ssid_key_save_t wpa_save = { { 0 } }; + switch (event_id) + { + case EVENT_NETIF_GOT_IP4: + stationConnected = true; + WiFiStationConnectedHandler(); + ChipLogProgress(DeviceLayer, "netif_event_cb EVENT_NETIF_GOT_IP4"); + break; + default: + ChipLogProgress(DeviceLayer, "unSupported netif status:%d", event_id); + break; + } + + return BK_OK; +} + +int ConnectivityManagerImpl::wlan_event_cb(void * arg, event_module_t event_module, int event_id, void * event_data) +{ + switch (event_id) + { + case EVENT_WIFI_STA_CONNECTED: + ChipLogProgress(DeviceLayer, "wlan_event_cb EVENT_WIFI_STA_CONNECTED"); + break; + case EVENT_WIFI_STA_DISCONNECTED: + stationConnected = false; + ChipLogProgress(DeviceLayer, "wlan_event_cb EVENT_WIFI_STA_DISCONNECTED"); + wifi_event_sta_disconnected_t * sta_disconnected; + sta_disconnected = (wifi_event_sta_disconnected_t *) event_data; + ChipDeviceEvent myevent; + myevent.Platform.BKSystemEvent.Data.WiFiStaDisconnected = sta_disconnected->disconnect_reason; + NetworkCommissioning::BekenWiFiDriver::GetInstance().SetLastDisconnectReason(&myevent); + break; + default: + ChipLogProgress(DeviceLayer, "unSupported wifi status:%d", event_id); + break; + } + return BK_OK; +} + +void ConnectivityManagerImpl::DriveStationState() +{ + mWiFiStationMode = GetWiFiStationMode(); + ChipLogProgress(DeviceLayer, "wifi station state:%d, mWiFiStationState:%d", stationConnected, mWiFiStationState); + // If the station interface is currently connected ... + if (stationConnected) + { + // Advance the station state to Connected if it was previously NotConnected or + // a previously initiated connect attempt succeeded. + if (mWiFiStationState == kWiFiStationState_NotConnected || mWiFiStationState == kWiFiStationState_Connecting_Succeeded) + { + ChangeWiFiStationState(kWiFiStationState_Connected); + ChipLogProgress(DeviceLayer, "WiFi station interface connected"); + mLastStationConnectFailTime = System::Clock::kZero; + OnStationConnected(); + IpConnectedEventNotify(); + } + } + + // Otherwise the station interface is NOT connected to an AP, so... + else + { + System::Clock::Timestamp now = System::SystemClock().GetMonotonicTimestamp(); + + // Advance the station state to NotConnected if it was previously Connected or Disconnecting, + // or if a previous initiated connect attempt failed. + if (mWiFiStationState == kWiFiStationState_Connected || mWiFiStationState == kWiFiStationState_Disconnecting || + mWiFiStationState == kWiFiStationState_Connecting_Failed) + { + WiFiStationState prevState = mWiFiStationState; + ChangeWiFiStationState(kWiFiStationState_NotConnected); + if (prevState != kWiFiStationState_Connecting_Failed) + { + ChipLogProgress(DeviceLayer, "WiFi station interface disconnected"); + mLastStationConnectFailTime = System::Clock::kZero; + OnStationDisconnected(); + } + else + { + mLastStationConnectFailTime = now; + } + } + // If the WiFi station interface is now enabled and provisioned (and by implication, + // not presently under application control), AND the system is not in the process of + // scanning, then... + ChipLogProgress(DeviceLayer, "mWiFiStationMode:%d, IsWiFiStationProvisioned:%d", mWiFiStationMode, + IsWiFiStationProvisioned()); + if (mWiFiStationMode == kWiFiStationMode_Enabled && IsWiFiStationProvisioned() && + mWiFiStationState != kWiFiStationState_Connecting) + { + // Initiate a connection to the AP if we haven't done so before, or if enough + // time has passed since the last attempt. + if (mLastStationConnectFailTime == System::Clock::kZero || + now >= mLastStationConnectFailTime + mWiFiStationReconnectInterval) + { + ChipLogProgress(DeviceLayer, "try to connect wifi"); + wifi_sta_config_t sta_config; + + memset(&sta_config, 0x0, sizeof(sta_config)); + sta_config.security = WIFI_SECURITY_AUTO; // can't use WIFI_DEFAULT_STA_CONFIG because of C99 designator error + strncpy(sta_config.ssid, mWifiNetconf.ssid, mWifiNetconf.ssidLen); + strncpy(sta_config.password, mWifiNetconf.credentials, mWifiNetconf.credentialsLen); + BK_LOG_ON_ERR(bk_wifi_sta_set_config(&sta_config)); + BK_LOG_ON_ERR(bk_wifi_sta_start()); + BK_LOG_ON_ERR(bk_event_register_cb(EVENT_MOD_WIFI, EVENT_ID_ALL, ConnectivityManagerImpl().wlan_event_cb, NULL)); + BK_LOG_ON_ERR(bk_event_register_cb(EVENT_MOD_NETIF, EVENT_ID_ALL, ConnectivityManagerImpl().netif_event_cb, NULL)); + BK_LOG_ON_ERR(bk_wifi_sta_connect()); + ChangeWiFiStationState(kWiFiStationState_Connecting); + } + + // Otherwise arrange another connection attempt at a suitable point in the future. + else + { + System::Clock::Timeout timeToNextConnect = (mLastStationConnectFailTime + mWiFiStationReconnectInterval) - now; + + ChipLogProgress(DeviceLayer, "Next WiFi station reconnect in %" PRIu32 " ms", + System::Clock::Milliseconds32(timeToNextConnect).count()); + + ReturnOnFailure(DeviceLayer::SystemLayer().StartTimer(timeToNextConnect, DriveStationState, nullptr)); + } + } + } + ChipLogProgress(DeviceLayer, "Done driving station state, nothing else to do..."); + // Kick-off any pending network scan that might have been deferred due to the activity + // of the WiFi station. +} + +void ConnectivityManagerImpl::OnStationConnected() +{ + // Alert other components of the new state. + ChipDeviceEvent event; + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Established; + PlatformMgr().PostEventOrDie(&event); + + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::OnStationDisconnected() +{ + // Alert other components of the new state. + ChipDeviceEvent event; + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Lost; + PlatformMgr().PostEventOrDie(&event); + + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::ChangeWiFiStationState(WiFiStationState newState) +{ + if (mWiFiStationState != newState) + { + ChipLogProgress(DeviceLayer, "WiFi station state change: %s -> %s", WiFiStationStateToStr(mWiFiStationState), + WiFiStationStateToStr(newState)); + mWiFiStationState = newState; + SystemLayer().ScheduleLambda([]() { NetworkCommissioning::BekenWiFiDriver::GetInstance().OnNetworkStatusChange(); }); + } +} + +void ConnectivityManagerImpl::DriveStationState(::chip::System::Layer * aLayer, void * aAppState) +{ + sInstance.DriveStationState(); +} + +void ConnectivityManagerImpl::DriveAPState() +{ + ChipLogProgress(DeviceLayer, "WiFi ConnectivityManagerImpl::DriveAPState, do nothing!"); + CHIP_ERROR err = CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() +{ + return CHIP_NO_ERROR; +} + +void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState) +{ + if (mWiFiAPState != newState) + { + ChipLogProgress(DeviceLayer, "WiFi AP state change: %s -> %s", WiFiAPStateToStr(mWiFiAPState), WiFiAPStateToStr(newState)); + mWiFiAPState = newState; + } +} + +void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState) +{ + sInstance.DriveAPState(); +} + +void ConnectivityManagerImpl::UpdateInternetConnectivityState(void) +{ + bool haveIPv4Conn = false; + bool haveIPv6Conn = false; + const bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity); + const bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity); + IPAddress addr; + + // If the WiFi station is currently in the connected state... + if (mWiFiStationState == kWiFiStationState_Connected) + { + // Get the LwIP netif for the WiFi station interface. + struct netif * netif = netif_list; + + // If the WiFi station interface is up... + if (netif != NULL && netif_is_up(netif) && netif_is_link_up(netif)) + { + // Check if a DNS server is currently configured. If so... + ip_addr_t dnsServerAddr = *dns_getserver(0); + if (!ip_addr_isany_val(dnsServerAddr)) + { + // If the station interface has been assigned an IPv4 address, and has + // an IPv4 gateway, then presume that the device has IPv4 Internet + // connectivity. + if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) && !ip4_addr_isany_val(*netif_ip4_gw(netif))) + { + haveIPv4Conn = true; + // char addrStr[INET_ADDRSTRLEN]; + // ip4addr_ntoa_r((const ip4_addr_t *) LwIP_GetIP(&xnetif[0]), addrStr, sizeof(addrStr)); + // IPAddress::FromString(addrStr, addr); + } + + // Search among the IPv6 addresses assigned to the interface for a Global Unicast + // address (2000::/3) that is in the valid state. If such an address is found... + for (uint8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) + { + if (ip6_addr_isglobal(netif_ip6_addr(netif, i)) && ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) + { + // Determine if there is a default IPv6 router that is currently reachable + // via the station interface. If so, presume for now that the device has + // IPv6 connectivity. + struct netif * found_if = nd6_find_route(IP6_ADDR_ANY6); + if (found_if && netif->num == found_if->num) + { + haveIPv6Conn = true; + } + } + } + } + } + } + + // If the internet connectivity state has changed... + if (haveIPv4Conn != hadIPv4Conn || haveIPv6Conn != hadIPv6Conn) + { + // Update the current state. + mFlags.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity, haveIPv4Conn) + .Set(ConnectivityFlags::kHaveIPv6InternetConnectivity, haveIPv6Conn); + + // Alert other components of the state change. + ChipDeviceEvent event; + event.Type = DeviceEventType::kInternetConnectivityChange; + event.InternetConnectivityChange.IPv4 = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn); + event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn); + // addr.ToString(event.InternetConnectivityChange.address); + PlatformMgr().PostEventOrDie(&event); + + if (haveIPv4Conn != hadIPv4Conn) + { + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST"); + } + + if (haveIPv6Conn != hadIPv6Conn) + { + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST"); + } + } +} + +void ConnectivityManagerImpl::OnStationIPv4AddressAvailable(void) +{ +#if 0 + uint8_t * ip = LwIP_GetIP(&xnetif[0]); + uint8_t * gw = LwIP_GetGW(&xnetif[0]); + uint8_t * msk = LwIP_GetMASK(&xnetif[0]); +#if CHIP_PROGRESS_LOGGING + { + ChipLogProgress(DeviceLayer, "\n\r\tIP => %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + ChipLogProgress(DeviceLayer, "\n\r\tGW => %d.%d.%d.%d\n\r", gw[0], gw[1], gw[2], gw[3]); + ChipLogProgress(DeviceLayer, "\n\r\tmsk => %d.%d.%d.%d\n\r", msk[0], msk[1], msk[2], msk[3]); + } +#endif // CHIP_PROGRESS_LOGGING +#endif + + UpdateInternetConnectivityState(); + ChipLogProgress(DeviceLayer, "IPv4 address available on WiFi station interface"); + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Assigned; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::OnStationIPv4AddressLost(void) +{ + ChipLogProgress(DeviceLayer, "IPv4 address lost on WiFi station interface"); + + UpdateInternetConnectivityState(); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Lost; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::OnIPv6AddressAvailable(void) +{ +#if 0 +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 +#if LWIP_IPV6 + uint8_t * ipv6_0 = LwIP_GetIPv6_linklocal(&xnetif[0]); + uint8_t * ipv6_1 = LwIP_GetIPv6_global(&xnetif[0]); +#endif +#endif +#if CHIP_PROGRESS_LOGGING + { +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 +#if LWIP_IPV6 + ChipLogProgress(DeviceLayer, + "\n\r\tLink-local IPV6 => %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ipv6_0[0], ipv6_0[1], ipv6_0[2], ipv6_0[3], ipv6_0[4], ipv6_0[5], ipv6_0[6], ipv6_0[7], ipv6_0[8], + ipv6_0[9], ipv6_0[10], ipv6_0[11], ipv6_0[12], ipv6_0[13], ipv6_0[14], ipv6_0[15]); + ChipLogProgress(DeviceLayer, + "\n\r\tIPV6 => %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ipv6_1[0], ipv6_1[1], ipv6_1[2], ipv6_1[3], ipv6_1[4], ipv6_1[5], ipv6_1[6], ipv6_1[7], ipv6_1[8], + ipv6_1[9], ipv6_1[10], ipv6_1[11], ipv6_1[12], ipv6_1[13], ipv6_1[14], ipv6_1[15]); +#endif +#endif + } +#endif // CHIP_PROGRESS_LOGGING +#endif + + UpdateInternetConnectivityState(); + ChipLogProgress(DeviceLayer, "IPv6 address available on WiFi station interface"); + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV6_Assigned; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::IpConnectedEventNotify() +{ + const bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity); + const bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity); + + if (hadIPv4Conn) + { + sInstance.OnStationIPv4AddressAvailable(); + } + if (hadIPv6Conn) + { + sInstance.OnIPv6AddressAvailable(); + } +} + +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/ConnectivityManagerImpl.h b/src/platform/Beken/ConnectivityManagerImpl.h new file mode 100644 index 00000000000000..686ba1a988d790 --- /dev/null +++ b/src/platform/Beken/ConnectivityManagerImpl.h @@ -0,0 +1,224 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include + +#if INET_CONFIG_ENABLE_TCP_ENDPOINT +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +#include +#else +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#else +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#else +#include +#endif + +#include + +#include + +namespace chip { + +namespace Inet { +class IPAddress; +} // namespace Inet + +namespace DeviceLayer { + +class PlatformManagerImpl; + +class ConnectivityManagerImpl final : public ConnectivityManager, + public Internal::GenericConnectivityManagerImpl, + public Internal::GenericConnectivityManagerImpl_UDP, +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + public Internal::GenericConnectivityManagerImpl_TCP, +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + public Internal::GenericConnectivityManagerImpl_WiFi, +#else + public Internal::GenericConnectivityManagerImpl_NoWiFi, +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + public Internal::GenericConnectivityManagerImpl_BLE, +#else + public Internal::GenericConnectivityManagerImpl_NoBLE, +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + public Internal::GenericConnectivityManagerImpl_Thread +#else + public Internal::GenericConnectivityManagerImpl_NoThread +#endif +{ + // Allow the ConnectivityManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConnectivityManager; + +private: + CHIP_ERROR _Init(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + using Flags = GenericConnectivityManagerImpl_WiFi::ConnectivityFlags; + // ===== Members that implement the ConnectivityManager abstract interface. + + WiFiStationMode _GetWiFiStationMode(void); + CHIP_ERROR _SetWiFiStationMode(WiFiStationMode val); + bool _IsWiFiStationEnabled(void); + bool _IsWiFiStationApplicationControlled(void); + bool _IsWiFiStationConnected(void); + System::Clock::Timeout _GetWiFiStationReconnectInterval(void); + CHIP_ERROR _SetWiFiStationReconnectInterval(System::Clock::Timeout val); + bool _IsWiFiStationProvisioned(void); + void _ClearWiFiStationProvision(void); + WiFiAPMode _GetWiFiAPMode(void); + CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val); + bool _IsWiFiAPActive(void); + bool _IsWiFiAPApplicationControlled(void); + void _DemandStartWiFiAP(void); + void _StopOnDemandWiFiAP(void); + void _MaintainOnDemandWiFiAP(void); + System::Clock::Timeout _GetWiFiAPIdleTimeout(void); + void _SetWiFiAPIdleTimeout(System::Clock::Timeout val); + CHIP_ERROR _GetAndLogWifiStatsCounters(void); + bool _CanStartWiFiScan(); + void _OnWiFiScanDone(); + void _OnWiFiStationProvisionChange(); + + // ===== Private members reserved for use by this class only. + + System::Clock::Timestamp mLastStationConnectFailTime; + System::Clock::Timestamp mLastAPDemandTime; + WiFiStationMode mWiFiStationMode; + WiFiStationState mWiFiStationState; + WiFiAPMode mWiFiAPMode; + WiFiAPState mWiFiAPState; + System::Clock::Timeout mWiFiStationReconnectInterval; + System::Clock::Timeout mWiFiAPIdleTimeout; + BitFlags mFlags; + + void DriveStationState(void); + void OnStationConnected(void); + void OnStationDisconnected(void); + void ChangeWiFiStationState(WiFiStationState newState); + static void DriveStationState(::chip::System::Layer * aLayer, void * aAppState); + + void DriveAPState(void); + CHIP_ERROR ConfigureWiFiAP(void); + void ChangeWiFiAPState(WiFiAPState newState); + static void DriveAPState(::chip::System::Layer * aLayer, void * aAppState); + + void UpdateInternetConnectivityState(void); + void OnStationIPv4AddressAvailable(void); + void OnStationIPv4AddressLost(void); + void OnIPv6AddressAvailable(void); + +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI + + // ===== Members for internal use by the following friends. + + friend ConnectivityManager & ConnectivityMgr(void); + friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); + + static ConnectivityManagerImpl sInstance; + static void WiFiStationConnectedHandler(); + static int wlan_event_cb(void * arg, event_module_t event_module, int event_id, void * event_data); + static int netif_event_cb(void * arg, event_module_t event_module, int event_id, void * event_data); + void IpConnectedEventNotify(void); +}; + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +inline bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled(void) +{ + return mWiFiStationMode == kWiFiStationMode_ApplicationControlled; +} + +inline bool ConnectivityManagerImpl::_IsWiFiStationConnected(void) +{ + return mWiFiStationState == kWiFiStationState_Connected; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPApplicationControlled(void) +{ + return mWiFiAPMode == kWiFiAPMode_ApplicationControlled; +} + +inline System::Clock::Timeout ConnectivityManagerImpl::_GetWiFiStationReconnectInterval(void) +{ + return mWiFiStationReconnectInterval; +} + +inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode(void) +{ + return mWiFiAPMode; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPActive(void) +{ + return mWiFiAPState == kWiFiAPState_Active; +} + +inline System::Clock::Timeout ConnectivityManagerImpl::_GetWiFiAPIdleTimeout(void) +{ + return mWiFiAPIdleTimeout; +} + +inline bool ConnectivityManagerImpl::_CanStartWiFiScan() +{ + return mWiFiStationState != kWiFiStationState_Connecting; +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI + +/** + * Returns the public interface of the ConnectivityManager singleton object. + * + * Chip applications should use this to access features of the ConnectivityManager object + * that are common to all platforms. + */ +inline ConnectivityManager & ConnectivityMgr(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ConnectivityManager singleton object. + * + * Chip applications can use this to gain access to features of the ConnectivityManager + * that are specific to the Beken platform. + */ +inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/DeviceInfoProviderImpl.cpp b/src/platform/Beken/DeviceInfoProviderImpl.cpp new file mode 100755 index 00000000000000..3b0b5aff2bad84 --- /dev/null +++ b/src/platform/Beken/DeviceInfoProviderImpl.cpp @@ -0,0 +1,364 @@ +/* + * + * Copyright (c) 2022 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 +#include +#include +#include +#include +#include + +#include +#include + +namespace chip { +namespace DeviceLayer { + +namespace { +constexpr TLV::Tag kLabelNameTag = TLV::ContextTag(0); +constexpr TLV::Tag kLabelValueTag = TLV::ContextTag(1); +} // anonymous namespace + +DeviceInfoProviderImpl & DeviceInfoProviderImpl::GetDefaultInstance() +{ + static DeviceInfoProviderImpl sInstance; + return sInstance; +} + +DeviceInfoProvider::FixedLabelIterator * DeviceInfoProviderImpl::IterateFixedLabel(EndpointId endpoint) +{ + return new FixedLabelIteratorImpl(endpoint); +} + +DeviceInfoProviderImpl::FixedLabelIteratorImpl::FixedLabelIteratorImpl(EndpointId endpoint) : mEndpoint(endpoint) +{ + mIndex = 0; +} + +size_t DeviceInfoProviderImpl::FixedLabelIteratorImpl::Count() +{ + // In Beken Simulation, return the size of the hardcoded labelList on all endpoints. + return 4; +} + +bool DeviceInfoProviderImpl::FixedLabelIteratorImpl::Next(FixedLabelType & output) +{ + bool retval = true; + + // In Beken Simulation, use the following hardcoded labelList on all endpoints. + CHIP_ERROR err = CHIP_NO_ERROR; + + const char * labelPtr = nullptr; + const char * valuePtr = nullptr; + + VerifyOrReturnError(mIndex < 4, false); + + ChipLogProgress(DeviceLayer, "Get the fixed label with index:%d at endpoint:%d", mIndex, mEndpoint); + + switch (mIndex) + { + case 0: + labelPtr = "room"; + valuePtr = "bedroom 2"; + break; + case 1: + labelPtr = "orientation"; + valuePtr = "North"; + break; + case 2: + labelPtr = "floor"; + valuePtr = "2"; + break; + case 3: + labelPtr = "direction"; + valuePtr = "up"; + break; + default: + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + break; + } + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(std::strlen(labelPtr) <= kMaxLabelNameLength, false); + VerifyOrReturnError(std::strlen(valuePtr) <= kMaxLabelValueLength, false); + + Platform::CopyString(mFixedLabelNameBuf, kMaxLabelNameLength + 1, labelPtr); + Platform::CopyString(mFixedLabelValueBuf, kMaxLabelValueLength + 1, valuePtr); + + output.label = CharSpan::fromCharString(mFixedLabelNameBuf); + output.value = CharSpan::fromCharString(mFixedLabelValueBuf); + + mIndex++; + + retval = true; + } + else + { + retval = false; + } + + return retval; +} + +CHIP_ERROR DeviceInfoProviderImpl::SetUserLabelLength(EndpointId endpoint, size_t val) +{ + DefaultStorageKeyAllocator keyAlloc; + + return mStorage->SyncSetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, static_cast(sizeof(val))); +} + +CHIP_ERROR DeviceInfoProviderImpl::GetUserLabelLength(EndpointId endpoint, size_t & val) +{ + DefaultStorageKeyAllocator keyAlloc; + uint16_t len = static_cast(sizeof(val)); + + return mStorage->SyncGetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, len); +} + +CHIP_ERROR DeviceInfoProviderImpl::SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel) +{ + DefaultStorageKeyAllocator keyAlloc; + uint8_t buf[UserLabelTLVMaxSize()]; + TLV::TLVWriter writer; + writer.Init(buf); + + TLV::TLVType outerType; + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType)); + ReturnErrorOnFailure(writer.PutString(kLabelNameTag, userLabel.label)); + ReturnErrorOnFailure(writer.PutString(kLabelValueTag, userLabel.value)); + ReturnErrorOnFailure(writer.EndContainer(outerType)); + + return mStorage->SyncSetKeyValue(keyAlloc.UserLabelIndexKey(endpoint, index), buf, + static_cast(writer.GetLengthWritten())); +} + +DeviceInfoProvider::UserLabelIterator * DeviceInfoProviderImpl::IterateUserLabel(EndpointId endpoint) +{ + return new UserLabelIteratorImpl(*this, endpoint); +} + +DeviceInfoProviderImpl::UserLabelIteratorImpl::UserLabelIteratorImpl(DeviceInfoProviderImpl & provider, EndpointId endpoint) : + mProvider(provider), mEndpoint(endpoint) +{ + size_t total = 0; + + ReturnOnFailure(mProvider.GetUserLabelLength(mEndpoint, total)); + mTotal = total; + mIndex = 0; +} + +bool DeviceInfoProviderImpl::UserLabelIteratorImpl::Next(UserLabelType & output) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrReturnError(mIndex < mTotal, false); + + DefaultStorageKeyAllocator keyAlloc; + uint8_t buf[UserLabelTLVMaxSize()]; + uint16_t len = static_cast(UserLabelTLVMaxSize()); + + err = mProvider.mStorage->SyncGetKeyValue(keyAlloc.UserLabelIndexKey(mEndpoint, mIndex), buf, len); + VerifyOrReturnError(err == CHIP_NO_ERROR, false); + + TLV::ContiguousBufferTLVReader reader; + reader.Init(buf); + err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()); + VerifyOrReturnError(err == CHIP_NO_ERROR, false); + + TLV::TLVType containerType; + VerifyOrReturnError(reader.EnterContainer(containerType) == CHIP_NO_ERROR, false); + + chip::CharSpan label; + chip::CharSpan value; + + VerifyOrReturnError(reader.Next(kLabelNameTag) == CHIP_NO_ERROR, false); + VerifyOrReturnError(reader.Get(label) == CHIP_NO_ERROR, false); + + VerifyOrReturnError(reader.Next(kLabelValueTag) == CHIP_NO_ERROR, false); + VerifyOrReturnError(reader.Get(value) == CHIP_NO_ERROR, false); + + VerifyOrReturnError(reader.VerifyEndOfContainer() == CHIP_NO_ERROR, false); + VerifyOrReturnError(reader.ExitContainer(containerType) == CHIP_NO_ERROR, false); + + Platform::CopyString(mUserLabelNameBuf, label); + Platform::CopyString(mUserLabelValueBuf, value); + + output.label = CharSpan::fromCharString(mUserLabelNameBuf); + output.value = CharSpan::fromCharString(mUserLabelValueBuf); + + mIndex++; + + return true; +} + +DeviceInfoProvider::SupportedLocalesIterator * DeviceInfoProviderImpl::IterateSupportedLocales() +{ + return new SupportedLocalesIteratorImpl(); +} + +size_t DeviceInfoProviderImpl::SupportedLocalesIteratorImpl::Count() +{ + // In Beken Simulation, return the size of the hardcoded list of Strings that are valid values for the ActiveLocale. + // {("en-US"), ("de-DE"), ("fr-FR"), ("en-GB"), ("es-ES"), ("zh-CN"), ("it-IT"), ("ja-JP")} + + return 8; +} + +bool DeviceInfoProviderImpl::SupportedLocalesIteratorImpl::Next(CharSpan & output) +{ + bool retval = true; + + // In Beken simulation, return following hardcoded list of Strings that are valid values for the ActiveLocale. + CHIP_ERROR err = CHIP_NO_ERROR; + + const char * activeLocalePtr = nullptr; + + VerifyOrReturnError(mIndex < 8, false); + + switch (mIndex) + { + case 0: + activeLocalePtr = "en-US"; + break; + case 1: + activeLocalePtr = "de-DE"; + break; + case 2: + activeLocalePtr = "fr-FR"; + break; + case 3: + activeLocalePtr = "en-GB"; + break; + case 4: + activeLocalePtr = "es-ES"; + break; + case 5: + activeLocalePtr = "zh-CN"; + break; + case 6: + activeLocalePtr = "it-IT"; + break; + case 7: + activeLocalePtr = "ja-JP"; + break; + default: + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + break; + } + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(std::strlen(activeLocalePtr) <= kMaxActiveLocaleLength, false); + + Platform::CopyString(mActiveLocaleBuf, kMaxActiveLocaleLength + 1, activeLocalePtr); + + output = CharSpan::fromCharString(mActiveLocaleBuf); + + mIndex++; + + retval = true; + } + else + { + retval = false; + } + + return retval; +} + +DeviceInfoProvider::SupportedCalendarTypesIterator * DeviceInfoProviderImpl::IterateSupportedCalendarTypes() +{ + return new SupportedCalendarTypesIteratorImpl(); +} + +size_t DeviceInfoProviderImpl::SupportedCalendarTypesIteratorImpl::Count() +{ + // In Beken Simulation, return the size of the hardcoded list of Strings that are valid values for the Calendar Types. + // {("kBuddhist"), ("kChinese"), ("kCoptic"), ("kEthiopian"), ("kGregorian"), ("kHebrew"), ("kIndian"), ("kJapanese"), + // ("kKorean"), ("kPersian"), ("kTaiwanese"), ("kIslamic")} + + return 12; +} + +bool DeviceInfoProviderImpl::SupportedCalendarTypesIteratorImpl::Next(CalendarType & output) +{ + bool retval = true; + + // In Beken Simulation, return following hardcoded list of Strings that are valid values for the Calendar Types. + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrReturnError(mIndex < 12, false); + + switch (mIndex) + { + case 0: + output = app::Clusters::TimeFormatLocalization::CalendarType::kBuddhist; + break; + case 1: + output = app::Clusters::TimeFormatLocalization::CalendarType::kChinese; + break; + case 2: + output = app::Clusters::TimeFormatLocalization::CalendarType::kCoptic; + break; + case 3: + output = app::Clusters::TimeFormatLocalization::CalendarType::kEthiopian; + break; + case 4: + output = app::Clusters::TimeFormatLocalization::CalendarType::kGregorian; + break; + case 5: + output = app::Clusters::TimeFormatLocalization::CalendarType::kHebrew; + break; + case 6: + output = app::Clusters::TimeFormatLocalization::CalendarType::kIndian; + break; + case 7: + output = app::Clusters::TimeFormatLocalization::CalendarType::kJapanese; + break; + case 8: + output = app::Clusters::TimeFormatLocalization::CalendarType::kKorean; + break; + case 9: + output = app::Clusters::TimeFormatLocalization::CalendarType::kPersian; + break; + case 10: + output = app::Clusters::TimeFormatLocalization::CalendarType::kTaiwanese; + break; + case 11: + output = app::Clusters::TimeFormatLocalization::CalendarType::kIslamic; + break; + default: + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + break; + } + + if (err == CHIP_NO_ERROR) + { + mIndex++; + retval = true; + } + else + { + retval = false; + } + + return retval; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/DeviceInfoProviderImpl.h b/src/platform/Beken/DeviceInfoProviderImpl.h new file mode 100644 index 00000000000000..d62b26136800a3 --- /dev/null +++ b/src/platform/Beken/DeviceInfoProviderImpl.h @@ -0,0 +1,107 @@ +/* + * + * Copyright (c) 2022 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 + +namespace chip { +namespace DeviceLayer { + +class DeviceInfoProviderImpl : public DeviceInfoProvider +{ +public: + DeviceInfoProviderImpl() = default; + ~DeviceInfoProviderImpl() override {} + + // Iterators + FixedLabelIterator * IterateFixedLabel(EndpointId endpoint) override; + UserLabelIterator * IterateUserLabel(EndpointId endpoint) override; + SupportedLocalesIterator * IterateSupportedLocales() override; + SupportedCalendarTypesIterator * IterateSupportedCalendarTypes() override; + + static DeviceInfoProviderImpl & GetDefaultInstance(); + +protected: + class FixedLabelIteratorImpl : public FixedLabelIterator + { + public: + FixedLabelIteratorImpl(EndpointId endpoint); + size_t Count() override; + bool Next(FixedLabelType & output) override; + void Release() override { delete this; } + + private: + EndpointId mEndpoint = 0; + size_t mIndex = 0; + char mFixedLabelNameBuf[kMaxLabelNameLength + 1]; + char mFixedLabelValueBuf[kMaxLabelValueLength + 1]; + }; + + class UserLabelIteratorImpl : public UserLabelIterator + { + public: + UserLabelIteratorImpl(DeviceInfoProviderImpl & provider, EndpointId endpoint); + size_t Count() override { return mTotal; } + bool Next(UserLabelType & output) override; + void Release() override { delete this; } + + private: + DeviceInfoProviderImpl & mProvider; + EndpointId mEndpoint = 0; + size_t mIndex = 0; + size_t mTotal = 0; + char mUserLabelNameBuf[kMaxLabelNameLength + 1]; + char mUserLabelValueBuf[kMaxLabelValueLength + 1]; + }; + + class SupportedLocalesIteratorImpl : public SupportedLocalesIterator + { + public: + SupportedLocalesIteratorImpl() = default; + size_t Count() override; + bool Next(CharSpan & output) override; + void Release() override { delete this; } + + private: + size_t mIndex = 0; + char mActiveLocaleBuf[kMaxActiveLocaleLength + 1]; + }; + + class SupportedCalendarTypesIteratorImpl : public SupportedCalendarTypesIterator + { + public: + SupportedCalendarTypesIteratorImpl() = default; + size_t Count() override; + bool Next(CalendarType & output) override; + void Release() override { delete this; } + + private: + size_t mIndex = 0; + }; + + CHIP_ERROR SetUserLabelLength(EndpointId endpoint, size_t val) override; + CHIP_ERROR GetUserLabelLength(EndpointId endpoint, size_t & val) override; + CHIP_ERROR SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel) override; + +private: + static constexpr size_t UserLabelTLVMaxSize() { return TLV::EstimateStructOverhead(kMaxLabelNameLength, kMaxLabelValueLength); } +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/DiagnosticDataProviderImpl.cpp b/src/platform/Beken/DiagnosticDataProviderImpl.cpp new file mode 100644 index 00000000000000..a26b37dd4dc370 --- /dev/null +++ b/src/platform/Beken/DiagnosticDataProviderImpl.cpp @@ -0,0 +1,301 @@ +/* + * + * Copyright (c) 2021 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 DiagnosticDataProvider object + * for Beken platform. + */ + +#include + +#include +#include +#include + +#include "matter_pal.h" + +namespace chip { +namespace DeviceLayer { + +DiagnosticDataProviderImpl & DiagnosticDataProviderImpl::GetDefaultInstance() +{ + static DiagnosticDataProviderImpl sInstance; + return sInstance; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapFree(uint64_t & currentHeapFree) +{ + currentHeapFree = xPortGetFreeHeapSize(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapUsed(uint64_t & currentHeapUsed) +{ + currentHeapUsed = prvHeapGetTotalSize() - xPortGetFreeHeapSize(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) +{ + currentHeapHighWatermark = prvHeapGetTotalSize() - xPortGetMinimumEverFreeHeapSize(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount) +{ + uint32_t count = 0; + + CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count); + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(count <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + rebootCount = static_cast(count); + } + + return err; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime) +{ + System::Clock::Timestamp currentTime = System::SystemClock().GetMonotonicTimestamp(); + System::Clock::Timestamp startTime = PlatformMgrImpl().GetStartTime(); + + if (currentTime >= startTime) + { + upTime = std::chrono::duration_cast(currentTime - startTime).count(); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_INVALID_TIME; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + uint64_t upTime = 0; + + if (GetUpTime(upTime) == CHIP_NO_ERROR) + { + uint32_t totalHours = 0; + if (ConfigurationMgr().GetTotalOperationalHours(totalHours) == CHIP_NO_ERROR) + { + VerifyOrReturnError(upTime / 3600 <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + totalOperationalHours = totalHours + static_cast(upTime / 3600); + return CHIP_NO_ERROR; + } + } + + return CHIP_ERROR_INVALID_TIME; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(BootReasonType & bootReason) +{ + uint32_t reason = 0; + + CHIP_ERROR err = ConfigurationMgr().GetBootReason(reason); + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(reason <= UINT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + bootReason = static_cast(reason); + } + + return err; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp) +{ + NetworkInterface * ifp = new NetworkInterface(); + struct netif * netif; + + netif = (struct netif *) net_get_sta_handle(); // assume only on station mode + if (netif == NULL || ifp == NULL) + { + ChipLogError(DeviceLayer, "Can't get the netif instance"); + *netifpp = NULL; + return CHIP_ERROR_INTERNAL; + } + + strncpy(ifp->Name, netif->hostname, Inet::InterfaceId::kMaxIfNameLength); + ifp->Name[Inet::InterfaceId::kMaxIfNameLength - 1] = '\0'; + ifp->name = CharSpan::fromCharString(ifp->Name); + ifp->type = EMBER_ZCL_INTERFACE_TYPE_WI_FI; + ifp->offPremiseServicesReachableIPv4.SetNonNull(false); + ifp->offPremiseServicesReachableIPv6.SetNonNull(false); + memcpy(ifp->MacAddress, netif->hwaddr, sizeof(netif->hwaddr)); + *netifpp = ifp; + return CHIP_NO_ERROR; +} + +void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp) +{ + while (netifp) + { + NetworkInterface * del = netifp; + netifp = netifp->Next; + delete del; + } +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBssId(ByteSpan & BssId) +{ + LinkStatusTypeDef linkStatus; + + memset(&linkStatus, 0x0, sizeof(LinkStatusTypeDef)); + if (0 == bk_wlan_get_link_status(&linkStatus)) + { + BssId = ByteSpan(linkStatus.bssid, 6); + } + else + { + ChipLogError(DeviceLayer, "GetWiFiBssId Not Supported"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiVersion(uint8_t & wifiVersion) +{ + // Support 802.11a/n Wi-Fi in Beken chipset + wifiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_802__11N; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiSecurityType(uint8_t & securityType) +{ + int cipher_type; + cipher_type = bk_sta_cipher_type(); + switch (cipher_type) + { + case BK_SECURITY_TYPE_NONE: + securityType = EMBER_ZCL_SECURITY_TYPE_NONE; + break; + case BK_SECURITY_TYPE_WEP: + securityType = EMBER_ZCL_SECURITY_TYPE_WEP; + break; + case BK_SECURITY_TYPE_WPA_TKIP: + case BK_SECURITY_TYPE_WPA_AES: + securityType = EMBER_ZCL_SECURITY_TYPE_WPA; + break; + case BK_SECURITY_TYPE_WPA2_AES: + case BK_SECURITY_TYPE_WPA2_TKIP: + case BK_SECURITY_TYPE_WPA2_MIXED: + securityType = EMBER_ZCL_SECURITY_TYPE_WPA2; + break; + case BK_SECURITY_TYPE_WPA3_SAE: + case BK_SECURITY_TYPE_WPA3_WPA2_MIXED: + securityType = EMBER_ZCL_SECURITY_TYPE_WPA3; + break; + case BK_SECURITY_TYPE_AUTO: + default: + securityType = EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiChannelNumber(uint16_t & channelNumber) +{ + LinkStatusTypeDef linkStatus; + + memset(&linkStatus, 0x0, sizeof(LinkStatusTypeDef)); + if (0 == bk_wlan_get_link_status(&linkStatus)) + { + channelNumber = linkStatus.channel; + } + else + { + ChipLogError(DeviceLayer, "GetWiFiChannelNumber Not Supported"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiRssi(int8_t & rssi) +{ + LinkStatusTypeDef linkStatus; + + memset(&linkStatus, 0x0, sizeof(LinkStatusTypeDef)); + if (0 == bk_wlan_get_link_status(&linkStatus)) + { + rssi = linkStatus.wifi_strength; + } + else + { + ChipLogError(DeviceLayer, "GetWiFiRssi Not Supported"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconLostCount(uint32_t & beaconLostCount) +{ + beaconLostCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) +{ + currentMaxRate = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) +{ + packetMulticastRxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) +{ + packetMulticastTxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) +{ + packetUnicastRxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) +{ + packetUnicastTxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiOverrunCount(uint64_t & overrunCount) +{ + overrunCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::ResetWiFiNetworkDiagnosticsCounts() +{ + return CHIP_NO_ERROR; +} + +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI + +DiagnosticDataProvider & GetDiagnosticDataProviderImpl() +{ + return DiagnosticDataProviderImpl::GetDefaultInstance(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/DiagnosticDataProviderImpl.h b/src/platform/Beken/DiagnosticDataProviderImpl.h new file mode 100644 index 00000000000000..1d0ef93a80ba6d --- /dev/null +++ b/src/platform/Beken/DiagnosticDataProviderImpl.h @@ -0,0 +1,78 @@ +/* + * + * Copyright (c) 2021 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 DiagnosticDataProvider object. + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for Linux platforms. + */ +class DiagnosticDataProviderImpl : public DiagnosticDataProvider +{ +public: + static DiagnosticDataProviderImpl & GetDefaultInstance(); + + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override; + CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override; + CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override; + + CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override; + CHIP_ERROR GetUpTime(uint64_t & upTime) override; + CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override; + CHIP_ERROR GetBootReason(BootReasonType & bootReason) override; + + CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override; + void ReleaseNetworkInterfaces(NetworkInterface * netifp) override; + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + CHIP_ERROR GetWiFiBssId(ByteSpan & BssId) override; + CHIP_ERROR GetWiFiSecurityType(uint8_t & securityType) override; + CHIP_ERROR GetWiFiVersion(uint8_t & wifiVersion) override; + CHIP_ERROR GetWiFiChannelNumber(uint16_t & channelNumber) override; + CHIP_ERROR GetWiFiRssi(int8_t & rssi) override; + CHIP_ERROR GetWiFiBeaconLostCount(uint32_t & beaconLostCount) override; + CHIP_ERROR GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) override; + CHIP_ERROR GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) override; + CHIP_ERROR GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) override; + CHIP_ERROR GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) override; + CHIP_ERROR GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) override; + CHIP_ERROR GetWiFiOverrunCount(uint64_t & overrunCount) override; + CHIP_ERROR ResetWiFiNetworkDiagnosticsCounts() override; +#endif +}; + +/** + * Returns the platform-specific implementation of the DiagnosticDataProvider singleton object. + * + * Applications can use this to gain access to features of the DiagnosticDataProvider + * that are specific to the selected platform. + */ +DiagnosticDataProvider & GetDiagnosticDataProviderImpl(); + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/InetPlatformConfig.h b/src/platform/Beken/InetPlatformConfig.h new file mode 100755 index 00000000000000..ef21415a816950 --- /dev/null +++ b/src/platform/Beken/InetPlatformConfig.h @@ -0,0 +1,47 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific configuration overrides for the CHIP Inet + * Layer on the Beken platform. + * + */ + +#pragma once + +// ==================== Platform Adaptations ==================== + +#define INET_CONFIG_ERROR_TYPE int32_t +#define INET_CONFIG_NO_ERROR 0 +#define INET_CONFIG_ERROR_MIN 1000000 +#define INET_CONFIG_ERROR_MAX 1000999 + +// ==================== General Configuration Overrides ==================== + +// NOTE: Values that are mapped to CONFIG_ #defines are settable via the Kconfig mechanism. + +#ifndef INET_CONFIG_NUM_TCP_ENDPOINTS +#define INET_CONFIG_NUM_TCP_ENDPOINTS 10 +#endif // INET_CONFIG_NUM_TCP_ENDPOINTS + +#ifndef INET_CONFIG_NUM_UDP_ENDPOINTS +#define INET_CONFIG_NUM_UDP_ENDPOINTS 10 +#endif // INET_CONFIG_NUM_UDP_ENDPOINTS + +#define INET_CONFIG_ENABLE_IPV4 1 diff --git a/src/platform/Beken/KeyValueStoreManagerImpl.cpp b/src/platform/Beken/KeyValueStoreManagerImpl.cpp new file mode 100644 index 00000000000000..d49c67baaa98d7 --- /dev/null +++ b/src/platform/Beken/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,120 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for Beken + */ +/* this file behaves like a config.h, comes first */ +#include "matter_pal.h" +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, + size_t offset_bytes) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + int32_t ret = -1; + uint32_t dwTeReadBytes = 0; + + if ((!value) || offset_bytes > 0) + { + // Offset and partial reads are not supported in nvs, for now just return NOT_IMPLEMENTED. Support can be added in the + // future if this is needed. + return (err = CHIP_ERROR_INVALID_ARGUMENT); + } + + if (read_bytes_size == NULL) + { + ret = bk_read_data(GetKVNameSpaceName(key), key, (char *) value, value_size, &dwTeReadBytes); + } + else + { + ret = bk_read_data(GetKVNameSpaceName(key), key, (char *) value, value_size, (uint32_t *) read_bytes_size); + } + if (ret == kNoErr) + { + err = CHIP_NO_ERROR; + } + else + { + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } + + return err; +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint32_t ret = 0; + bk_printf("put key:%s \r\n", key); + if (!value) + { + return (err = CHIP_ERROR_INVALID_ARGUMENT); + } + + ret = bk_write_data(GetKVNameSpaceName(key), key, (char *) value, value_size); + + if (ret == kNoErr) + { + err = CHIP_NO_ERROR; + } + else + { + err = CHIP_ERROR_INTERNAL; + } + + return err; +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) +{ + uint32_t ret = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + + bk_clean_data(GetKVNameSpaceName(key), key); + + return CHIP_NO_ERROR; +} + +const char * KeyValueStoreManagerImpl::GetKVNameSpaceName(const char * key) +{ + int idx = 0; + const char * BekenkeyValueNameSpace[] = { "BEKEN0", "BEKEN1", "BEKEN2", "BEKEN3", + "BEKEN4" }; // Put all key-value date into this namespace + if (key != NULL) + { + int i, len = strlen(key); + int sum = 0; + for (i = 0; i < len; i += 2) + sum += key[i]; + idx = sum % (sizeof(BekenkeyValueNameSpace) / sizeof(BekenkeyValueNameSpace[0])); + } + return BekenkeyValueNameSpace[idx]; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/KeyValueStoreManagerImpl.h b/src/platform/Beken/KeyValueStoreManagerImpl.h new file mode 100644 index 00000000000000..e1c162e00c1f11 --- /dev/null +++ b/src/platform/Beken/KeyValueStoreManagerImpl.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for Beken + */ +/* this file behaves like a config.h, comes first */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +class KeyValueStoreManagerImpl final : public KeyValueStoreManager +{ + // Allow the KeyValueStoreManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class KeyValueStoreManager; + +public: + // NOTE: Currently this platform does not support partial and offset reads + // these will return CHIP_ERROR_NOT_IMPLEMENTED. + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0); + + CHIP_ERROR _Delete(const char * key); + + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size); + +private: + // ===== Members for internal use by the following friends. + friend KeyValueStoreManager & KeyValueStoreMgr(); + friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); + + static KeyValueStoreManagerImpl sInstance; + const char * GetKVNameSpaceName(const char * key); +}; + +/** + * Returns the public interface of the KeyValueStoreManager singleton object. + * + * Chip applications should use this to access features of the KeyValueStoreManager object + * that are common to all platforms. + */ +inline KeyValueStoreManager & KeyValueStoreMgr(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/Logging.cpp b/src/platform/Beken/Logging.cpp new file mode 100644 index 00000000000000..f7bbeeeb8ca3bb --- /dev/null +++ b/src/platform/Beken/Logging.cpp @@ -0,0 +1,69 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides implementations for the CHIP logging functions + * on the Beken platform. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include +extern "C" void bk_printf(const char * fmt, ...); + +#ifdef LOG_LOCAL_LEVEL +#undef LOG_LOCAL_LEVEL +#endif + +namespace chip { +namespace Logging { +namespace Platform { + +void LogV(const char * module, uint8_t category, const char * msg, va_list v) +{ + char tag[11]; + + snprintf(tag, sizeof(tag), "chip[%s]", module); + tag[sizeof(tag) - 1] = 0; + + char formattedMsg[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE]; + vsnprintf(formattedMsg, sizeof(formattedMsg), msg, v); + + switch (category) + { + case kLogCategory_Error: + bk_printf("%s %s\r\n", tag, formattedMsg); + break; + case kLogCategory_Progress: + default: + bk_printf("%s %s\r\n", tag, formattedMsg); + break; + case kLogCategory_Detail: + case kLogCategory_Automation: + bk_printf("%s %s\r\n", tag, formattedMsg); + break; + } +} + +} // namespace Platform +} // namespace Logging +} // namespace chip diff --git a/src/platform/Beken/LwIPCoreLock.cpp b/src/platform/Beken/LwIPCoreLock.cpp new file mode 100644 index 00000000000000..7629ca3a4cf5ff --- /dev/null +++ b/src/platform/Beken/LwIPCoreLock.cpp @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include + +namespace { + +SemaphoreHandle_t LwIPCoreLock; + +} + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +CHIP_ERROR InitLwIPCoreLock(void) +{ + if (LwIPCoreLock == NULL) + { + LwIPCoreLock = xSemaphoreCreateMutex(); + if (LwIPCoreLock == NULL) + { + ChipLogError(DeviceLayer, "Failed to create LwIP core lock"); + return CHIP_ERROR_NO_MEMORY; + } + } + + return CHIP_NO_ERROR; +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip + +extern "C" void lock_lwip_core() +{ + xSemaphoreTake(LwIPCoreLock, portMAX_DELAY); +} + +extern "C" void unlock_lwip_core() +{ + xSemaphoreGive(LwIPCoreLock); +} diff --git a/src/platform/Beken/NetworkCommissioningDriver.h b/src/platform/Beken/NetworkCommissioningDriver.h new file mode 100644 index 00000000000000..6b226dea5ee4b3 --- /dev/null +++ b/src/platform/Beken/NetworkCommissioningDriver.h @@ -0,0 +1,141 @@ +/* + * + * Copyright (c) 2021 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 + +#define NC_SECURITYCONVERT(security) ((security < 3) ? security : (security == 3) ? 2 : (security < 7) ? 3 : 4) + +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { + +namespace { +constexpr uint8_t kMaxWiFiNetworks = 1; +constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; +constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 20; +} // namespace + +class BKScanResponseIterator : public Iterator +{ +public: + BKScanResponseIterator(const size_t size, const wifi_scan_result_t * scanResults) : mSize(size), mpScanResults(scanResults) {} + size_t Count() override { return mSize; } + bool Next(WiFiScanResponse & item) override + { + if (mIternum >= mSize) + { + return false; + } + uint8_t ssidlenth = strlen(mpScanResults->aps[mIternum].ssid); + item.security.SetRaw(NC_SECURITYCONVERT(mpScanResults->aps[mIternum].security)); + item.ssidLen = ssidlenth; + item.channel = mpScanResults->aps[mIternum].channel; + item.wiFiBand = chip::DeviceLayer::NetworkCommissioning::WiFiBand::k2g4; + item.rssi = mpScanResults->aps[mIternum].rssi; + memcpy(item.ssid, mpScanResults->aps[mIternum].ssid, ssidlenth); + memcpy(item.bssid, mpScanResults->aps[mIternum].bssid, 6); + + mIternum++; + return true; + } + void Release() override {} + +private: + const size_t mSize; + const wifi_scan_result_t * mpScanResults; + size_t mIternum = 1; +}; + +class BekenWiFiDriver final : public WiFiDriver +{ +public: + class WiFiNetworkIterator final : public NetworkIterator + { + public: + WiFiNetworkIterator(BekenWiFiDriver * aDriver) : mDriver(aDriver) {} + size_t Count() override; + bool Next(Network & item) override; + void Release() override { delete this; } + ~WiFiNetworkIterator() = default; + + private: + BekenWiFiDriver * mDriver; + bool mExhausted = false; + }; + + struct WiFiNetwork + { + char ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength]; + uint8_t ssidLen = 0; + char credentials[DeviceLayer::Internal::kMaxWiFiKeyLength]; + uint8_t credentialsLen = 0; + }; + + // BaseDriver + NetworkIterator * GetNetworks() override { return new WiFiNetworkIterator(this); } + CHIP_ERROR Init(NetworkStatusChangeCallback * networkStatusChangeCallback) override; + void Shutdown() override; + + // WirelessDriver + uint8_t GetMaxNetworks() override { return kMaxWiFiNetworks; } + uint8_t GetScanNetworkTimeoutSeconds() override { return kWiFiScanNetworksTimeOutSeconds; } + uint8_t GetConnectNetworkTimeoutSeconds() override { return kWiFiConnectNetworkTimeoutSeconds; } + + CHIP_ERROR CommitConfiguration() override; + CHIP_ERROR RevertConfiguration() override; + + Status RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override; + Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) override; + void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override; + + // WiFiDriver + Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, + uint8_t & outNetworkIndex) override; + void ScanNetworks(ByteSpan ssid, ScanCallback * callback) override; + + CHIP_ERROR ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen); + void OnConnectWiFiNetwork(); + void OnScanWiFiNetworkDone(); + void OnNetworkStatusChange(); + + CHIP_ERROR SetLastDisconnectReason(const ChipDeviceEvent * event); + int32_t GetLastDisconnectReason(); + + static BekenWiFiDriver & GetInstance() + { + static BekenWiFiDriver instance; + return instance; + } + CHIP_ERROR GetSavedNetWorkConfig(WiFiNetwork * WifiNetconf); + +private: + bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId); + CHIP_ERROR StartScanWiFiNetworks(ByteSpan ssid); + + WiFiNetworkIterator mWiFiIterator = WiFiNetworkIterator(this); + WiFiNetwork mSavedNetwork; + WiFiNetwork mStagingNetwork; + ScanCallback * mpScanCallback; + ConnectCallback * mpConnectCallback; + NetworkStatusChangeCallback * mpStatusChangeCallback = nullptr; + int32_t mLastDisconnectedReason; +}; + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/NetworkCommissioningWiFiDriver.cpp b/src/platform/Beken/NetworkCommissioningWiFiDriver.cpp new file mode 100644 index 00000000000000..6f3cdd3c9c3d63 --- /dev/null +++ b/src/platform/Beken/NetworkCommissioningWiFiDriver.cpp @@ -0,0 +1,366 @@ +/* + * + * Copyright (c) 2021 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 +#include +#include +#include + +#include +#include + +#include "wlan_ui_pub.h" + +using namespace ::chip; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { + +namespace { +constexpr char kWiFiSSIDKeyName[] = "wifi-ssid"; +constexpr char kWiFiCredentialsKeyName[] = "wifi-pass"; +} // namespace + +CHIP_ERROR BekenWiFiDriver::Init(NetworkStatusChangeCallback * networkStatusChangeCallback) +{ + CHIP_ERROR err; + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::Init\r\n"); + + err = GetSavedNetWorkConfig(&mSavedNetwork); + + mStagingNetwork = mSavedNetwork; + mpScanCallback = nullptr; + mpConnectCallback = nullptr; + mpStatusChangeCallback = networkStatusChangeCallback; + return err; +} + +CHIP_ERROR BekenWiFiDriver::GetSavedNetWorkConfig(WiFiNetwork * WifiNetconf) +{ + CHIP_ERROR err; + size_t ssidLen = 0; + size_t credentialsLen = 0; + + memset(WifiNetconf, 0x0, sizeof(WiFiNetwork)); + err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, WifiNetconf->credentials, + sizeof(WifiNetconf->credentials), &credentialsLen); + if (err == CHIP_ERROR_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + + err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, WifiNetconf->ssid, sizeof(WifiNetconf->ssid), &ssidLen); + if (err == CHIP_ERROR_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + WifiNetconf->credentialsLen = credentialsLen; + WifiNetconf->ssidLen = ssidLen; + return err; +} + +void BekenWiFiDriver::Shutdown() +{ + mpStatusChangeCallback = nullptr; +} + +CHIP_ERROR BekenWiFiDriver::CommitConfiguration() +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::CommitConfiguration\r\n"); + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen)); + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials, + mStagingNetwork.credentialsLen)); + mSavedNetwork = mStagingNetwork; + return CHIP_NO_ERROR; +} + +CHIP_ERROR BekenWiFiDriver::RevertConfiguration() +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::RevertConfiguration\r\n"); + mStagingNetwork = mSavedNetwork; + return CHIP_NO_ERROR; +} + +bool BekenWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::NetworkMatch\r\n"); + return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0; +} + +Status BekenWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, + uint8_t & outNetworkIndex) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::AddOrUpdateNetwork\r\n"); + + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded); + VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange); + VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange); + + memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size()); + mStagingNetwork.credentialsLen = static_cast(credentials.size()); + + memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size()); + mStagingNetwork.ssidLen = static_cast(ssid.size()); + + return Status::kSuccess; +} + +Status BekenWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::RemoveNetwork\r\n"); + + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + + // Use empty ssid for representing invalid network + mStagingNetwork.ssidLen = 0; + return Status::kSuccess; +} + +Status BekenWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ReorderNetwork\r\n"); + // Only one network is supported now + outDebugText.reduce_size(0); + VerifyOrReturnError(index == 0, Status::kOutOfRange); + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + return Status::kSuccess; +} + +CHIP_ERROR BekenWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ConnectWiFiNetwork....ssid:%s", ssid); + ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); + + wifi_sta_config_t sta_config; + memset(&sta_config, 0x0, sizeof(sta_config)); + sta_config.security = WIFI_SECURITY_AUTO; // can't use WIFI_DEFAULT_STA_CONFIG because of C99 designator error + strncpy(sta_config.ssid, ssid, ssidLen); + strncpy(sta_config.password, key, keyLen); + + BK_LOG_ON_ERR(bk_wifi_sta_set_config(&sta_config)); + BK_LOG_ON_ERR(bk_wifi_sta_start()); + BK_LOG_ON_ERR(bk_wifi_sta_connect()); + + return ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled); +} + +void BekenWiFiDriver::OnConnectWiFiNetwork() +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::OnConnectWiFiNetwork\r\n"); + if (mpConnectCallback) + { + // chip::DeviceLayer::PlatformMgr().LockChipStack(); + mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0); + // chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + mpConnectCallback = nullptr; + } +} + +void BekenWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ConnectNetwork\r\n"); + CHIP_ERROR err = CHIP_NO_ERROR; + Status networkingStatus = Status::kSuccess; + + VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound); + VerifyOrExit(mpConnectCallback == nullptr, networkingStatus = Status::kUnknownError); + + err = ConnectWiFiNetwork(reinterpret_cast(mStagingNetwork.ssid), mStagingNetwork.ssidLen, + reinterpret_cast(mStagingNetwork.credentials), mStagingNetwork.credentialsLen); + mpConnectCallback = callback; +exit: + if (err != CHIP_NO_ERROR) + { + networkingStatus = Status::kUnknownError; + } + if (networkingStatus != Status::kSuccess) + { + ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network:%s", chip::ErrorStr(err)); + mpConnectCallback = nullptr; + // chip::DeviceLayer::PlatformMgr().LockChipStack(); + callback->OnResult(networkingStatus, CharSpan(), 0); + // chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + } +} + +CHIP_ERROR GetConnectedNetwork(Network & network) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::GetConnectedNetwork\r\n"); + wifi_link_status_t wifi_setting; + memset(&wifi_setting, 0x0, sizeof(wifi_setting)); + bk_wifi_sta_get_link_status(&wifi_setting); + uint8_t length = strnlen(reinterpret_cast(wifi_setting.ssid), DeviceLayer::Internal::kMaxWiFiSSIDLength); + + os_memcpy(network.networkID, wifi_setting.ssid, length); + ChipLogProgress(NetworkProvisioning, "networkID:[%s][%d]\r\n", network.networkID, length); + network.networkIDLen = length; + return CHIP_NO_ERROR; +} + +void BekenWiFiDriver::OnNetworkStatusChange() +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::OnNetworkStatusChange\r\n"); + Network configuredNetwork = { 0 }; + + VerifyOrReturn(mpStatusChangeCallback != nullptr); + GetConnectedNetwork(configuredNetwork); + + if (configuredNetwork.networkIDLen) + { + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kSuccess, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), NullOptional); + return; + } + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kUnknownError, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), + MakeOptional(GetLastDisconnectReason())); +} + +CHIP_ERROR BekenWiFiDriver::SetLastDisconnectReason(const ChipDeviceEvent * event) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::SetLastDisconnectReason\r\n"); + mLastDisconnectedReason = event->Platform.BKSystemEvent.Data.WiFiStaDisconnected; + return CHIP_NO_ERROR; +} + +int32_t BekenWiFiDriver::GetLastDisconnectReason() +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::GetLastDisconnectReason\r\n"); + return mLastDisconnectedReason; +} + +static beken_semaphore_t matter_scan_sema = NULL; + +int scan_done_handler(void * arg, event_module_t event_module, int event_id, void * event_data) +{ + if (matter_scan_sema) + { + rtos_set_semaphore(&matter_scan_sema); + } + return BK_OK; +} + +CHIP_ERROR BekenWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::StartScanWiFiNetworks\r\n"); + wifi_scan_config_t config = { 0 }; + if (ssid.data() == NULL) // non-directed scanning + { + ChipLogProgress(NetworkProvisioning, "non-directed scanning...\r\n"); + BK_LOG_ON_ERR(bk_wifi_scan_start(NULL)); + } + else // directed scanning + { + os_memcpy(config.ssid, ssid.data(), ssid.size()); + ChipLogProgress(NetworkProvisioning, "directed scanning... ssid:%s ; %d \r\n", config.ssid, ssid.size()); + BK_LOG_ON_ERR(bk_wifi_scan_start(&config)); + } + return CHIP_NO_ERROR; +} + +void BekenWiFiDriver::OnScanWiFiNetworkDone() +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::OnScanWiFiNetworkDone\r\n"); + if (!GetInstance().mpScanCallback) + { + ChipLogProgress(NetworkProvisioning, "can't find the ScanCallback function\r\n"); + return; + } + wifi_scan_result_t scan_result = { 0 }; + int scan_rst_ap_num = 0; + BK_LOG_ON_ERR(bk_wifi_scan_get_result(&scan_result)); + scan_rst_ap_num = scan_result.ap_num; + if (scan_rst_ap_num < 2) // beken scan result > = 1 + { + ChipLogProgress(NetworkProvisioning, "NULL AP\r\n"); + GetInstance().mpScanCallback->OnFinished(Status::kNetworkNotFound, CharSpan(), nullptr); + } + else + { + ChipLogProgress(NetworkProvisioning, "AP num = %d\r\n", scan_rst_ap_num); + BKScanResponseIterator iter(scan_rst_ap_num, &scan_result); + GetInstance().mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), &iter); + } + GetInstance().mpScanCallback = nullptr; + bk_wifi_scan_free_result(&scan_result); +} + +void BekenWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::ScanNetworks\r\n"); + if (callback != nullptr) + { + mpScanCallback = callback; + if (matter_scan_sema == NULL) + { + BK_LOG_ON_ERR(rtos_init_semaphore(&matter_scan_sema, 1)); + } + BK_LOG_ON_ERR(bk_event_register_cb(EVENT_MOD_WIFI, EVENT_WIFI_SCAN_DONE, scan_done_handler, NULL)); + if (StartScanWiFiNetworks(ssid) != CHIP_NO_ERROR) + { + mpScanCallback = nullptr; + callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); + } + BK_LOG_ON_ERR(rtos_get_semaphore(&matter_scan_sema, 4000)); // timeout 4000ms + BK_LOG_ON_ERR(bk_event_unregister_cb(EVENT_MOD_WIFI, EVENT_WIFI_SCAN_DONE, scan_done_handler)); + BK_LOG_ON_ERR(rtos_deinit_semaphore(&matter_scan_sema)); + matter_scan_sema = NULL; + OnScanWiFiNetworkDone(); + } +} + +size_t BekenWiFiDriver::WiFiNetworkIterator::Count() +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::WiFiNetworkIterator::Count\r\n"); + return mDriver->mStagingNetwork.ssidLen == 0 ? 0 : 1; +} + +bool BekenWiFiDriver::WiFiNetworkIterator::Next(Network & item) +{ + ChipLogProgress(NetworkProvisioning, "BekenWiFiDriver::WiFiNetworkIterator::Next\r\n"); + if (mExhausted || mDriver->mStagingNetwork.ssidLen == 0) + { + return false; + } + uint8_t length = + strnlen(reinterpret_cast(mDriver->mStagingNetwork.ssid), DeviceLayer::Internal::kMaxWiFiSSIDLength); + memcpy(item.networkID, mDriver->mStagingNetwork.ssid, length); + item.networkIDLen = length; + item.connected = false; + mExhausted = true; + Network connectedNetwork = { 0 }; + CHIP_ERROR err = GetConnectedNetwork(connectedNetwork); + if (err == CHIP_NO_ERROR) + { + if (connectedNetwork.networkIDLen == item.networkIDLen && + memcmp(connectedNetwork.networkID, item.networkID, item.networkIDLen) == 0) + { + item.connected = true; + } + } + return true; +} + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI diff --git a/src/platform/Beken/OTAImageProcessorImpl.cpp b/src/platform/Beken/OTAImageProcessorImpl.cpp new file mode 100644 index 00000000000000..ab22bfae5a3678 --- /dev/null +++ b/src/platform/Beken/OTAImageProcessorImpl.cpp @@ -0,0 +1,351 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "matter_pal.h" +#include +#include + +using namespace chip::System; +using namespace ::chip::DeviceLayer::Internal; + +namespace chip { + +namespace { +void HandleRestart(Layer * systemLayer, void * appState) +{ + bk_reboot(); +} +} // namespace + +const char ucFinishFlag[] = { 0xF0, 0x5D, 0x4A, 0x8C }; // Flag that OTA update has finished +CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() +{ + ChipLogProgress(SoftwareUpdate, "Prepare download"); + + DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::Finalize() +{ + ChipLogProgress(SoftwareUpdate, "Finalize"); + + DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::Apply() +{ + ChipLogProgress(SoftwareUpdate, "Apply"); + + DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::Abort() +{ + ChipLogProgress(SoftwareUpdate, "Abort"); + + DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +bool OTAImageProcessorImpl::IsFirstImageRun() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return false; + } + + return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying; +} + +CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + uint32_t currentVersion; + uint32_t targetVersion = requestor->GetTargetVersion(); + ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion)); + if (currentVersion != targetVersion) + { + ChipLogError(SoftwareUpdate, "Current software version = %" PRIu32 ", expected software version = %" PRIu32, currentVersion, + targetVersion); + return CHIP_ERROR_INCORRECT_STATE; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) +{ + ChipLogProgress(SoftwareUpdate, "Process Block"); + + if ((block.data() == nullptr) || block.empty()) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + CHIP_ERROR err = SetBlock(block); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + else if (imageProcessor->mDownloader == nullptr) + { + ChipLogError(SoftwareUpdate, "mDownloader is null"); + return; + } + + ChipLogProgress(SoftwareUpdate, "%s [%d] OTA address space will be upgraded", __FUNCTION__, __LINE__); + imageProcessor->mHeaderParser.Init(); // Initialize the status of OTA parse + imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); +} + +void OTAImageProcessorImpl::HandleFinalize(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + bk_logic_partition_t * partition_info = NULL; + UINT32 dwFlagAddrOffset = 0; + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + + partition_info = bk_flash_get_info(BK_PARTITION_OTA); + BK_CHECK_POINTER_NULL_TO_VOID(partition_info); + dwFlagAddrOffset = partition_info->partition_length - (sizeof(ucFinishFlag) - 1); + + bk_write_ota_data_to_flash((char *) ucFinishFlag, dwFlagAddrOffset, (sizeof(ucFinishFlag) - 1)); + + imageProcessor->ReleaseBlock(); + + ChipLogProgress(SoftwareUpdate, "OTA image downloaded and written to flash"); +} + +void OTAImageProcessorImpl::HandleAbort(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + + // Abort OTA procedure + + imageProcessor->ReleaseBlock(); +} + +void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + else if (imageProcessor->mDownloader == nullptr) + { + ChipLogError(SoftwareUpdate, "mDownloader is null"); + return; + } + + ByteSpan block = ByteSpan(imageProcessor->mBlock.data(), imageProcessor->mBlock.size()); + + CHIP_ERROR error = imageProcessor->ProcessHeader(block); + if (error != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Failed to process OTA image header"); + imageProcessor->mDownloader->EndDownload(error); + return; + } + + if (!imageProcessor->readHeader) // First block received, process header + { + ota_data_struct_t * tempBuf = (ota_data_struct_t *) chip::Platform::MemoryAlloc(sizeof(ota_data_struct_t)); + + if (NULL == tempBuf) + { + ChipLogError(SoftwareUpdate, "%s [%d] malloc failed ", __FUNCTION__, __LINE__); + } + memset((char *) tempBuf, 0, sizeof(ota_data_struct_t)); + memcpy((char *) &(imageProcessor->pOtaTgtHdr), block.data(), sizeof(ota_data_struct_t)); + + imageProcessor->flash_data_offset = 0; + + bk_read_ota_data_in_flash((char *) tempBuf, imageProcessor->flash_data_offset, sizeof(ota_data_struct_t)); + ChipLogProgress(SoftwareUpdate, "Download version %s,date is %ld ", tempBuf->version, tempBuf->timestamp); + ChipLogProgress(SoftwareUpdate, "Download size_raw %ld,size_package is %ld ", tempBuf->size_raw, tempBuf->size_package); + ChipLogProgress(SoftwareUpdate, "imageProcessor version %s,date is 0x%lx ", imageProcessor->pOtaTgtHdr.version, + imageProcessor->pOtaTgtHdr.timestamp); + + bk_logic_partition_t * partition_info = NULL; + UINT32 dwFlagAddrOffset = 0; + char ucflag[(sizeof(ucFinishFlag) - 1)] = { 0 }; + + partition_info = bk_flash_get_info(BK_PARTITION_OTA); + BK_CHECK_POINTER_NULL_TO_VOID(partition_info); + + dwFlagAddrOffset = partition_info->partition_length - (sizeof(ucFinishFlag) - 1); + bk_read_ota_data_in_flash((char *) ucflag, dwFlagAddrOffset, (sizeof(ucFinishFlag) - 1)); + ChipLogProgress(SoftwareUpdate, "Block size is %d ,ucFinishFlag size len is %d", block.size(), sizeof(ucFinishFlag)); + + if ((0 == memcmp(ucflag, ucFinishFlag, (sizeof(ucFinishFlag) - 1))) && + (0 == memcmp(tempBuf->version, imageProcessor->pOtaTgtHdr.version, sizeof(imageProcessor->pOtaTgtHdr.version)))) + { + chip::Platform::MemoryFree(tempBuf); + tempBuf = NULL; + ChipLogError(SoftwareUpdate, "The version is is the same as the previous version"); + return; + } + + imageProcessor->readHeader = true; + ChipLogProgress(SoftwareUpdate, "flash_data_offset is 0x%lx", imageProcessor->flash_data_offset); + + // Erase update partition + ChipLogProgress(SoftwareUpdate, "Erasing target partition..."); + bk_erase_ota_data_in_flash(); + ChipLogProgress(SoftwareUpdate, "Erasing target partition..."); + + if (0 != bk_write_ota_data_to_flash((char *) block.data(), imageProcessor->flash_data_offset, block.size())) + { + chip::Platform::MemoryFree(tempBuf); + tempBuf = NULL; + ChipLogError(SoftwareUpdate, "bk_write_ota_data_to_flash failed %s [%d] ", __FUNCTION__, __LINE__); + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); + return; + } + + imageProcessor->flash_data_offset += block.size(); // count next write flash address + + chip::Platform::MemoryFree(tempBuf); + tempBuf = NULL; + } + else // received subsequent blocks + { + if (0 != bk_write_ota_data_to_flash((char *) block.data(), imageProcessor->flash_data_offset, block.size())) + { + ChipLogError(SoftwareUpdate, "bk_write_ota_data_to_flash failed %s [%d] ", __FUNCTION__, __LINE__); + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); + return; + } + + imageProcessor->flash_data_offset += block.size(); // count next write flash address + + imageProcessor->size += block.size(); + } + + imageProcessor->mParams.downloadedBytes += block.size(); + imageProcessor->mDownloader->FetchNextData(); +} + +void OTAImageProcessorImpl::HandleApply(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + ChipLogError(SoftwareUpdate, "Update completly,will reboot %s [%d] ", __FUNCTION__, __LINE__); + + // HandleApply is called after delayed action time seconds are elapsed, so it would be safe to schedule the restart + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(2 * 1000), HandleRestart, nullptr); +} + +CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block) +{ + if (!IsSpanUsable(block)) + { + ReleaseBlock(); + return CHIP_NO_ERROR; + } + + if (mBlock.size() < block.size()) + { + if (!mBlock.empty()) + { + ReleaseBlock(); + } + uint8_t * mBlock_ptr = static_cast(chip::Platform::MemoryAlloc(block.size())); + if (mBlock_ptr == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + mBlock = MutableByteSpan(mBlock_ptr, block.size()); + } + CHIP_ERROR err = CopySpanToMutableSpan(block, mBlock); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Cannot copy block data: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock() +{ + if (mBlock.data() != nullptr) + { + chip::Platform::MemoryFree(mBlock.data()); + } + + mBlock = MutableByteSpan(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) +{ + if (mHeaderParser.IsInitialized()) + { + OTAImageHeader header; + CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header); + + // Needs more data to decode the header + ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); + ReturnErrorOnFailure(error); + + mParams.totalFileBytes = header.mPayloadSize; + mHeaderParser.Clear(); + } + + return CHIP_NO_ERROR; +} + +} // namespace chip diff --git a/src/platform/Beken/OTAImageProcessorImpl.h b/src/platform/Beken/OTAImageProcessorImpl.h new file mode 100644 index 00000000000000..8822d9a364bd2c --- /dev/null +++ b/src/platform/Beken/OTAImageProcessorImpl.h @@ -0,0 +1,71 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "flash_namespace_value.h" +#include +#include +#include +#include +#include + +namespace chip { + +class OTAImageProcessorImpl : public OTAImageProcessorInterface +{ +public: + //////////// OTAImageProcessorInterface Implementation /////////////// + CHIP_ERROR PrepareDownload() override; + CHIP_ERROR Finalize() override; + CHIP_ERROR Apply() override; + CHIP_ERROR Abort() override; + CHIP_ERROR ProcessBlock(ByteSpan & block) override; + bool IsFirstImageRun() override; + CHIP_ERROR ConfirmCurrentImage() override; + void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; } + +private: + //////////// Actual handlers for the OTAImageProcessorInterface /////////////// + static void HandlePrepareDownload(intptr_t context); + static void HandleFinalize(intptr_t context); + static void HandleAbort(intptr_t context); + static void HandleProcessBlock(intptr_t context); + static void HandleApply(intptr_t context); + + /** + * Called to allocate memory for mBlock if necessary and set it to block + */ + CHIP_ERROR SetBlock(ByteSpan & block); + + /** + * Called to release allocated memory for mBlock + */ + CHIP_ERROR ReleaseBlock(); + CHIP_ERROR ProcessHeader(ByteSpan & block); + + MutableByteSpan mBlock; + OTADownloader * mDownloader; + OTAImageHeaderParser mHeaderParser; + bool readHeader = false; + ota_data_struct_t pOtaTgtHdr = { 0 }; + uint32_t flash_data_offset = 0; + uint32_t size = 0; +}; + +} // namespace chip diff --git a/src/platform/Beken/PlatformManagerImpl.cpp b/src/platform/Beken/PlatformManagerImpl.cpp new file mode 100644 index 00000000000000..25edc1a2c8ecc4 --- /dev/null +++ b/src/platform/Beken/PlatformManagerImpl.cpp @@ -0,0 +1,97 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the PlatformManager object + * for the Beken platform. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace Internal { +CHIP_ERROR InitLwIPCoreLock(void); +} + +PlatformManagerImpl PlatformManagerImpl::sInstance; + +extern "C" int mbedtls_hardware_poll(void * data, unsigned char * output, size_t len, size_t * olen); + +CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) +{ + + CHIP_ERROR err; + + // Make sure the LwIP core lock has been initialized + err = Internal::InitLwIPCoreLock(); + + SuccessOrExit(err); + + mStartTime = System::SystemClock().GetMonotonicTimestamp(); + + // TODO Wi-Fi Initialzation currently done through the example app needs to be moved into here. + // for now we will let this happen that way and assume all is OK + chip::Crypto::add_entropy_source(mbedtls_hardware_poll, NULL, 32); + + // Call _InitChipStack() on the generic implementation base class + // to finish the initialization process. + err = Internal::GenericPlatformManagerImpl_FreeRTOS::_InitChipStack(); + SuccessOrExit(err); + err = System::Clock::InitClock_RealTime(); + SuccessOrExit(err); + +exit: + return err; +} + +void PlatformManagerImpl::_Shutdown() +{ + uint64_t upTime = 0; + + if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR) + { + uint32_t totalOperationalHours = 0; + + if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR) + { + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast(upTime / 3600)); + } + else + { + ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node"); + } + } + else + { + ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot"); + } + + Internal::GenericPlatformManagerImpl_FreeRTOS::_Shutdown(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/PlatformManagerImpl.h b/src/platform/Beken/PlatformManagerImpl.h new file mode 100644 index 00000000000000..6c434dcac0d1b7 --- /dev/null +++ b/src/platform/Beken/PlatformManagerImpl.h @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the PlatformManager object + * for the Beken platform. + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for the Beken platform. + */ +class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_FreeRTOS +{ + // Allow the PlatformManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend PlatformManager; + + // Allow the generic implementation base class to call helper methods on + // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericPlatformManagerImpl_FreeRTOS; +#endif + +public: + // ===== Platform-specific members that may be accessed directly by the application. + + System::Clock::Timestamp GetStartTime() { return mStartTime; } + +private: + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR _InitChipStack(void); + void _Shutdown(); + + // ===== Members for internal use by the following friends. + + friend PlatformManager & PlatformMgr(void); + friend PlatformManagerImpl & PlatformMgrImpl(void); + + System::Clock::Timestamp mStartTime = System::Clock::kZero; + + static PlatformManagerImpl sInstance; + + using Internal::GenericPlatformManagerImpl_FreeRTOS::PostEventFromISR; +}; + +/** + * Returns the public interface of the PlatformManager singleton object. + * + * Chip applications should use this to access features of the PlatformManager object + * that are common to all platforms. + */ +inline PlatformManager & PlatformMgr(void) +{ + return PlatformManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the PlatformManager singleton object. + * + * Chip applications can use this to gain access to features of the PlatformManager + * that are specific to the Beken platform. + */ +inline PlatformManagerImpl & PlatformMgrImpl(void) +{ + return PlatformManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Beken/SoftwareUpdateManagerImpl.h b/src/platform/Beken/SoftwareUpdateManagerImpl.h new file mode 100755 index 00000000000000..df934dc323345b --- /dev/null +++ b/src/platform/Beken/SoftwareUpdateManagerImpl.h @@ -0,0 +1,89 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER + +#include +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the SoftwareUpdateManager singleton object for the + * Beken platform. + */ +class SoftwareUpdateManagerImpl final : public SoftwareUpdateManager, + public Internal::GenericSoftwareUpdateManagerImpl, + public Internal::GenericSoftwareUpdateManagerImpl_BDX +{ + // Allow the SoftwareUpdateManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class SoftwareUpdateManager; + + // Allow the GenericSoftwareUpdateManagerImpl base class to access helper methods + // and types defined on this class. + friend class Internal::GenericSoftwareUpdateManagerImpl; + + // Allow the GenericSoftwareUpdateManagerImpl_BDX base class to access helper methods + // and types defined on this class. + friend class Internal::GenericSoftwareUpdateManagerImpl_BDX; + +public: + // ===== Members for internal use by the following friends. + + friend ::chip::DeviceLayer::SoftwareUpdateManager & SoftwareUpdateMgr(void); + friend SoftwareUpdateManagerImpl & SoftwareUpdateMgrImpl(void); + + static SoftwareUpdateManagerImpl sInstance; + +private: + // ===== Members that implement the SoftwareUpdateManager abstract interface. + + CHIP_ERROR _Init(void); +}; + +/** + * Returns a reference to the public interface of the SoftwareUpdateManager singleton object. + * + * Internal components should use this to access features of the SoftwareUpdateManager object + * that are common to all platforms. + */ +inline SoftwareUpdateManager & SoftwareUpdateMgr(void) +{ + return SoftwareUpdateManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the SoftwareUpdateManager singleton object. + * + * Internal components can use this to gain access to features of the SoftwareUpdateManager + * that are specific to the Beken platform. + */ +inline SoftwareUpdateManagerImpl & SoftwareUpdateMgrImpl(void) +{ + return SoftwareUpdateManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER diff --git a/src/platform/Beken/SystemPlatformConfig.h b/src/platform/Beken/SystemPlatformConfig.h new file mode 100755 index 00000000000000..944fa44b059a0b --- /dev/null +++ b/src/platform/Beken/SystemPlatformConfig.h @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific configuration overrides for the CHIP System + * Layer on the Beken platform. + * + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +struct ChipDeviceEvent; +} // namespace DeviceLayer +} // namespace chip + +// ==================== Platform Adaptations ==================== +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS 1 +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 1 +#define CHIP_SYSTEM_CONFIG_EVENT_OBJECT_TYPE const struct ::chip::DeviceLayer::ChipDeviceEvent * + +#define CHIP_SYSTEM_CONFIG_ERROR_TYPE uint32_t +#define CHIP_SYSTEM_CONFIG_NO_ERROR 0 +#define CHIP_SYSTEM_CONFIG_ERROR_MIN 7000000 +#define CHIP_SYSTEM_CONFIG_ERROR_MAX 7000999 +#define _CHIP_SYSTEM_CONFIG_ERROR(e) (CHIP_SYSTEM_CONFIG_ERROR_MIN + (e)) +#define CHIP_SYSTEM_LWIP_ERROR_MIN 3000000 +#define CHIP_SYSTEM_LWIP_ERROR_MAX 3000128 + +// ==================== General Configuration Overrides ==================== + +// NOTE: Values that are mapped to CONFIG_ #defines are settable via the Kconfig mechanism. + +#ifndef CHIP_SYSTEM_CONFIG_NUM_TIMERS +#define CHIP_SYSTEM_CONFIG_NUM_TIMERS 16 +#endif // CHIP_SYSTEM_CONFIG_NUM_TIMERS + +#define CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF 0 +#define CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS 0 +#define CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS00 +#define CHIP_SYSTEM_CONFIG_USE_LWIP 1 +#define CHIP_SYSTEM_CONFIG_USE_SOCKETS 0 +#define CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK 0 +#define CHIP_SYSTEM_CONFIG_POSIX_LOCKING 0 +#define CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING 1 +#define CHIP_CONFIG_MDNS_CACHE_SIZE 4 diff --git a/src/platform/Beken/SystemTimeSupport.cpp b/src/platform/Beken/SystemTimeSupport.cpp new file mode 100644 index 00000000000000..1cacab2b0a6336 --- /dev/null +++ b/src/platform/Beken/SystemTimeSupport.cpp @@ -0,0 +1,81 @@ + +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides implementations of the CHIP System Layer platform + * time/clock functions that are suitable for use on the Ameba platform. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include "FreeRTOS.h" + +namespace chip { +namespace System { +namespace Clock { + +namespace Internal { +ClockImpl gClockImpl; +} // namespace Internal + +Clock::Milliseconds64 baseTime; + +Microseconds64 ClockImpl::GetMonotonicMicroseconds64(void) +{ + return (Clock::Microseconds64(xTaskGetTickCount() << 1) * kMicrosecondsPerMillisecond); +} + +Milliseconds64 ClockImpl::GetMonotonicMilliseconds64(void) +{ + return (Clock::Milliseconds64(xTaskGetTickCount() << 1)); +} + +CHIP_ERROR ClockImpl::GetClock_RealTime(Clock::Microseconds64 & curTime) +{ + curTime = GetMonotonicMicroseconds64(); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ClockImpl::GetClock_RealTimeMS(Clock::Milliseconds64 & curTime) +{ + curTime = baseTime + GetMonotonicMilliseconds64(); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ClockImpl::SetClock_RealTime(Clock::Microseconds64 aNewCurTime) +{ + baseTime = Clock::Milliseconds64(aNewCurTime.count() / kMicrosecondsPerMillisecond); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR InitClock_RealTime() +{ + baseTime = + Clock::Milliseconds64((static_cast(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) * kMicrosecondsPerMillisecond)); + + return CHIP_NO_ERROR; +} + +} // namespace Clock +} // namespace System +} // namespace chip diff --git a/src/platform/Beken/SystemTimeSupport.h b/src/platform/Beken/SystemTimeSupport.h new file mode 100755 index 00000000000000..89eb960eea07b9 --- /dev/null +++ b/src/platform/Beken/SystemTimeSupport.h @@ -0,0 +1,29 @@ + +/* + * + * Copyright (c) 2022 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 + +namespace chip { +namespace System { +namespace Clock { + +CHIP_ERROR InitClock_RealTime(); + +} // namespace Clock +} // namespace System +} // namespace chip diff --git a/src/platform/Beken/args.gni b/src/platform/Beken/args.gni new file mode 100755 index 00000000000000..9bdd727ee0e8fe --- /dev/null +++ b/src/platform/Beken/args.gni @@ -0,0 +1,25 @@ +# Copyright (c) 2020 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. + +import("//build_overrides/chip.gni") + +chip_device_platform = "beken" + +lwip_platform = "external" +mbedtls_target = "//mbedtls:mbedtls" + +chip_build_tests = false +chip_inet_config_enable_tun_endpoint = false +chip_inet_config_enable_tcp_endpoint = true +chip_inet_config_enable_udp_endpoint = true diff --git a/src/platform/Beken/matter_pal.h b/src/platform/Beken/matter_pal.h new file mode 100644 index 00000000000000..45b6ab36a81ebd --- /dev/null +++ b/src/platform/Beken/matter_pal.h @@ -0,0 +1,38 @@ +/** + **************************************************************************************** + * + * @file matter_pal.h + * + * @brief This file contains matter_pal. + * @author zhengyaohan + * @date 2022-03-29 + * + **************************************************************************************** + */ + +#ifndef _MATTER_PAL_H_ +#define _MATTER_PAL_H_ + +#include "common/bk_err.h" +#include "common/bk_include.h" +#include +#include +//#include +#include "BkDriverFlash.h" +#include "flash_namespace_value.h" +#include + +#include "bk_wifi.h" +#include "bk_wifi_types.h" +#include "bk_wifi_v1.h" +#include "net.h" +#include "wlan_ui_pub.h" + +#include "portable.h" +#include "projdefs.h" + +#include "at_ble_common.h" +#include "ble.h" + +#endif // _HOMEKIT_PAL_H_ +// eof diff --git a/src/platform/device.gni b/src/platform/device.gni index 3e4486b6df6b7c..0592a6720e13c0 100755 --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -16,7 +16,7 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/ble/ble.gni") declare_args() { - # Device platform layer: cc13x2_26x2, cc32xx, darwin, efr32, esp32, external, freertos, linux, nrfconnect, k32w0, qpg, tizen, cyw30739, bl602, mw320, zephyr, none. + # Device platform layer: cc13x2_26x2, cc32xx, darwin, efr32, esp32, external, freertos, linux, nrfconnect, k32w0, qpg, tizen, cyw30739, bl602, mw320, zephyr, beken, none. chip_device_platform = "auto" chip_platform_target = "" @@ -64,7 +64,7 @@ declare_args() { chip_device_platform == "android" || chip_device_platform == "ameba" || chip_device_platform == "webos" || chip_device_platform == "cc32xx" || chip_device_platform == "bl602" || chip_device_platform == "bl602" || - chip_device_platform == "mw320" || + chip_device_platform == "mw320" || chip_device_platform == "beken" || (chip_device_platform == "darwin" && current_os == "mac") # Enable ble support. @@ -85,7 +85,7 @@ declare_args() { chip_device_platform == "mbed" || chip_device_platform == "p6" || chip_device_platform == "ameba" || chip_device_platform == "webos" || chip_device_platform == "cc32xx" || chip_device_platform == "bl602" || - chip_device_platform == "mw320") { + chip_device_platform == "mw320" || chip_device_platform == "beken") { chip_mdns = "minimal" } else if (chip_device_platform == "darwin" || chip_device_platform == "cc13x2_26x2" || current_os == "android" || @@ -138,6 +138,8 @@ if (chip_device_platform == "cc13x2_26x2") { _chip_device_layter = "nxp/mw320" } else if (chip_device_platform == "zephyr") { _chip_device_layer = "Zephyr" +} else if (chip_device_platform == "beken") { + _chip_device_layer = "Beken" } if (chip_device_platform != "external") { @@ -197,5 +199,6 @@ assert( chip_device_platform == "p6" || chip_device_platform == "android" || chip_device_platform == "ameba" || chip_device_platform == "cyw30739" || chip_device_platform == "webos" || chip_device_platform == "bl602" || - chip_device_platform == "mw320" || chip_device_platform == "zephyr", + chip_device_platform == "mw320" || chip_device_platform == "zephyr" || + chip_device_platform == "beken", "Please select a valid value for chip_device_platform")