blob: 845719038ef03598db778fce4b323c071ac29f28 [file] [log] [blame]
// 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/driver2/record.h>
#include <lib/driver2/start_args.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/epitaph.h>
#include <lib/service/llcpp/service.h>
#include <lib/sys/component/llcpp/outgoing_directory.h>
namespace fdf = fuchsia_driver_framework;
namespace ftest = fuchsia_driverhost_test;
class TestDriver {
public:
explicit TestDriver(fdf_dispatcher_t* dispatcher)
: dispatcher_(dispatcher),
outgoing_(
component::OutgoingDirectory::Create(fdf_dispatcher_get_async_dispatcher(dispatcher))) {
}
zx::status<> Init(fdf::wire::DriverStartArgs* start_args) {
auto error = driver::SymbolValue<zx_status_t*>(*start_args, "error");
if (error.is_ok()) {
return zx::error(**error);
}
// Call the "func" driver symbol.
auto func = driver::SymbolValue<void (*)()>(*start_args, "func");
if (func.is_ok()) {
(*func)();
}
// Set the "dispatcher" driver symbol.
auto dispatcher = driver::SymbolValue<fdf_dispatcher_t**>(*start_args, "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.
auto status =
outgoing_.AddProtocol<ftest::Outgoing>([](fidl::ServerEnd<ftest::Outgoing> request) {
fidl_epitaph_write(request.channel().get(), ZX_ERR_STOP);
});
if (status.is_error()) {
return status;
}
return outgoing_.Serve(std::move(start_args->outgoing_dir()));
}
private:
fdf_dispatcher_t* dispatcher_;
component::OutgoingDirectory outgoing_;
};
zx_status_t test_driver_start(EncodedDriverStartArgs encoded_start_args,
fdf_dispatcher_t* dispatcher, void** driver) {
// TODO(fxbug.dev/45252): Use FIDL at rest.
auto wire_format_metadata =
fidl::WireFormatMetadata::FromOpaque(encoded_start_args.wire_format_metadata);
fidl::unstable::DecodedMessage<fdf::wire::DriverStartArgs> decoded(
wire_format_metadata.wire_format_version(), encoded_start_args.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);