blob: 121b59c027a704397304a4d6876163d5180209fe [file] [log] [blame]
/*
*
* 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 a definition for a class that implements OTADownloader and downloads CHIP OTA images using the BDX protocol.
* It should not execute any logic that is application specific.
*/
// TODO: unit tests
#pragma once
#include "OTADownloader.h"
#include <app-common/zap-generated/cluster-objects.h>
#include <lib/core/CHIPError.h>
#include <protocols/bdx/BdxTransferSession.h>
#include <system/SystemPacketBuffer.h>
#include <transport/raw/MessageHeader.h>
namespace chip {
class BDXDownloader : public chip::OTADownloader
{
public:
// A delegate for passing messages to/from BDXDownloader and some messaging layer. This is mainly to make BDXDownloader more
// easily unit-testable.
class MessagingDelegate
{
public:
virtual CHIP_ERROR SendMessage(const chip::bdx::TransferSession::OutputEvent & msgEvent) = 0;
virtual ~MessagingDelegate() {}
};
class StateDelegate
{
public:
// Handle download state change
virtual void OnDownloadStateChanged(State state, app::Clusters::OtaSoftwareUpdateRequestor::OTAChangeReasonEnum reason) = 0;
// Handle update progress change
virtual void OnUpdateProgressChanged(app::DataModel::Nullable<uint8_t> percent) = 0;
virtual ~StateDelegate() = default;
};
// To be called when there is an incoming message to handle (of any protocol type)
void OnMessageReceived(const chip::PayloadHeader & payloadHeader, chip::System::PacketBufferHandle msg);
void SetMessageDelegate(MessagingDelegate * delegate) { mMsgDelegate = delegate; }
void SetStateDelegate(StateDelegate * delegate) { mStateDelegate = delegate; }
// Initialize a BDX transfer session but will not proceed until OnPreparedForDownload() is called.
CHIP_ERROR SetBDXParams(const chip::bdx::TransferSession::TransferInitData & bdxInitData, System::Clock::Timeout timeout);
// OTADownloader Overrides
CHIP_ERROR BeginPrepareDownload() override;
CHIP_ERROR OnPreparedForDownload(CHIP_ERROR status) override;
void OnDownloadTimeout() override;
// BDX does not provide a mechanism for the driver of a transfer to gracefully end the exchange, so it will abort the transfer
// instead.
void EndDownload(CHIP_ERROR reason = CHIP_NO_ERROR) override;
CHIP_ERROR FetchNextData() override;
// TODO: override SkipData
System::Clock::Timeout GetTimeout();
// If True, there's been a timeout in the transfer as measured by no download progress after 'mTimeout' seconds.
// If False, there's been progress in the transfer.
bool HasTransferTimedOut();
private:
void PollTransferSession();
void CleanupOnError(app::Clusters::OtaSoftwareUpdateRequestor::OTAChangeReasonEnum reason);
CHIP_ERROR HandleBdxEvent(const chip::bdx::TransferSession::OutputEvent & outEvent);
void SetState(State state, app::Clusters::OtaSoftwareUpdateRequestor::OTAChangeReasonEnum reason);
void Reset();
chip::bdx::TransferSession mBdxTransfer;
MessagingDelegate * mMsgDelegate = nullptr;
StateDelegate * mStateDelegate = nullptr;
// Timeout value in seconds to abort the download if there's no progress in the transfer session.
System::Clock::Timeout mTimeout = System::Clock::kZero;
// Tracks the last block counter used during the transfer session as of the previous check.
uint32_t mPrevBlockCounter = 0;
};
} // namespace chip