blob: e5de58c959baa37905e29430663fe26cb22097d9 [file] [log] [blame]
// Copyright 2017 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 <lib/async/cpp/wait.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <lib/zx/process.h>
#include <utility>
#include <fbl/intrusive_double_list.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fs/pseudo_dir.h>
#include "device.h"
#include "fdio.h"
using LoaderServiceConnector = fit::function<zx_status_t(zx::channel*)>;
class Coordinator;
struct DriverHostConfig {
const char* name;
const char* binary;
const char* const* env;
const zx::unowned_job job;
const zx::unowned_resource root_resource;
const LoaderServiceConnector* loader_service_connector;
FsProvider* fs_provider;
Coordinator* coordinator;
class DriverHost : public fbl::RefCounted<DriverHost>,
public fbl::DoublyLinkedListable<DriverHost*> {
enum Flags : uint32_t {
kDying = 1 << 0,
kSuspend = 1 << 1,
// This constructor is public so that tests can create DriverHosts without launching processes.
// The main program logic will want to use DriverHost::Launch
// |coordinator| must outlive this DriverHost object.
// |rpc| is a client channel speaking fuchsia.device.manager/DriverHostController
// |diagnostics| is a client to driver host diagnostics directory
// |proc| is a handle to the driver_host process this DriverHost tracks.
DriverHost(Coordinator* coordinator, zx::channel rpc, zx::channel diagnostics, zx::process proc);
// |coordinator| must outlive this DriverHost object. If |loader_conector| is nullptr, the
// default loader service is used, which is useful in test environments.
static zx_status_t Launch(const DriverHostConfig& config, fbl::RefPtr<DriverHost>* out);
const zx::channel& hrpc() const { return hrpc_; }
zx::unowned_process proc() const { return zx::unowned_process(proc_); }
zx_koid_t koid() const { return koid_; }
// Note: this is a non-const reference to make |= etc. ergonomic.
uint32_t& flags() { return flags_; }
fbl::TaggedDoublyLinkedList<Device*, Device::DriverHostListTag>& devices() { return devices_; }
// Returns a device id that will be unique within this driver_host.
uint64_t new_device_id() { return next_device_id_++; }
Coordinator* coordinator_;
zx::channel hrpc_;
zx::process proc_;
zx_koid_t koid_ = 0;
uint32_t flags_ = 0;
// The next ID to be allocated to a device in this driver_host. Skip 0 to make
// an uninitialized value more obvious.
uint64_t next_device_id_ = 1;
// list of all devices on this driver_host
fbl::TaggedDoublyLinkedList<Device*, Device::DriverHostListTag> devices_;
// Holding reference to driver host inspect directory so that it will not be freed while in use
fbl::RefPtr<fs::PseudoDir> driver_host_dir_;