blob: e87324b6a01390400857a7c95241c99b7880e451 [file] [log] [blame]
// Copyright 2023 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_GPIO_TESTING_FAKE_GPIO_FAKE_GPIO_H_
#define SRC_DEVICES_GPIO_TESTING_FAKE_GPIO_FAKE_GPIO_H_
#include <fidl/fuchsia.hardware.gpio/cpp/wire_test_base.h>
#include <lib/zx/interrupt.h>
#include <queue>
#include <vector>
namespace fake_gpio {
// Contains information specific to when a GPIO has been configured for
// output.
struct WriteSubState {
// Value that the GPIO has been set to output.
uint8_t value;
bool operator==(const WriteSubState& other) const;
};
// Contains information specific to when a GPIO has been configured for input.
struct ReadSubState {
fuchsia_hardware_gpio::GpioFlags flags;
bool operator==(const ReadSubState& other) const;
};
// Contains information specific to when a GPIO has been configured to perform
// an alternative function.
struct AltFunctionSubState {
uint64_t function;
bool operator==(const AltFunctionSubState& other) const;
};
using SubState = std::variant<WriteSubState, ReadSubState, AltFunctionSubState>;
template <typename T>
bool operator==(const T& sub_state1, const SubState& sub_state2) {
const T* alternative = std::get_if<T>(&sub_state2);
return alternative != nullptr && sub_state1 == *alternative;
}
template <typename T>
bool operator==(const SubState& sub_state1, const T& sub_state2) {
return sub_state2 == sub_state1;
}
struct State {
fuchsia_hardware_gpio::GpioPolarity polarity;
SubState sub_state;
};
class FakeGpio;
using ReadCallback = std::function<zx::result<uint8_t>(FakeGpio&)>;
using WriteCallback = std::function<zx_status_t(FakeGpio&)>;
class FakeGpio : public fidl::testing::WireTestBase<fuchsia_hardware_gpio::Gpio> {
public:
FakeGpio();
// fidl::testing::WireTestBase<fuchsia_hardware_gpu::Gpio>
void GetInterrupt(GetInterruptRequestView request,
GetInterruptCompleter::Sync& completer) override;
void SetAltFunction(SetAltFunctionRequestView request,
SetAltFunctionCompleter::Sync& completer) override;
void ConfigIn(ConfigInRequestView request, ConfigInCompleter::Sync& completer) override;
void ConfigOut(ConfigOutRequestView request, ConfigOutCompleter::Sync& completer) override;
void Write(WriteRequestView request, WriteCompleter::Sync& completer) override;
void Read(ReadCompleter::Sync& completer) override;
void ReleaseInterrupt(ReleaseInterruptCompleter::Sync& completer) override;
void SetPolarity(SetPolarityRequestView request, SetPolarityCompleter::Sync& completer) override;
void NotImplemented_(const std::string& name, ::fidl::CompleterBase& completer) override {
completer.Close(ZX_ERR_NOT_SUPPORTED);
}
// Return the function set by `SetAltFunction`. Will fail if the current
// state isn't `AltFunction.`
uint64_t GetAltFunction() const;
// Return the value being written by the gpio. Will fail if the current state
// isn't `Write`.
uint8_t GetWriteValue() const;
// Return the read flags set by `ConfigIn`. Will fail if the current state
// isn't `Read`.
fuchsia_hardware_gpio::GpioFlags GetReadFlags() const;
// Return the most recent polarity set by `SetPolarity`. Will fail if there
// is not a current state.
fuchsia_hardware_gpio::GpioPolarity GetPolarity() const;
// Set the interrupt used for GetInterrupt requests to `interrupt`.
void SetInterrupt(zx::result<zx::interrupt> interrupt);
// Add `callback` to the queue of callbacks used to handle `Read` requests.
void PushReadCallback(ReadCallback callback);
// Add a callback that will return `response` to the queue of callbacks used
// to handle `Read` requests.
void PushReadResponse(zx::result<uint8_t> response);
// Set the default response for `Read` requests if the callback queue for
// `Read` requests is empty. Set to none for no default response.
void SetDefaultReadResponse(std::optional<zx::result<uint8_t>> response);
// Set the callback used for responding to Write requests to `write_callback`.
void SetWriteCallback(WriteCallback write_callback);
// Set the current state to `state`.
void SetCurrentState(State state);
// Return the states the gpio has been set to in chronological order.
std::vector<State> GetStateLog();
// Serve the gpio FIDL protocol on the current dispatcher and return a client
// end that can communicate with the server.
fidl::ClientEnd<fuchsia_hardware_gpio::Gpio> Connect();
// Returns a handler that binds incoming gpio service connections to this
// server implementation and the dispatcher of the caller.
fuchsia_hardware_gpio::Service::InstanceHandler CreateInstanceHandler();
private:
// Returns the polarity of the current state. Returns high if there isn't a
// current state.
fuchsia_hardware_gpio::GpioPolarity GetCurrentPolarity();
// Contains the states that the gpio has been set to in chronological order.
std::vector<State> state_log_;
// Default response for `Read` requests if `read_callbacks_` is empty.
std::optional<zx::result<uint8_t>> default_read_response_;
// Queue of callbacks that provide values to respond to `Read` requests with.
std::queue<ReadCallback> read_callbacks_;
// Callback that provides the value to respond to `Write` requests with.
WriteCallback write_callback_;
// Interrupt used for GetInterrupt requests.
zx::result<zx::interrupt> interrupt_;
std::atomic<bool> interrupt_used_ = false;
fidl::ServerBindingGroup<fuchsia_hardware_gpio::Gpio> bindings_;
};
} // namespace fake_gpio
#endif // SRC_DEVICES_GPIO_TESTING_FAKE_GPIO_FAKE_GPIO_H_