blob: d625d18a4201f55a3825b161157771368035389f [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_DRIVER_FAKE_PLATFORM_DEVICE_CPP_FAKE_PDEV_H_
#define LIB_DRIVER_FAKE_PLATFORM_DEVICE_CPP_FAKE_PDEV_H_
#include <fidl/fuchsia.hardware.platform.device/cpp/wire_test_base.h>
#include <fidl/fuchsia.hardware.power/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/driver/platform-device/cpp/pdev.h>
#include <lib/mmio/mmio.h>
#include <map>
#if FUCHSIA_API_LEVEL_AT_LEAST(HEAD)
namespace fdf_fake {
using Mmio = std::variant<fdf::PDev::MmioInfo, fdf::MmioBuffer>;
class FakePDev final : public fidl::WireServer<fuchsia_hardware_platform_device::Device> {
public:
// Allows for `std::string_view`'s to be used when searching an unordered map that uses
// `std::string` as its key.
struct StringHash {
using hash_type = std::hash<std::string_view>;
using is_transparent = void;
std::size_t operator()(const char* str) const { return hash_type{}(str); }
std::size_t operator()(std::string_view str) const { return hash_type{}(str); }
std::size_t operator()(std::string const& str) const { return hash_type{}(str); }
};
using MetadataMap =
std::unordered_map<std::string, std::vector<uint8_t>, StringHash, std::equal_to<>>;
using ResourceNamesMap = std::unordered_map<std::string, uint32_t, StringHash, std::equal_to<>>;
// Use `ResourceNamesMap` instead.
// TODO(b/394855439): Remove type once no longer referenced.
using InterruptNamesMap = ResourceNamesMap;
struct Config final {
// If true, a bti will be generated lazily if it does not exist.
bool use_fake_bti = false;
// If true, a smc will be generated lazily if it does not exist.
bool use_fake_smc = false;
// If true, an irq will be generated lazily if it does not exist.
bool use_fake_irq = false;
// Key is the index of the mmio.
std::map<uint32_t, Mmio> mmios;
// Maps the name of an mmio to the index of the mmio. The key is the name of the mmio and the
// value is the index of the mmio.
ResourceNamesMap mmio_names;
// Key is the index of the interrupt.
std::map<uint32_t, zx::interrupt> irqs;
// Maps the name of an interrupt to the index of the interrupt. The key is the name of the
// interrupt and the value is the index of the interrupt.
ResourceNamesMap irq_names;
std::map<uint32_t, zx::bti> btis;
// Maps the name of an bti to the index of the bti. The key is the name of the
// bti and the value is the index of the bti.
ResourceNamesMap bti_names;
std::map<uint32_t, zx::resource> smcs;
std::optional<fdf::PDev::DeviceInfo> device_info;
std::optional<fdf::PDev::BoardInfo> board_info;
#if FUCHSIA_API_LEVEL_AT_LEAST(HEAD)
std::vector<fuchsia_hardware_power::PowerElementConfiguration> power_elements;
#endif
};
FakePDev() = default;
FakePDev(const FakePDev&) = delete;
FakePDev& operator=(const FakePDev&) = delete;
FakePDev(FakePDev&&) = delete;
FakePDev& operator=(FakePDev&&) = delete;
fuchsia_hardware_platform_device::Service::InstanceHandler GetInstanceHandler(
async_dispatcher_t* dispatcher = nullptr) {
return fuchsia_hardware_platform_device::Service::InstanceHandler({
.device = binding_group_.CreateHandler(
this, dispatcher ? dispatcher : async_get_default_dispatcher(),
fidl::kIgnoreBindingClosure),
});
}
zx_status_t Connect(fidl::ServerEnd<fuchsia_hardware_platform_device::Device> request) {
binding_group_.AddBinding(async_get_default_dispatcher(), std::move(request), this,
fidl::kIgnoreBindingClosure);
return ZX_OK;
}
zx_status_t SetConfig(Config&& config) {
config_ = std::move(config);
return ZX_OK;
}
void set_metadata(MetadataMap metadata) { metadata_ = std::move(metadata); }
template <typename FidlType>
zx_status_t AddFidlMetadata(std::string metadata_id, const FidlType& metadata) {
static_assert(fidl::IsFidlType<FidlType>::value, "|FidlType| must be a FIDL domain object.");
static_assert(!fidl::IsResource<FidlType>::value,
"|FidlType| cannot be a resource type. Resources cannot be persisted.");
fit::result encoded_metadata = fidl::Persist(metadata);
if (encoded_metadata.is_error()) {
return encoded_metadata.error_value().status();
}
metadata_.insert({std::move(metadata_id), std::move(encoded_metadata.value())});
return ZX_OK;
}
private:
void GetMmioById(GetMmioByIdRequestView request, GetMmioByIdCompleter::Sync& completer) override;
void GetMmioByName(GetMmioByNameRequestView request,
GetMmioByNameCompleter::Sync& completer) override;
void GetInterruptById(GetInterruptByIdRequestView request,
GetInterruptByIdCompleter::Sync& completer) override;
void GetInterruptByName(GetInterruptByNameRequestView request,
GetInterruptByNameCompleter::Sync& completer) override;
void GetBtiById(GetBtiByIdRequestView request, GetBtiByIdCompleter::Sync& completer) override;
void GetBtiByName(GetBtiByNameRequestView request,
GetBtiByNameCompleter::Sync& completer) override;
void GetSmcById(GetSmcByIdRequestView request, GetSmcByIdCompleter::Sync& completer) override;
void GetSmcByName(GetSmcByNameRequestView request,
GetSmcByNameCompleter::Sync& completer) override;
void GetNodeDeviceInfo(GetNodeDeviceInfoCompleter::Sync& completer) override;
void GetBoardInfo(GetBoardInfoCompleter::Sync& completer) override;
void GetPowerConfiguration(GetPowerConfigurationCompleter::Sync& completer) override;
void GetMetadata(GetMetadataRequestView request, GetMetadataCompleter::Sync& completer) override;
void handle_unknown_method(
fidl::UnknownMethodMetadata<fuchsia_hardware_platform_device::Device> metadata,
fidl::UnknownMethodCompleter::Sync& completer) override;
zx::result<zx::interrupt> GetInterruptById(uint32_t index);
zx::result<zx::bti> GetBtiById(uint32_t index);
zx::result<fuchsia_hardware_platform_device::wire::Mmio> GetMmioById(uint32_t index,
fidl::AnyArena& arena);
Config config_;
fidl::ServerBindingGroup<fuchsia_hardware_platform_device::Device> binding_group_;
// Key is the ID of the metadata and value is the encoded metadata.
MetadataMap metadata_;
};
} // namespace fdf_fake
#endif // FUCHSIA_API_LEVEL_AT_LEAST(HEAD)
#endif // LIB_DRIVER_FAKE_PLATFORM_DEVICE_CPP_FAKE_PDEV_H_