blob: e4e3be76eb41bdbc1fe8fe6a9b20d9900a7cc0cd [file]
// Copyright 2020 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 <fidl/fuchsia.driverhost.test/cpp/wire.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/epitaph.h>
#include <lib/service/llcpp/outgoing_directory.h>
#include <lib/service/llcpp/service.h>
#include "src/devices/lib/driver2/record.h"
#include "src/devices/lib/driver2/start_args.h"
namespace fdf = fuchsia_driver_framework;
namespace ftest = fuchsia_driverhost_test;
class TestDriver {
public:
explicit TestDriver(async_dispatcher_t* dispatcher)
: dispatcher_(dispatcher), outgoing_(dispatcher) {}
zx::status<> Init(fdf::wire::DriverStartArgs* start_args) {
auto error = driver::SymbolValue<zx_status_t*>(start_args->symbols(), "error");
if (error.is_ok()) {
return zx::error(**error);
}
// Call the "func" driver symbol.
auto func = driver::SymbolValue<void (*)()>(start_args->symbols(), "func");
if (func.is_ok()) {
(*func)();
}
// Set the "dispatcher" driver symbol.
auto dispatcher =
driver::SymbolValue<async_dispatcher_t**>(start_args->symbols(), "dispatcher");
if (dispatcher.is_ok()) {
**dispatcher = dispatcher_;
}
// Connect to the incoming service.
auto svc_dir = driver::NsValue(start_args->ns(), "/svc");
if (svc_dir.is_error()) {
return svc_dir.take_error();
}
auto client_end = service::ConnectAt<ftest::Incoming>(svc_dir.value());
if (!client_end.is_ok()) {
return client_end.take_error();
}
// Setup the outgoing service.
zx_status_t status = outgoing_.svc_dir()->AddEntry(
fidl::DiscoverableProtocolName<ftest::Outgoing>,
fbl::MakeRefCounted<fs::Service>([](fidl::ServerEnd<ftest::Outgoing> request) {
return fidl_epitaph_write(request.channel().get(), ZX_ERR_STOP);
}));
if (status != ZX_OK) {
return zx::error(status);
}
return outgoing_.Serve(std::move(start_args->outgoing_dir()));
}
private:
async_dispatcher_t* dispatcher_;
service::OutgoingDirectory outgoing_;
};
zx_status_t test_driver_start(fidl_incoming_msg_t* msg, async_dispatcher_t* dispatcher,
void** driver) {
fidl::DecodedMessage<fdf::wire::DriverStartArgs> decoded(
fidl::internal::kLLCPPEncodedWireFormatVersion, msg);
if (!decoded.ok()) {
return decoded.status();
}
auto test_driver = std::make_unique<TestDriver>(dispatcher);
auto init = test_driver->Init(decoded.PrimaryObject());
if (init.is_error()) {
return init.error_value();
}
*driver = test_driver.release();
return ZX_OK;
}
zx_status_t test_driver_stop(void* driver) {
delete static_cast<TestDriver*>(driver);
return ZX_OK;
}
FUCHSIA_DRIVER_RECORD_V1(.start = test_driver_start, .stop = test_driver_stop);