blob: 6f41e5656dc08a52881750111fa300aa94d579b0 [file] [log] [blame] [edit]
// Copyright 2021 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 SRC_DEVICES_TPM_DRIVERS_TPM_TPM_H_
#define SRC_DEVICES_TPM_DRIVERS_TPM_TPM_H_
#include <fidl/fuchsia.hardware.tpmimpl/cpp/wire.h>
#include <fidl/fuchsia.tpm/cpp/wire.h>
#include <lib/ddk/device.h>
#include <lib/inspect/cpp/inspector.h>
#include <condition_variable>
#include <ddktl/device.h>
#include "src/devices/tpm/drivers/tpm/commands.h"
namespace tpm {
constexpr uint32_t kTpmVendorPrefix = (1 << 29);
using TpmCommandCallback = fit::function<void(zx_status_t, TpmResponseHeader*)>;
struct TpmCommand {
std::unique_ptr<TpmCmdHeader> cmd;
TpmCommandCallback handler;
};
class TpmDevice;
using DeviceType = ddk::Device<TpmDevice, ddk::Initializable, ddk::Suspendable, ddk::Unbindable,
ddk::Messageable<fuchsia_tpm::TpmDevice>::Mixin>;
class TpmDevice : public DeviceType {
public:
TpmDevice(zx_device_t* parent, fidl::WireSyncClient<fuchsia_hardware_tpmimpl::TpmImpl> client)
: DeviceType(parent), tpm_(std::move(client)) {}
static zx_status_t Create(void* ctx, zx_device_t* parent);
// DDK mixins
void DdkInit(ddk::InitTxn txn);
void DdkRelease() {
if (command_thread_.joinable()) {
command_thread_.join();
}
delete this;
}
void DdkUnbind(ddk::UnbindTxn txn);
void DdkSuspend(ddk::SuspendTxn txn);
// FIDL method implementation.
void GetDeviceId(GetDeviceIdCompleter::Sync& completer);
void ExecuteVendorCommand(ExecuteVendorCommandRequestView request,
ExecuteVendorCommandCompleter::Sync& completer);
void ExecuteCommand(ExecuteCommandRequestView request, ExecuteCommandCompleter::Sync& completer);
private:
template <typename CmdType>
void QueueCommand(std::unique_ptr<CmdType> cmd, TpmCommandCallback&& callback)
__TA_EXCLUDES(command_mutex_);
zx_status_t DoCommand(TpmCommand& cmd);
void CommandThread(ddk::InitTxn txn);
zx_status_t ReadFromFifo(cpp20::span<uint8_t> data);
zx_status_t DoInit();
fidl::WireSyncClient<fuchsia_hardware_tpmimpl::TpmImpl> tpm_;
std::vector<TpmCommand> command_queue_ __TA_GUARDED(command_mutex_);
std::mutex command_mutex_;
std::condition_variable_any command_ready_;
std::thread command_thread_;
std::optional<ddk::UnbindTxn> unbind_txn_ __TA_GUARDED(command_mutex_);
bool shutdown_ __TA_GUARDED(command_mutex_) = false;
inspect::Inspector inspect_;
uint16_t vendor_id_;
uint16_t device_id_;
uint8_t revision_id_;
};
} // namespace tpm
#endif // SRC_DEVICES_TPM_DRIVERS_TPM_TPM_H_