blob: 6bd08c7d365725e6ae517e1f49c0ed0c7e308470 [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.
#ifndef SRC_DEVICES_BIN_DRIVER_MANAGER_DRIVER_RUNNER_H_
#define SRC_DEVICES_BIN_DRIVER_MANAGER_DRIVER_RUNNER_H_
#include <fuchsia/component/runner/llcpp/fidl.h>
#include <fuchsia/driver/framework/llcpp/fidl.h>
#include <fuchsia/sys2/llcpp/fidl.h>
#include <lib/fidl/llcpp/client.h>
#include <lib/zx/status.h>
#include <unordered_map>
#include <fbl/intrusive_double_list.h>
#include <fs/pseudo_dir.h>
class DriverComponent : public llcpp::fuchsia::component::runner::ComponentController::Interface,
public fbl::DoublyLinkedListable<std::unique_ptr<DriverComponent>> {
public:
DriverComponent(zx::channel exposed_dir, zx::channel driver);
private:
// llcpp::fuchsia::component::runner::ComponentController::Interface
void Stop(StopCompleter::Sync& completer) override;
void Kill(KillCompleter::Sync& completer) override;
zx::channel exposed_dir_;
zx::channel driver_;
};
class DriverHostComponent : public fbl::DoublyLinkedListable<std::unique_ptr<DriverHostComponent>> {
public:
DriverHostComponent(zx::channel driver_host, async_dispatcher_t* dispatcher,
fbl::DoublyLinkedList<std::unique_ptr<DriverHostComponent>>* driver_hosts);
zx::status<zx::channel> Start(
zx::channel node, fidl::VectorView<fidl::StringView> offers,
fidl::VectorView<llcpp::fuchsia::driver::framework::NodeSymbol> symbols,
llcpp::fuchsia::data::Dictionary program,
fidl::VectorView<llcpp::fuchsia::component::runner::ComponentNamespaceEntry> ns,
zx::channel outgoing_dir, zx::channel exposed_dir);
private:
fidl::Client<llcpp::fuchsia::driver::framework::DriverHost> driver_host_;
};
class Node;
class DriverBinder {
public:
virtual ~DriverBinder() = default;
virtual zx::status<> Bind(Node* node, llcpp::fuchsia::driver::framework::NodeAddArgs args) = 0;
};
class Node : public llcpp::fuchsia::driver::framework::NodeController::Interface,
public llcpp::fuchsia::driver::framework::Node::Interface,
public fbl::DoublyLinkedListable<std::unique_ptr<Node>> {
public:
using Offers = std::vector<fidl::StringView>;
using Symbols = std::vector<llcpp::fuchsia::driver::framework::NodeSymbol>;
Node(Node* parent, DriverBinder* driver_binder, async_dispatcher_t* dispatcher, Offers offers,
Symbols symbols);
~Node() override;
fidl::VectorView<fidl::StringView> offers();
fidl::VectorView<llcpp::fuchsia::driver::framework::NodeSymbol> symbols();
DriverHostComponent* parent_driver_host() const;
void set_driver_host(DriverHostComponent* driver_host);
void set_controller_binding(
fidl::ServerBindingRef<llcpp::fuchsia::driver::framework::NodeController> controller_binding);
void set_binding(fidl::ServerBindingRef<llcpp::fuchsia::driver::framework::Node> binding);
void Remove();
private:
// llcpp::fuchsia::driver::framework::NodeController::Interface
void Remove(RemoveCompleter::Sync& completer) override;
// llcpp::fuchsia::driver::framework::Node::Interface
void AddChild(llcpp::fuchsia::driver::framework::NodeAddArgs args, zx::channel controller,
zx::channel node, AddChildCompleter::Sync& completer) override;
Node* parent_;
DriverBinder* driver_binder_;
async_dispatcher_t* dispatcher_;
Offers offers_;
Symbols symbols_;
DriverHostComponent* driver_host_ = nullptr;
std::optional<fidl::ServerBindingRef<llcpp::fuchsia::driver::framework::NodeController>>
controller_binding_;
std::optional<fidl::ServerBindingRef<llcpp::fuchsia::driver::framework::Node>> binding_;
fbl::DoublyLinkedList<std::unique_ptr<Node>> children_;
};
struct MatchResult {
std::string url;
llcpp::fuchsia::driver::framework::NodeAddArgs matched_args;
};
// TODO(fxbug.dev/33183): Replace this with a driver_index component.
class DriverIndex {
public:
using MatchCallback =
fit::function<zx::status<MatchResult>(llcpp::fuchsia::driver::framework::NodeAddArgs args)>;
explicit DriverIndex(MatchCallback match_callback);
zx::status<MatchResult> Match(llcpp::fuchsia::driver::framework::NodeAddArgs args);
private:
MatchCallback match_callback_;
};
struct DriverArgs {
zx::channel exposed_dir;
Node* node;
};
class DriverRunner : public llcpp::fuchsia::component::runner::ComponentRunner::Interface,
public DriverBinder {
public:
DriverRunner(zx::channel realm, DriverIndex* driver_index, async_dispatcher_t* dispatcher);
zx::status<> PublishComponentRunner(const fbl::RefPtr<fs::PseudoDir>& svc_dir);
zx::status<> StartRootDriver(std::string_view name);
private:
// llcpp::fuchsia::component::runner::ComponentRunner::Interface
void Start(llcpp::fuchsia::component::runner::ComponentStartInfo start_info,
zx::channel controller, StartCompleter::Sync& completer) override;
// DriverBinder
zx::status<> Bind(Node* node, llcpp::fuchsia::driver::framework::NodeAddArgs args) override;
zx::status<std::unique_ptr<DriverHostComponent>> StartDriverHost();
zx::status<zx::channel> CreateComponent(std::string name, std::string url,
std::string collection);
uint64_t NextId();
uint64_t next_id_ = 0;
fidl::Client<llcpp::fuchsia::sys2::Realm> realm_;
DriverIndex* driver_index_;
async_dispatcher_t* dispatcher_;
Node root_node_;
std::unordered_map<std::string, DriverArgs> driver_args_;
fbl::DoublyLinkedList<std::unique_ptr<DriverComponent>> drivers_;
fbl::DoublyLinkedList<std::unique_ptr<DriverHostComponent>> driver_hosts_;
};
#endif // SRC_DEVICES_BIN_DRIVER_MANAGER_DRIVER_RUNNER_H_