From d9fe34ebd0780f4469de80ff8b58552d8f6e432c Mon Sep 17 00:00:00 2001 From: ATmobica Date: Thu, 16 Dec 2021 14:30:47 +0000 Subject: [PATCH] Update Mbed OTA requestor app - implement common OTARequestor and BDXDownloader Fix Mbed shell app build --- config/mbed/CMakeLists.txt | 5 + config/mbed/chip-gn/BUILD.gn | 5 + .../ota-requestor-app/mbed/CMakeLists.txt | 2 +- .../ota-requestor-app/mbed/main/AppTask.cpp | 197 ++++++------ ...rDriver.cpp => OTARequestorDriverImpl.cpp} | 17 +- .../mbed/main/include/AppEvent.h | 20 -- .../mbed/main/include/AppTask.h | 17 +- ...estorDriver.h => OTARequestorDriverImpl.h} | 15 +- examples/ota-requestor-app/mbed/mbed_app.json | 3 +- examples/shell/mbed/mbed_app.json | 3 +- src/platform/mbed/BUILD.gn | 10 +- src/platform/mbed/MbedOTADownloader.cpp | 198 ------------ src/platform/mbed/MbedOTADownloader.h | 95 ------ src/platform/mbed/MbedOTAImageProcessor.cpp | 46 --- src/platform/mbed/MbedOTAImageProcessor.h | 49 --- src/platform/mbed/MbedOTARequestor.cpp | 285 ------------------ src/platform/mbed/MbedOTARequestor.h | 103 ------- src/platform/mbed/OTAImageProcessorImpl.cpp | 181 +++++++++++ src/platform/mbed/OTAImageProcessorImpl.h | 81 +++++ 19 files changed, 423 insertions(+), 909 deletions(-) rename examples/ota-requestor-app/mbed/main/{MbedOTARequestorDriver.cpp => OTARequestorDriverImpl.cpp} (65%) rename examples/ota-requestor-app/mbed/main/include/{MbedOTARequestorDriver.h => OTARequestorDriverImpl.h} (73%) delete mode 100644 src/platform/mbed/MbedOTADownloader.cpp delete mode 100644 src/platform/mbed/MbedOTADownloader.h delete mode 100644 src/platform/mbed/MbedOTAImageProcessor.cpp delete mode 100644 src/platform/mbed/MbedOTAImageProcessor.h delete mode 100644 src/platform/mbed/MbedOTARequestor.cpp delete mode 100644 src/platform/mbed/MbedOTARequestor.h create mode 100644 src/platform/mbed/OTAImageProcessorImpl.cpp create mode 100644 src/platform/mbed/OTAImageProcessorImpl.h diff --git a/config/mbed/CMakeLists.txt b/config/mbed/CMakeLists.txt index 27af412a943472..d467d6fee56672 100644 --- a/config/mbed/CMakeLists.txt +++ b/config/mbed/CMakeLists.txt @@ -451,12 +451,17 @@ if (CONFIG_CHIP_OTA_REQUESTOR) ${CHIP_ROOT}/zzz_generated/ota-requestor-app ${CHIP_ROOT}/src/app/clusters/ota-requestor ${CHIP_ROOT}/src/platform/mbed + ${CHIP_ROOT}/src/include/platform ) target_sources(${APP_TARGET} PRIVATE ${CHIP_ROOT}/zzz_generated/ota-requestor-app/zap-generated/callback-stub.cpp ${CHIP_ROOT}/zzz_generated/ota-requestor-app/zap-generated/CHIPClusters.cpp ${CHIP_ROOT}/zzz_generated/ota-requestor-app/zap-generated/IMClusterCommandHandler.cpp + + ${CHIP_ROOT}/src/app/clusters/ota-requestor/OTARequestor.cpp + ${CHIP_ROOT}/src/app/clusters/ota-requestor/BDXDownloader.cpp + ${CHIP_ROOT}/src/app/clusters/ota-requestor/ClusterInterface.cpp ) list(APPEND CHIP_DEFINES diff --git a/config/mbed/chip-gn/BUILD.gn b/config/mbed/chip-gn/BUILD.gn index 28f56889a1bf46..3f083c3cf8190c 100644 --- a/config/mbed/chip-gn/BUILD.gn +++ b/config/mbed/chip-gn/BUILD.gn @@ -37,6 +37,11 @@ group("mbed") { if (chip_build_pw_rpc_lib) { deps += [ "//lib/pw_rpc" ] } + + if (chip_enable_ota_requestor) { + deps += [ "${chip_root}/examples/ota-requestor-app/ota-requestor-common" ] + + } } group("default") { diff --git a/examples/ota-requestor-app/mbed/CMakeLists.txt b/examples/ota-requestor-app/mbed/CMakeLists.txt index 6a04c18aadc46c..50988c999f8b09 100644 --- a/examples/ota-requestor-app/mbed/CMakeLists.txt +++ b/examples/ota-requestor-app/mbed/CMakeLists.txt @@ -44,7 +44,7 @@ target_sources(${APP_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/main/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main/ZclCallbacks.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main/AppTask.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/main/MbedOTARequestorDriver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/main/OTARequestorDriverImpl.cpp ${MBED_COMMON}/util/LEDWidget.cpp ) diff --git a/examples/ota-requestor-app/mbed/main/AppTask.cpp b/examples/ota-requestor-app/mbed/main/AppTask.cpp index 6c8be6fea32bba..21edab8816d58d 100644 --- a/examples/ota-requestor-app/mbed/main/AppTask.cpp +++ b/examples/ota-requestor-app/mbed/main/AppTask.cpp @@ -31,10 +31,10 @@ #include "events/EventQueue.h" #ifdef CHIP_OTA_REQUESTOR -#include "MbedOTARequestorDriver.h" -#include -#include -#include +#include "OTARequestorDriverImpl.h" +#include +#include +#include #endif // CHIP_OTA_REQUESTOR static bool sIsWiFiStationProvisioned = false; @@ -92,30 +92,6 @@ int AppTask::Init() } } -#ifdef CHIP_OTA_REQUESTOR - // Initialize and interconnect the Requestor and Image Processor objects -- START - // Initialize the instance of the main Requestor Class - MbedOTARequestor * requestorCore = new MbedOTARequestor(OnAnnounceProviderCallback, OnProviderResponseCallback); - SetRequestorInstance(requestorCore); - - // Initialize an instance of the Requestor Driver - MbedOTARequestorDriver * requestorUser = new MbedOTARequestorDriver; - - // Connect the Requestor and Requestor Driver objects - requestorCore->SetOtaRequestorDriver(requestorUser); - - // Initialize the Downloader object - MbedOTADownloader * downloaderCore = new MbedOTADownloader(OnDownloadCompletedCallback); - SetDownloaderInstance(downloaderCore); - - // Initialize the Image Processor object - MbedOTAImageProcessor * downloaderUser = new MbedOTAImageProcessor; - - // Connect the Downloader and Image Processor objects - downloaderCore->SetImageProcessorDelegate(downloaderUser); - // Initialize and interconnect the Requestor and Image Processor objects -- END -#endif // CHIP_OTA_REQUESTOR - ConnectivityMgrImpl().StartWiFiManagement(); // Init ZCL Data Model and start server @@ -132,6 +108,57 @@ int AppTask::Init() // QR code will be used with CHIP Tool PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); +#ifdef CHIP_OTA_REQUESTOR + // Initialize the instance of the main Requestor Class + OTARequestor * requestor = new OTARequestor(); + if (requestor == nullptr) + { + ChipLogError(NotSpecified, "Create OTA Requestor core failed"); + return EXIT_FAILURE; + } + SetRequestorInstance(requestor); + + Server * server = &(Server::GetInstance()); + if (server == nullptr) + { + ChipLogError(NotSpecified, "Get server instance failed"); + return EXIT_FAILURE; + } + requestor->SetServerInstance(server); + + // Initialize an instance of the Requestor Driver + OTARequestorDriverImpl * requestorDriver = new OTARequestorDriverImpl; + if (requestorDriver == nullptr) + { + ChipLogError(NotSpecified, "Create OTA Requestor driver failed"); + return EXIT_FAILURE; + } + + // Connect the Requestor and Requestor Driver objects + requestor->SetOtaRequestorDriver(requestorDriver); + + // Initialize the Downloader object + BDXDownloader * downloader = new BDXDownloader(); + if (downloader == nullptr) + { + ChipLogError(NotSpecified, "Create OTA Downloader failed"); + return EXIT_FAILURE; + } + + // Initialize the Image Processor object + OTAImageProcessorImpl * imageProcessor = new OTAImageProcessorImpl; + if (imageProcessor == nullptr) + { + ChipLogError(NotSpecified, "Create OTA Image Processor failed"); + return EXIT_FAILURE; + } + + imageProcessor->SetOTADownloader(downloader); + downloader->SetImageProcessorDelegate(imageProcessor); + + requestor->SetBDXDownloader(downloader); +#endif // CHIP_OTA_REQUESTOR + return 0; } @@ -216,60 +243,60 @@ void AppTask::DispatchEvent(const AppEvent * aEvent) } } -#ifdef CHIP_OTA_REQUESTOR -void AppTask::OnOtaEventHandler(AppEvent * aEvent) -{ - switch (aEvent->Type) - { - case AppEvent::kEventType_ota_provider_announce: { - ChipLogProgress(NotSpecified, "OTA provider announce event"); - MbedOTARequestor * requestor = static_cast(GetRequestorInstance()); - requestor->ConnectProvider(); - break; - } - - case AppEvent::kEventType_ota_provider_response: { - ChipLogProgress(NotSpecified, "OTA provider response event"); - MbedOTADownloader * downloader = static_cast(GetDownloaderInstance()); - downloader->SetDownloadImageInfo(aEvent->OTAProviderResponseEvent.imageDatails->updateFileName); - downloader->BeginPrepareDownload(); - break; - } - case AppEvent::kEventType_ota_download_completed: - ChipLogProgress(NotSpecified, "OTA download completed event"); - ChipLogProgress(NotSpecified, "Download %.*s image size %ukB", - static_cast(aEvent->OTADownloadCompletedEvent.imageInfo->imageName.size()), - aEvent->OTADownloadCompletedEvent.imageInfo->imageName.data(), - (static_cast(aEvent->OTADownloadCompletedEvent.imageInfo->imageSize) / 1024u)); - break; - default: - ChipLogError(NotSpecified, "OTA event unknown"); - } -} - -void AppTask::OnAnnounceProviderCallback() -{ - AppEvent ota_announce_provider_event; - ota_announce_provider_event.Type = AppEvent::kEventType_ota_provider_announce; - ota_announce_provider_event.Handler = OnOtaEventHandler; - sAppTask.PostEvent(&ota_announce_provider_event); -} - -void AppTask::OnProviderResponseCallback(MbedOTARequestor::OTAUpdateDetails * updateDetails) -{ - AppEvent ota_provider_response_event; - ota_provider_response_event.Type = AppEvent::kEventType_ota_provider_response; - ota_provider_response_event.Handler = OnOtaEventHandler; - ota_provider_response_event.OTAProviderResponseEvent.imageDatails = updateDetails; - sAppTask.PostEvent(&ota_provider_response_event); -} - -void AppTask::OnDownloadCompletedCallback(MbedOTADownloader::ImageInfo * imageInfo) -{ - AppEvent ota_download_completed_event; - ota_download_completed_event.Type = AppEvent::kEventType_ota_download_completed; - ota_download_completed_event.Handler = OnOtaEventHandler; - ota_download_completed_event.OTADownloadCompletedEvent.imageInfo = imageInfo; - sAppTask.PostEvent(&ota_download_completed_event); -} -#endif \ No newline at end of file +// #ifdef CHIP_OTA_REQUESTOR +// void AppTask::OnOtaEventHandler(AppEvent * aEvent) +// { +// switch (aEvent->Type) +// { +// case AppEvent::kEventType_ota_provider_announce: { +// ChipLogProgress(NotSpecified, "OTA provider announce event"); +// MbedOTARequestor * requestor = static_cast(GetRequestorInstance()); +// requestor->ConnectProvider(); +// break; +// } + +// case AppEvent::kEventType_ota_provider_response: { +// ChipLogProgress(NotSpecified, "OTA provider response event"); +// MbedOTADownloader * downloader = static_cast(GetDownloaderInstance()); +// downloader->SetDownloadImageInfo(aEvent->OTAProviderResponseEvent.imageDatails->updateFileName); +// downloader->BeginPrepareDownload(); +// break; +// } +// case AppEvent::kEventType_ota_download_completed: +// ChipLogProgress(NotSpecified, "OTA download completed event"); +// ChipLogProgress(NotSpecified, "Download %.*s image size %ukB", +// static_cast(aEvent->OTADownloadCompletedEvent.imageInfo->imageName.size()), +// aEvent->OTADownloadCompletedEvent.imageInfo->imageName.data(), +// (static_cast(aEvent->OTADownloadCompletedEvent.imageInfo->imageSize) / 1024u)); +// break; +// default: +// ChipLogError(NotSpecified, "OTA event unknown"); +// } +// } + +// void AppTask::OnAnnounceProviderCallback() +// { +// AppEvent ota_announce_provider_event; +// ota_announce_provider_event.Type = AppEvent::kEventType_ota_provider_announce; +// ota_announce_provider_event.Handler = OnOtaEventHandler; +// sAppTask.PostEvent(&ota_announce_provider_event); +// } + +// void AppTask::OnProviderResponseCallback(MbedOTARequestor::OTAUpdateDetails * updateDetails) +// { +// AppEvent ota_provider_response_event; +// ota_provider_response_event.Type = AppEvent::kEventType_ota_provider_response; +// ota_provider_response_event.Handler = OnOtaEventHandler; +// ota_provider_response_event.OTAProviderResponseEvent.imageDatails = updateDetails; +// sAppTask.PostEvent(&ota_provider_response_event); +// } + +// void AppTask::OnDownloadCompletedCallback(MbedOTADownloader::ImageInfo * imageInfo) +// { +// AppEvent ota_download_completed_event; +// ota_download_completed_event.Type = AppEvent::kEventType_ota_download_completed; +// ota_download_completed_event.Handler = OnOtaEventHandler; +// ota_download_completed_event.OTADownloadCompletedEvent.imageInfo = imageInfo; +// sAppTask.PostEvent(&ota_download_completed_event); +// } +// #endif \ No newline at end of file diff --git a/examples/ota-requestor-app/mbed/main/MbedOTARequestorDriver.cpp b/examples/ota-requestor-app/mbed/main/OTARequestorDriverImpl.cpp similarity index 65% rename from examples/ota-requestor-app/mbed/main/MbedOTARequestorDriver.cpp rename to examples/ota-requestor-app/mbed/main/OTARequestorDriverImpl.cpp index 6f1437b900a821..edbee29e7db698 100644 --- a/examples/ota-requestor-app/mbed/main/MbedOTARequestorDriver.cpp +++ b/examples/ota-requestor-app/mbed/main/OTARequestorDriverImpl.cpp @@ -16,11 +16,22 @@ * limitations under the License. */ -#include +#include "OTARequestorDriverImpl.h" -bool MbedOTARequestorDriver::CheckImageDownloadAllowed() +namespace chip { + +bool OTARequestorDriverImpl::CheckImageDownloadAllowed() { return true; } -void MbedOTARequestorDriver::ImageDownloadComplete() {} +UserConsentAction OTARequestorDriverImpl::RequestUserConsent() +{ + return ImmediateYes; +} + +void OTARequestorDriverImpl::ImageDownloadComplete() {} + +void OTARequestorDriverImpl::NotifyUpdateStateChange(chip::UpdateStateEnum state) {} + +} // namespace chip \ No newline at end of file diff --git a/examples/ota-requestor-app/mbed/main/include/AppEvent.h b/examples/ota-requestor-app/mbed/main/include/AppEvent.h index 38ed3cd26c21f9..a65b98f69f0c6a 100644 --- a/examples/ota-requestor-app/mbed/main/include/AppEvent.h +++ b/examples/ota-requestor-app/mbed/main/include/AppEvent.h @@ -21,11 +21,6 @@ #include -#ifdef CHIP_OTA_REQUESTOR -#include -#include -#endif // CHIP_OTA_REQUESTOR - struct AppEvent; typedef void (*EventHandler)(AppEvent *); @@ -42,20 +37,5 @@ struct AppEvent uint16_t Type; -#ifdef CHIP_OTA_REQUESTOR - union - { - struct - { - MbedOTARequestor::OTAUpdateDetails * imageDatails; - } OTAProviderResponseEvent; - - struct - { - chip::MbedOTADownloader::ImageInfo * imageInfo; - } OTADownloadCompletedEvent; - }; -#endif // CHIP_OTA_REQUESTOR - EventHandler Handler; }; diff --git a/examples/ota-requestor-app/mbed/main/include/AppTask.h b/examples/ota-requestor-app/mbed/main/include/AppTask.h index 8254ef29f00e8d..772d19ed1f74e1 100644 --- a/examples/ota-requestor-app/mbed/main/include/AppTask.h +++ b/examples/ota-requestor-app/mbed/main/include/AppTask.h @@ -21,11 +21,6 @@ #include "AppEvent.h" -#ifdef CHIP_OTA_REQUESTOR -#include -#include -#endif - class AppTask { public: @@ -39,13 +34,13 @@ class AppTask void PostEvent(AppEvent * aEvent); void DispatchEvent(const AppEvent * event); -#ifdef CHIP_OTA_REQUESTOR - static void OnOtaEventHandler(AppEvent * aEvent); + // #ifdef CHIP_OTA_REQUESTOR + // static void OnOtaEventHandler(AppEvent * aEvent); - static void OnAnnounceProviderCallback(); - static void OnProviderResponseCallback(MbedOTARequestor::OTAUpdateDetails * updateDetails); - static void OnDownloadCompletedCallback(chip::MbedOTADownloader::ImageInfo * imageInfo); -#endif + // static void OnAnnounceProviderCallback(); + // static void OnProviderResponseCallback(MbedOTARequestor::OTAUpdateDetails * updateDetails); + // static void OnDownloadCompletedCallback(chip::MbedOTADownloader::ImageInfo * imageInfo); + // #endif static AppTask sAppTask; }; diff --git a/examples/ota-requestor-app/mbed/main/include/MbedOTARequestorDriver.h b/examples/ota-requestor-app/mbed/main/include/OTARequestorDriverImpl.h similarity index 73% rename from examples/ota-requestor-app/mbed/main/include/MbedOTARequestorDriver.h rename to examples/ota-requestor-app/mbed/main/include/OTARequestorDriverImpl.h index 3c2845046bba97..14b7d1552d20a3 100644 --- a/examples/ota-requestor-app/mbed/main/include/MbedOTARequestorDriver.h +++ b/examples/ota-requestor-app/mbed/main/include/OTARequestorDriverImpl.h @@ -24,9 +24,11 @@ #pragma once -#include "app/clusters/ota-requestor/OTARequestorDriver.h" +#include -class MbedOTARequestorDriver : public OTARequestorDriver +namespace chip { + +class OTARequestorDriverImpl : public OTARequestorDriver { public: // A call into the application logic to give it a chance to allow or stop the Requestor @@ -34,6 +36,15 @@ class MbedOTARequestorDriver : public OTARequestorDriver // to proceed, returning FALSE will abort the download process. bool CheckImageDownloadAllowed(); + // Application is directed to complete user consent: either return ImmediateYes/ImmediateNo + // without blocking or return Requested and call OTARequestor::OnUserConsent() later. + UserConsentAction RequestUserConsent(); + // Notify the application that the download is complete and the image can be applied void ImageDownloadComplete(); + + // Notify application of a change in the UpdateState attribute + void NotifyUpdateStateChange(chip::UpdateStateEnum state); }; + +} // namespace chip \ No newline at end of file diff --git a/examples/ota-requestor-app/mbed/mbed_app.json b/examples/ota-requestor-app/mbed/mbed_app.json index e72b92e10a7cff..48d1146f5785ec 100644 --- a/examples/ota-requestor-app/mbed/mbed_app.json +++ b/examples/ota-requestor-app/mbed/mbed_app.json @@ -18,8 +18,7 @@ "MXCRYPTO_DISABLED", "NL_ASSERT_LOG=NL_ASSERT_LOG_DEFAULT", "NL_ASSERT_EXPECT_FLAGS=NL_ASSERT_FLAG_LOG", - "WHD_PRINT_DISABLE", - "MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED" + "WHD_PRINT_DISABLE" ] } }, diff --git a/examples/shell/mbed/mbed_app.json b/examples/shell/mbed/mbed_app.json index c7281d23ee5fc2..1a6b662db9abcf 100644 --- a/examples/shell/mbed/mbed_app.json +++ b/examples/shell/mbed/mbed_app.json @@ -18,8 +18,7 @@ "MXCRYPTO_DISABLED", "NL_ASSERT_LOG=NL_ASSERT_LOG_DEFAULT", "NL_ASSERT_EXPECT_FLAGS=NL_ASSERT_FLAG_LOG", - "WHD_PRINT_DISABLE", - "MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED" + "WHD_PRINT_DISABLE" ] } }, diff --git a/src/platform/mbed/BUILD.gn b/src/platform/mbed/BUILD.gn index c5eed4ca9cb1c8..42c64ea78e0cbe 100644 --- a/src/platform/mbed/BUILD.gn +++ b/src/platform/mbed/BUILD.gn @@ -44,17 +44,13 @@ static_library("mbed") { if (chip_enable_openthread && chip_mdns == "platform") { sources += [ "../OpenThread/DnssdImpl.cpp" ] - deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] + public_deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] } if (chip_enable_ota_requestor) { sources += [ - "${chip_root}/src/app/clusters/ota-requestor/ClusterInterface.cpp", - "MbedOTADownloader.cpp", - "MbedOTAImageProcessor.cpp", - "MbedOTARequestor.cpp", + "OTAImageProcessorImpl.cpp", + "OTAImageProcessorImpl.h" ] - - include_dirs = [ "${chip_root}/zzz_generated/ota-requestor-app" ] } } diff --git a/src/platform/mbed/MbedOTADownloader.cpp b/src/platform/mbed/MbedOTADownloader.cpp deleted file mode 100644 index ce73a05911630c..00000000000000 --- a/src/platform/mbed/MbedOTADownloader.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* - * - * 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 "MbedOTADownloader.h" -#include -#include - -using namespace ::chip; -using namespace ::chip::bdx; - -static OTADownloader * sInstance; - -CHIP_ERROR MbedOTADownloader::BeginPrepareDownload() -{ - ChipLogProgress(SoftwareUpdate, "Begin download"); - - OperationalDeviceProxy * deviceProxy = Server::GetInstance().GetOperationalDeviceProxy(); - VerifyOrReturnError(deviceProxy != nullptr, CHIP_ERROR_INCORRECT_STATE); - - Messaging::ExchangeManager * exchangeMgr = deviceProxy->GetExchangeManager(); - Optional session = deviceProxy->GetSecureSession(); - Messaging::ExchangeContext * exchangeCtx = nullptr; - - if (exchangeMgr != nullptr && session.HasValue()) - { - exchangeCtx = exchangeMgr->NewContext(session.Value(), this); - } - - VerifyOrReturnError(exchangeCtx != nullptr, CHIP_ERROR_INTERNAL); - - mExchangeCtx = exchangeCtx; - - TransferSession::TransferInitData initOptions; - initOptions.TransferCtlFlags = TransferControlFlags::kReceiverDrive; - initOptions.MaxBlockSize = mBlockSize; - initOptions.FileDesLength = mImageInfo.imageName.size(); - initOptions.FileDesignator = reinterpret_cast(mImageInfo.imageName.data()); - - ReturnErrorOnFailure( - InitiateTransfer(&DeviceLayer::SystemLayer(), TransferRole::kReceiver, initOptions, System::Clock::Seconds16(20))); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR MbedOTADownloader::OnPreparedForDownload(CHIP_ERROR status) -{ - ChipLogProgress(SoftwareUpdate, "On Prepared For Download"); - - return CHIP_NO_ERROR; -} - -void MbedOTADownloader::HandleTransferSessionOutput(TransferSession::OutputEvent & event) -{ - using OutputEventType = TransferSession::OutputEventType; - using SendMessageFlags = Messaging::SendMessageFlags; - - CHIP_ERROR error = CHIP_NO_ERROR; - - if (event.EventType != OutputEventType::kNone) - { - ChipLogDetail(BDX, "OutputEvent type: %s", event.ToString(event.EventType)); - } - - switch (event.EventType) - { - case OutputEventType::kNone: - if (mIsTransferComplete) - { - ChipLogProgress(BDX, "Image file transfer complete"); - mTransfer.Reset(); - mIsTransferComplete = false; - - error = mImageProcessor->Finalize(); - if (error != CHIP_NO_ERROR) - { - ChipLogError(BDX, "Image processing finalize failed: %" CHIP_ERROR_FORMAT, error.Format()); - mImageProcessor->Abort(); - return; - } - - if (mDownloadCompletedCallback) - { - mDownloadCompletedCallback(&mImageInfo); - } - } - break; - case OutputEventType::kMsgToSend: { - Messaging::SendFlags flags; - flags.Set(SendMessageFlags::kFromInitiator, event.msgTypeData.MessageType == to_underlying(MessageType::ReceiveInit)); - flags.Set(SendMessageFlags::kExpectResponse, event.msgTypeData.MessageType != to_underlying(MessageType::BlockAckEOF)); - - VerifyOrReturn(mExchangeCtx != nullptr, ChipLogError(BDX, "Exchange context is null")); - error = - mExchangeCtx->SendMessage(event.msgTypeData.ProtocolId, event.msgTypeData.MessageType, std::move(event.MsgData), flags); - VerifyOrReturn(error == CHIP_NO_ERROR, ChipLogError(BDX, "SendMessage failed: %" CHIP_ERROR_FORMAT, error.Format())); - break; - } - case TransferSession::OutputEventType::kAcceptReceived: - ChipLogProgress(BDX, "Starting image file transfer size %lldB", static_cast(event.transferAcceptData.Length)); - error = mImageProcessor->PrepareDownload(); - if (error != CHIP_NO_ERROR) - { - ChipLogError(BDX, "Image processing prepare failed: %" CHIP_ERROR_FORMAT, error.Format()); - mTransfer.Reset(); - mImageProcessor->Abort(); - return; - } - - mImageInfo.imageSize = 0; - - error = mTransfer.PrepareBlockQuery(); - VerifyOrReturn(error == CHIP_NO_ERROR, ChipLogError(BDX, "PrepareBlockQuery failed: %" CHIP_ERROR_FORMAT, error.Format())); - - break; - case TransferSession::OutputEventType::kBlockReceived: { - ChipLogProgress(BDX, "Received %uB (total: %ukB)", static_cast(event.blockdata.Length), - static_cast(mTransfer.GetNumBytesProcessed()) / 1024u); - - ByteSpan data(event.blockdata.Data, event.blockdata.Length); - mImageProcessor->ProcessBlock(data); - if (error != CHIP_NO_ERROR) - { - ChipLogError(BDX, "Image processing process block failed: %" CHIP_ERROR_FORMAT, error.Format()); - mTransfer.Reset(); - ; - mImageProcessor->Abort(); - return; - } - - mImageInfo.imageSize += event.blockdata.Length; - - if (event.blockdata.IsEof) - { - error = mTransfer.PrepareBlockAck(); - VerifyOrReturn(error == CHIP_NO_ERROR, - ChipLogError(BDX, "PrepareBlockAck failed: %" CHIP_ERROR_FORMAT, error.Format())); - mIsTransferComplete = true; - } - else - { - error = mTransfer.PrepareBlockQuery(); - VerifyOrReturn(error == CHIP_NO_ERROR, - ChipLogError(BDX, "PrepareBlockQuery failed: %" CHIP_ERROR_FORMAT, error.Format())); - } - break; - } - case TransferSession::OutputEventType::kStatusReceived: - ChipLogError(BDX, "Received status %" PRIu16, to_underlying(event.statusData.statusCode)); - - if (event.statusData.statusCode != bdx::StatusCode::kNone) - { - mTransfer.Reset(); - mImageProcessor->Abort(); - } - break; - case TransferSession::OutputEventType::kInternalError: - ChipLogError(BDX, "Transfer stopped due to internal error"); - mTransfer.Reset(); - mImageProcessor->Abort(); - break; - case TransferSession::OutputEventType::kTransferTimeout: - ChipLogError(BDX, "Transfer timed out"); - mTransfer.Reset(); - mImageProcessor->Abort(); - break; - case TransferSession::OutputEventType::kInitReceived: - case TransferSession::OutputEventType::kAckReceived: - case TransferSession::OutputEventType::kQueryReceived: - case TransferSession::OutputEventType::kAckEOFReceived: - default: - ChipLogError(BDX, "Unexpected BDX event type: %" PRIu16, to_underlying(event.EventType)); - } -} - -void SetDownloaderInstance(OTADownloader * instance) -{ - sInstance = instance; -} - -OTADownloader * GetDownloaderInstance() -{ - return sInstance; -} diff --git a/src/platform/mbed/MbedOTADownloader.h b/src/platform/mbed/MbedOTADownloader.h deleted file mode 100644 index 9cb0857259571d..00000000000000 --- a/src/platform/mbed/MbedOTADownloader.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * 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. - */ - -/* This file contains the declarations for the OTADownloader class which - * abstracts the image download functionality from the particular protocol - * used for it. - * Applications and platforms implementing the OTA Requestor functionality - * must include this file - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace chip { - -// A class that abstracts the image download functionality from the particular -// protocol used for that (BDX or possibly HTTPS) -class MbedOTADownloader : public bdx::Initiator, public OTADownloader -{ -public: - struct ImageInfo - { - MutableCharSpan imageName; - size_t imageSize; - }; - -private: - typedef void (*DownloadCompletedCallback)(ImageInfo *); - -public: - MbedOTADownloader(DownloadCompletedCallback downloadCompletedCallback = nullptr) - { - mDownloadCompletedCallback = downloadCompletedCallback; - } - - // Application calls this method to direct OTADownloader to begin the download - CHIP_ERROR BeginPrepareDownload(); - - // Platform calls this method upon the completion of PrepareDownload() processing - CHIP_ERROR OnPreparedForDownload(CHIP_ERROR status); - - // Should be called when it has been determined that the download has timed out. - void OnDownloadTimeout() {} - - // Not all download protocols will be able to close gracefully from the receiver side. - // The reason parameter should be used to indicate if this is a graceful end or a forceful abort. - void EndDownload(CHIP_ERROR reason = CHIP_NO_ERROR) {} - - void SetDownloadImageInfo(MutableCharSpan & imageName); - -private: - // inherited from bdx::Endpoint - void HandleTransferSessionOutput(bdx::TransferSession::OutputEvent & event); - - bool mIsTransferComplete = false; - - ImageInfo mImageInfo; - - static const uint16_t mBlockSize = 1024; - - DownloadCompletedCallback mDownloadCompletedCallback; -}; - -inline void MbedOTADownloader::SetDownloadImageInfo(MutableCharSpan & imageName) -{ - mImageInfo.imageName = imageName; -} - -} // namespace chip - -void SetDownloaderInstance(chip::OTADownloader * instance); - -chip::OTADownloader * GetDownloaderInstance(); diff --git a/src/platform/mbed/MbedOTAImageProcessor.cpp b/src/platform/mbed/MbedOTAImageProcessor.cpp deleted file mode 100644 index 73b445ac81febb..00000000000000 --- a/src/platform/mbed/MbedOTAImageProcessor.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * 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 "MbedOTAImageProcessor.h" -#include - -using namespace ::chip; - -CHIP_ERROR MbedOTAImageProcessor::PrepareDownload() -{ - ChipLogProgress(SoftwareUpdate, "Prepare download"); - return CHIP_NO_ERROR; -} - -CHIP_ERROR MbedOTAImageProcessor::ProcessBlock(ByteSpan & data) -{ - ChipLogProgress(SoftwareUpdate, "Process block"); - return CHIP_NO_ERROR; -} - -CHIP_ERROR MbedOTAImageProcessor::Finalize() -{ - ChipLogProgress(SoftwareUpdate, "Finalize"); - return CHIP_NO_ERROR; -} - -CHIP_ERROR MbedOTAImageProcessor::Abort() -{ - ChipLogProgress(SoftwareUpdate, "Abort"); - return CHIP_NO_ERROR; -}; diff --git a/src/platform/mbed/MbedOTAImageProcessor.h b/src/platform/mbed/MbedOTAImageProcessor.h deleted file mode 100644 index a4f149898b0aa7..00000000000000 --- a/src/platform/mbed/MbedOTAImageProcessor.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * 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. - */ - -/* This file contains the declarations for OTAImageProcessor, a platform-agnostic - * interface for processing downloaded chunks of OTA image data. - * Each platform should provide an implementation of this interface. - */ - -#pragma once - -#include -#include -#include - -namespace chip { - -class MbedOTAImageProcessor : public OTAImageProcessorInterface -{ -public: - // Open file, find block of space in persistent memory, or allocate a buffer, etc. - CHIP_ERROR PrepareDownload(); - - // Must not be a blocking call to support cases that require IO to elements such as // external peripherals/radios - CHIP_ERROR ProcessBlock(ByteSpan & data); - - // Close file, close persistent storage, etc - CHIP_ERROR Finalize(); - - // Clean up the download which could mean erasing everything that was written, - // releasing buffers, etc. - CHIP_ERROR Abort(); -}; - -} // namespace chip diff --git a/src/platform/mbed/MbedOTARequestor.cpp b/src/platform/mbed/MbedOTARequestor.cpp deleted file mode 100644 index dca820f11b0e9b..00000000000000 --- a/src/platform/mbed/MbedOTARequestor.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* - * - * 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 "MbedOTARequestor.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -using chip::DeviceProxy; -using chip::EndpointId; -using chip::FabricIndex; -using chip::NodeId; -using chip::OnDeviceConnected; -using chip::OnDeviceConnectionFailure; -using chip::PeerId; -using chip::Server; -using chip::VendorId; -using chip::Callback::Callback; -using chip::Inet::IPAddress; -using chip::System::Layer; -using chip::Transport::PeerAddress; -using namespace ::chip::app::Clusters::OtaSoftwareUpdateProvider::Commands; -using namespace ::chip::DeviceLayer; -using namespace ::chip::Inet; - -static OTARequestorInterface * sInstance; - -constexpr const char gRequestorLocation[] = { 'U', 'S' }; -constexpr EmberAfOTADownloadProtocol gRequestorProtocols[] = { EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS }; -constexpr chip::EndpointId gOtaProviderEndpoint = 0; -constexpr bool gRequestorCanConsent = false; - -static void OnProviderConnected(void * context, chip::OperationalDeviceProxy * deviceProxy); -static void OnProviderConnectionFailure(void * context, chip::NodeId deviceId, CHIP_ERROR error); - -static void -OnQueryImageResponse(void * context, - const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::DecodableType & response); -static void OnQueryImageFailure(void * context, EmberAfStatus status); - -static Callback mOnConnectedCallback(OnProviderConnected, nullptr); -static Callback mOnConnectionFailureCallback(OnProviderConnectionFailure, nullptr); - -MbedOTARequestor::MbedOTARequestor(AnnounceProviderCallback announceProviderCallback = nullptr, - ProviderResponseCallback providerResponseCallback = nullptr) -{ - mProviderNodeId = chip::kUndefinedNodeId; - mProviderFabricIndex = chip::kUndefinedFabricIndex; - - mAnnounceProviderCallback = announceProviderCallback; - mProviderResponseCallback = providerResponseCallback; - - mUpdateDetails.updateVersionString = chip::MutableCharSpan(mUpdateVersion, kVersionBufLen); - mUpdateDetails.updateFileName = chip::MutableCharSpan(mUpdateFileName, kFileNameBufLen); - mUpdateDetails.updateToken = chip::MutableByteSpan(mUpdateToken, kTokenBufLen); -} - -chip::CharSpan MbedOTARequestor::GetFileNameFromURI(chip::CharSpan imageURI) -{ - constexpr char delimiter = '/'; - - char * ptr = strrchr(imageURI.data(), delimiter); - - if (ptr != nullptr) - { - size_t offset = ptr - imageURI.data() + 1; - imageURI = imageURI.SubSpan(offset, imageURI.size() - offset); - } - - return imageURI; -} - -EmberAfStatus MbedOTARequestor::HandleAnnounceOTAProvider( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) -{ - if (commandObj == nullptr) - { - ChipLogError(SoftwareUpdate, "Cannot access get FabricIndex"); - return EMBER_ZCL_STATUS_FAILURE; - } - - mProviderNodeId = commandData.providerLocation; - mProviderFabricIndex = commandObj->GetAccessingFabricIndex(); - mAnnouncementReason = commandData.announcementReason; - IPAddress ipAddr; - IPAddress::FromString(reinterpret_cast(commandData.metadataForNode.Value().data()), - commandData.metadataForNode.Value().size(), ipAddr); - SetIpAddress(ipAddr); - - char strIpAddr[INET6_ADDRSTRLEN]; - ipAddr.ToString(strIpAddr); - ChipLogProgress(SoftwareUpdate, "OTA Requestor received AnnounceOTAProvider"); - ChipLogProgress(SoftwareUpdate, " FabricIndex: %" PRIu8, mProviderFabricIndex); - ChipLogProgress(SoftwareUpdate, " ProviderNodeID: %" PRIu64 " (0x%" PRIX64 ")", mProviderNodeId, mProviderNodeId); - ChipLogProgress(SoftwareUpdate, " VendorID: %" PRIu16 " (0x%" PRIX16 ")", commandData.vendorId, commandData.vendorId); - ChipLogProgress(SoftwareUpdate, " ProviderIP: %s", strIpAddr); - ChipLogProgress(SoftwareUpdate, " AnnouncementReason: %" PRIu8, mAnnouncementReason); - - if (mAnnounceProviderCallback) - { - mAnnounceProviderCallback(); - } - - return EMBER_ZCL_STATUS_SUCCESS; -} - -bool MbedOTARequestor::HandleQueryImageResponse(void * context, uint8_t status, uint32_t delayedActionTime, chip::CharSpan imageURI, - uint32_t softwareVersion, chip::CharSpan softwareVersionString, - chip::ByteSpan updateToken, bool userConsentNeeded, - chip::ByteSpan metadataForRequestor) -{ - switch (status) - { - case EMBER_ZCL_OTA_QUERY_STATUS_UPDATE_AVAILABLE: - ChipLogProgress(SoftwareUpdate, "Update available"); - break; - case EMBER_ZCL_OTA_QUERY_STATUS_BUSY: - ChipLogProgress(SoftwareUpdate, "OTA provider busy"); - return false; - case EMBER_ZCL_OTA_QUERY_STATUS_NOT_AVAILABLE: - ChipLogProgress(SoftwareUpdate, "Update not available"); - return false; - } - - ChipLogProgress(SoftwareUpdate, " Image URI: %.*s", static_cast(imageURI.size()), imageURI.data()); - ChipLogProgress(SoftwareUpdate, " Version: %lu name: %.*s", softwareVersion, static_cast(softwareVersionString.size()), - softwareVersionString.data()); - - mUpdateDetails.updateVersion = softwareVersion; - memcpy((void *) mUpdateDetails.updateVersionString.begin(), softwareVersionString.data(), softwareVersionString.size()); - mUpdateDetails.updateVersionString.reduce_size(softwareVersionString.size()); - auto fileName = GetFileNameFromURI(imageURI); - memcpy((void *) mUpdateDetails.updateFileName.begin(), fileName.data(), fileName.size()); - mUpdateDetails.updateFileName.reduce_size(fileName.size()); - memcpy((void *) mUpdateDetails.updateToken.begin(), updateToken.data(), updateToken.size()); - mUpdateDetails.updateToken.reduce_size(updateToken.size()); - - ChipLogProgress(SoftwareUpdate, " Image name: %.*s", static_cast(mUpdateDetails.updateFileName.size()), - mUpdateDetails.updateFileName.data()); - - if (mProviderResponseCallback) - { - mProviderResponseCallback(&mUpdateDetails); - } - return false; -} - -void MbedOTARequestor::ConnectProvider() -{ - chip::NodeId peerNodeId = mProviderNodeId; - chip::FabricIndex peerFabricIndex = mProviderFabricIndex; - - Server * server = &(Server::GetInstance()); - chip::FabricInfo * fabric = server->GetFabricTable().FindFabricWithIndex(peerFabricIndex); - if (fabric == nullptr) - { - ChipLogError(SoftwareUpdate, "Did not find fabric for index %d", peerFabricIndex); - return; - } - - chip::DeviceProxyInitParams initParams = { - .sessionManager = &(server->GetSecureSessionManager()), - .exchangeMgr = &(server->GetExchangeManager()), - .idAllocator = &(server->GetSessionIDAllocator()), - .fabricInfo = fabric, - .imDelegate = chip::Platform::New(), - }; - - chip::OperationalDeviceProxy * operationalDeviceProxy = - chip::Platform::New(initParams, fabric->GetPeerIdForNode(peerNodeId)); - if (operationalDeviceProxy == nullptr) - { - ChipLogError(SoftwareUpdate, "Failed in creating an instance of OperationalDeviceProxy"); - return; - } - - server->SetOperationalDeviceProxy(operationalDeviceProxy); - - // Explicitly calling UpdateDeviceData() should not be needed once OperationalDeviceProxy can resolve IP address from node - // ID and fabric index - PeerAddress addr = PeerAddress::UDP(mProviderIpAddress, CHIP_PORT); - operationalDeviceProxy->UpdateDeviceData(addr, operationalDeviceProxy->GetMRPConfig()); - - CHIP_ERROR err = operationalDeviceProxy->Connect(&mOnConnectedCallback, &mOnConnectionFailureCallback); - if (err != CHIP_NO_ERROR) - { - ChipLogError(SoftwareUpdate, "Cannot establish connection to peer device: %" CHIP_ERROR_FORMAT, err.Format()); - } -} - -void OnProviderConnected(void * context, chip::OperationalDeviceProxy * deviceProxy) -{ - ChipLogProgress(SoftwareUpdate, "OnProviderConnected"); - chip::Controller::OtaSoftwareUpdateProviderCluster cluster; - - CHIP_ERROR err = cluster.Associate(deviceProxy, gOtaProviderEndpoint); - if (err != CHIP_NO_ERROR) - { - ChipLogError(SoftwareUpdate, "Associate() failed: %" CHIP_ERROR_FORMAT, err.Format()); - return; - } - - // Send QueryImage command - uint16_t vendorId = 0; - uint16_t productId = 0; - uint16_t hardwareVersion = 0; - uint16_t softwareVersion = 0; - - ConfigurationMgr().GetVendorId(vendorId); - ConfigurationMgr().GetProductId(productId); - ConfigurationMgr().GetHardwareVersion(hardwareVersion); - ConfigurationMgr().GetSoftwareVersion(softwareVersion); - - QueryImage::Type request; - request.vendorId = static_cast(vendorId); - request.productId = productId; - request.softwareVersion = softwareVersion; - request.protocolsSupported = gRequestorProtocols; - request.hardwareVersion.Emplace(hardwareVersion); - request.location.Emplace(gRequestorLocation); - request.requestorCanConsent.SetValue(gRequestorCanConsent); - err = cluster.InvokeCommand(request, /* context = */ nullptr, OnQueryImageResponse, OnQueryImageFailure); - if (err != CHIP_NO_ERROR) - { - ChipLogError(SoftwareUpdate, "QueryImage() failed: %" CHIP_ERROR_FORMAT, err.Format()); - } -} - -void OnProviderConnectionFailure(void * context, NodeId deviceId, CHIP_ERROR error) -{ - ChipLogError(SoftwareUpdate, "Provider connection failure 0x%" PRIX64 ": %" CHIP_ERROR_FORMAT, deviceId, error.Format()); -} - -void OnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response) -{ - ChipLogProgress(SoftwareUpdate, "OnQueryImageResponse"); - - MbedOTARequestor * requestor = static_cast(GetRequestorInstance()); - - requestor->HandleQueryImageResponse(context, response.status, response.delayedActionTime.ValueOr(0), - response.imageURI.ValueOr({}), response.softwareVersion.ValueOr(0), - response.softwareVersionString.ValueOr({}), response.updateToken.ValueOr({}), - response.userConsentNeeded.ValueOr(false), response.metadataForRequestor.ValueOr({})); -} - -void OnQueryImageFailure(void * context, EmberAfStatus status) -{ - ChipLogError(SoftwareUpdate, "QueryImage failure %" PRIu8, status); -} - -OTARequestorInterface * GetRequestorInstance() -{ - return sInstance; -} - -void SetRequestorInstance(OTARequestorInterface * instance) -{ - sInstance = instance; -} diff --git a/src/platform/mbed/MbedOTARequestor.h b/src/platform/mbed/MbedOTARequestor.h deleted file mode 100644 index 68f715c0fd70c3..00000000000000 --- a/src/platform/mbed/MbedOTARequestor.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * 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 -#include -#include -#include -#include -#include -#include - -#include "events/EventQueue.h" -#include - -class MbedOTARequestor : public OTARequestorInterface -{ - static constexpr uint8_t kVersionBufLen = 32; - char mUpdateVersion[kVersionBufLen]; - - static constexpr size_t kFileNameBufLen = 256; - char mUpdateFileName[kFileNameBufLen]; // null-terminated - - static constexpr uint8_t kTokenBufLen = 32; - uint8_t mUpdateToken[kTokenBufLen]; - -public: - struct OTAUpdateDetails - { - uint32_t updateVersion; - chip::MutableCharSpan updateVersionString; - chip::MutableCharSpan updateFileName; - chip::MutableByteSpan updateToken; - }; - -private: - typedef void (*AnnounceProviderCallback)(); - typedef void (*ProviderResponseCallback)(OTAUpdateDetails * updateDetails); - -public: - MbedOTARequestor(AnnounceProviderCallback announceProviderCallback, ProviderResponseCallback providerResponseCallback); - - // Handler for the AnnounceOTAProvider command - EmberAfStatus HandleAnnounceOTAProvider( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData); - - // Handler for the QueryImageResponse command - bool HandleQueryImageResponse(void * context, uint8_t status, uint32_t delayedActionTime, chip::CharSpan imageURI, - uint32_t softwareVersion, chip::CharSpan softwareVersionString, chip::ByteSpan updateToken, - bool userConsentNeeded, chip::ByteSpan metadataForRequestor); - // Application directs the Requestor to start the Image Query process - // and download the new image if available - void TriggerImmediateQuery() {} - - // A setter for the delegate class pointer - void SetOtaRequestorDriver(OTARequestorDriver * driver); - - // Application directs the Requestor to abort any processing related to - // the image update - void AbortImageUpdate() {} - - void ConnectProvider(); - - // Temporary until IP address resolution is implemented in the Exchange Layer - void SetIpAddress(chip::Inet::IPAddress IpAddress) { mProviderIpAddress = IpAddress; } - -private: - OTAUpdateDetails mUpdateDetails; - - chip::NodeId mProviderNodeId; - chip::FabricIndex mProviderFabricIndex; - EmberAfOTAAnnouncementReason mAnnouncementReason; - chip::Inet::IPAddress mProviderIpAddress; - - AnnounceProviderCallback mAnnounceProviderCallback; - ProviderResponseCallback mProviderResponseCallback; - - OTARequestorDriver * mOtaRequestorDriver; - - chip::CharSpan GetFileNameFromURI(chip::CharSpan imageURI); -}; - -inline void MbedOTARequestor::SetOtaRequestorDriver(OTARequestorDriver * driver) -{ - mOtaRequestorDriver = driver; -} diff --git a/src/platform/mbed/OTAImageProcessorImpl.cpp b/src/platform/mbed/OTAImageProcessorImpl.cpp new file mode 100644 index 00000000000000..af4135b4499c4d --- /dev/null +++ b/src/platform/mbed/OTAImageProcessorImpl.cpp @@ -0,0 +1,181 @@ +/* + * + * 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 "OTAImageProcessorImpl.h" +#include +#include + +using namespace ::chip::DeviceLayer::Internal; + +namespace chip { + +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; +}; + +CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) +{ + ChipLogProgress(SoftwareUpdate, "Process block"); + 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; + } + + // TODO mbed partition prepare + imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); +} + +void OTAImageProcessorImpl::HandleFinalize(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + + // TODO finalize image download + imageProcessor->ReleaseBlock(); + // ChipLogProgress(SoftwareUpdate, "OTA image downloaded to offset 0x%x", imageProcessor->mOTAUpdatePartition->address); +} + +void OTAImageProcessorImpl::HandleAbort(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + + // TODO abort image download + 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; + } + // TODO write image chunk + imageProcessor->mParams.downloadedBytes += imageProcessor->mBlock.size(); + imageProcessor->mDownloader->FetchNextData(); +} + +void OTAImageProcessorImpl::HandleApply(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + // TODO apply update image +} + +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; +} + +} // namespace chip \ No newline at end of file diff --git a/src/platform/mbed/OTAImageProcessorImpl.h b/src/platform/mbed/OTAImageProcessorImpl.h new file mode 100644 index 00000000000000..ff4ca59504c611 --- /dev/null +++ b/src/platform/mbed/OTAImageProcessorImpl.h @@ -0,0 +1,81 @@ +/* + * + * 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. + */ + +/* This file contains the declarations for OTAImageProcessor, a platform-agnostic + * interface for processing downloaded chunks of OTA image data. + * Each platform should provide an implementation of this interface. + */ + +#pragma once + +#include +#include +#include +#include + +namespace chip { + +class OTAImageProcessorImpl : public OTAImageProcessorInterface +{ +public: + /** + * Called to prepare for an OTA image download. This may include but not limited to opening the file, finding a block of space + * in persistent memory, and allocating a buffer. This must not be a blocking call. + */ + CHIP_ERROR PrepareDownload(); + + /** + * Called when the OTA image download process has completed. This may include but not limited to closing the file and persistent + * storage. This must not be a blocking call. + */ + CHIP_ERROR Finalize(); + + /** + * Called when the OTA image should be applied. + */ + CHIP_ERROR Apply(); + + /** + * Called when the OTA image download process is incomplete or cannot continue. This may include but not limited to erasing + * everything that has been written and releasing buffers. This must not be a blocking call. + */ + CHIP_ERROR Abort(); + + /** + * Called to process a downloaded block of data. This must not be a blocking call to support cases that require IO to elements + * such as external peripherals/radios. This must not be a blocking call. + */ + CHIP_ERROR ProcessBlock(ByteSpan & block); + + void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }; + +private: + 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); + + CHIP_ERROR SetBlock(ByteSpan & block); + CHIP_ERROR ReleaseBlock(); + + OTADownloader * mDownloader = nullptr; + MutableByteSpan mBlock; +}; + +} // namespace chip