blob: 5aa6bfc5bb5b631d7a2e43aee6e353c85be4ad13 [file] [log] [blame]
// Copyright 2019 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.
#include "aml-pwm-init.h"
#include <fidl/fuchsia.hardware.gpio/cpp/wire.h>
#include <fidl/fuchsia.hardware.pwm/cpp/wire_test_base.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/default.h>
#include <lib/async_patterns/testing/cpp/dispatcher_bound.h>
#include <list>
#include <fbl/alloc_checker.h>
#include <zxtest/zxtest.h>
#include "src/devices/gpio/testing/fake-gpio/fake-gpio.h"
bool operator==(const fuchsia_hardware_pwm::wire::PwmConfig& lhs,
const fuchsia_hardware_pwm::wire::PwmConfig& rhs) {
return (lhs.polarity == rhs.polarity) && (lhs.period_ns == rhs.period_ns) &&
(lhs.duty_cycle == rhs.duty_cycle) &&
(lhs.mode_config.count() == rhs.mode_config.count()) &&
(reinterpret_cast<aml_pwm::mode_config*>(lhs.mode_config.data())->mode ==
reinterpret_cast<aml_pwm::mode_config*>(rhs.mode_config.data())->mode);
}
namespace pwm_init {
class MockPwmServer final : public fidl::testing::WireTestBase<fuchsia_hardware_pwm::Pwm> {
public:
void SetConfig(SetConfigRequestView request, SetConfigCompleter::Sync& completer) override {
ASSERT_GT(expect_configs_.size(), 0);
auto expect_config = expect_configs_.front();
ASSERT_EQ(request->config, expect_config);
expect_configs_.pop_front();
mode_config_buffers_.pop_front();
completer.ReplySuccess();
}
void Enable(EnableCompleter::Sync& completer) override {
ASSERT_TRUE(expect_enable_);
expect_enable_ = false;
completer.ReplySuccess();
}
void ExpectSetConfig(fuchsia_hardware_pwm::wire::PwmConfig config) {
std::unique_ptr<uint8_t[]> mode_config =
std::make_unique<uint8_t[]>(config.mode_config.count());
memcpy(mode_config.get(), config.mode_config.data(), config.mode_config.count());
auto copy = config;
copy.mode_config =
fidl::VectorView<uint8_t>::FromExternal(mode_config.get(), config.mode_config.count());
expect_configs_.push_back(std::move(copy));
mode_config_buffers_.push_back(std::move(mode_config));
}
void ExpectEnable() { expect_enable_ = true; }
void NotImplemented_(const std::string& name, ::fidl::CompleterBase& completer) override {
completer.Close(ZX_ERR_NOT_SUPPORTED);
}
fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm> BindServer() {
auto endpoints = fidl::Endpoints<fuchsia_hardware_pwm::Pwm>::Create();
fidl::BindServer(async_get_default_dispatcher(), std::move(endpoints.server), this);
return fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm>(std::move(endpoints.client));
}
void VerifyAndClear() {
ASSERT_EQ(expect_configs_.size(), 0);
ASSERT_EQ(mode_config_buffers_.size(), 0);
ASSERT_FALSE(expect_enable_);
}
private:
std::list<fuchsia_hardware_pwm::wire::PwmConfig> expect_configs_;
std::list<std::unique_ptr<uint8_t[]>> mode_config_buffers_;
bool expect_enable_ = false;
};
TEST(PwmInitDeviceTest, InitTest) {
fdf::Logger logger{"common-test", FUCHSIA_LOG_DEBUG, zx::socket{},
fidl::WireClient<fuchsia_logger::LogSink>()};
fdf::Logger::SetGlobalInstance(&logger);
async::Loop fidl_loop{&kAsyncLoopConfigNoAttachToCurrentThread};
async_patterns::TestDispatcherBound<MockPwmServer> pwm{fidl_loop.dispatcher(), std::in_place};
async_patterns::TestDispatcherBound<fake_gpio::FakeGpio> wifi_gpio{fidl_loop.dispatcher(),
std::in_place};
async_patterns::TestDispatcherBound<fake_gpio::FakeGpio> bt_gpio{fidl_loop.dispatcher(),
std::in_place};
EXPECT_OK(fidl_loop.StartThread("fidl-servers"));
auto pwm_client = pwm.SyncCall(&MockPwmServer::BindServer);
auto wifi_gpio_client = wifi_gpio.SyncCall(&fake_gpio::FakeGpio::Connect);
auto bt_gpio_client = bt_gpio.SyncCall(&fake_gpio::FakeGpio::Connect);
// Create a clock connection, but don't connect it to anything.
auto clock_endpoints = fidl::Endpoints<fuchsia_hardware_clock::Clock>::Create();
fidl::ClientEnd<fuchsia_hardware_clock::Clock> clock(std::move(clock_endpoints.client));
clock_endpoints.server.Close(ZX_OK);
pwm.SyncCall(&MockPwmServer::ExpectEnable);
aml_pwm::mode_config two_timer = {
.mode = aml_pwm::Mode::kTwoTimer,
.two_timer =
{
.period_ns2 = 30052,
.duty_cycle2 = 50.0,
.timer1 = 0x0a,
.timer2 = 0x0a,
},
};
fuchsia_hardware_pwm::wire::PwmConfig init_cfg = {
.polarity = false,
.period_ns = 30053,
.duty_cycle = static_cast<float>(49.931787176),
.mode_config = fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&two_timer),
sizeof(two_timer))};
pwm.SyncCall(&MockPwmServer::ExpectSetConfig, init_cfg);
PwmInitDevice dev(std::move(clock), std::move(pwm_client), std::move(wifi_gpio_client),
std::move(bt_gpio_client));
EXPECT_OK(dev.Init());
ASSERT_EQ(1, wifi_gpio.SyncCall(&fake_gpio::FakeGpio::GetAltFunction));
std::vector states = bt_gpio.SyncCall(&fake_gpio::FakeGpio::GetStateLog);
ASSERT_EQ(2, states.size());
ASSERT_EQ(fake_gpio::WriteSubState{.value = 0}, states[0].sub_state);
ASSERT_EQ(fake_gpio::WriteSubState{.value = 1}, states[1].sub_state);
pwm.SyncCall(&MockPwmServer::VerifyAndClear);
}
} // namespace pwm_init