blob: ddb035aa4dd5b0ae51bbb1fcdcf9c0c265345a66 [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_INSPECT_H_
#define SRC_DEVICES_BIN_DRIVER_MANAGER_INSPECT_H_
#include <lib/inspect/cpp/inspect.h>
#include <lib/zx/channel.h>
#include <lib/zx/status.h>
#include <ddk/binding.h>
#include <fbl/array.h>
#include <fbl/ref_ptr.h>
#include <fs/pseudo_dir.h>
#include <fs/synchronous_vfs.h>
class Device;
struct ProtocolInfo {
const char* name;
fbl::RefPtr<fs::PseudoDir> devnode;
uint32_t id;
uint32_t flags;
uint32_t seqcount;
};
static const inline ProtocolInfo kProtoInfos[] = {
#define DDK_PROTOCOL_DEF(tag, val, name, flags) {name, nullptr, val, flags, 0},
#include <ddk/protodefs.h>
};
class InspectDevfs {
public:
// Use Create instead.
explicit InspectDevfs(const fbl::RefPtr<fs::PseudoDir>& root_dir,
fbl::RefPtr<fs::PseudoDir> class_dir);
static zx::status<InspectDevfs> Create(const fbl::RefPtr<fs::PseudoDir>& root_dir);
std::tuple<fbl::RefPtr<fs::PseudoDir>, uint32_t*> GetProtoDir(uint32_t id);
// Get protocol |id| directory if it exists, else create one.
std::tuple<fbl::RefPtr<fs::PseudoDir>, uint32_t*> GetOrCreateProtoDir(uint32_t id);
// Delete protocol |id| directory if no files are present.
void RemoveEmptyProtoDir(uint32_t id);
zx::status<> AddClassDirEntry(const fbl::RefPtr<Device>& dev);
// Initialize |dev|'s devfs state
zx::status<> InitInspectFile(const fbl::RefPtr<Device>& dev);
zx::status<> Publish(const fbl::RefPtr<Device>& dev);
// Convenience method for initializing |dev| and publishing it to devfs immediately.
zx::status<> InitInspectFileAndPublish(const fbl::RefPtr<Device>& dev);
void Unpublish(Device* dev);
private:
fbl::RefPtr<fs::PseudoDir> root_dir_;
fbl::RefPtr<fs::PseudoDir> class_dir_;
std::array<ProtocolInfo, std::size(kProtoInfos)> proto_infos_;
};
class InspectManager {
public:
explicit InspectManager(async_dispatcher_t* dispatcher);
InspectManager() = delete;
zx::unowned_channel diagnostics_channel() { return zx::unowned_channel(diagnostics_client_); }
fs::PseudoDir& diagnostics_dir() { return *diagnostics_dir_; }
fbl::RefPtr<fs::PseudoDir> driver_host_dir() { return driver_host_dir_; }
inspect::Node& root_node() { return inspect_.GetRoot(); }
inspect::Node& devices() { return devices_; }
inspect::UintProperty& device_count() { return device_count_; }
// Public method for test purpose
inspect::Inspector& inspector() { return inspect_; }
std::optional<InspectDevfs>& devfs() { return devfs_; }
private:
fbl::RefPtr<fs::PseudoDir> diagnostics_dir_;
std::unique_ptr<fs::SynchronousVfs> diagnostics_vfs_;
fbl::RefPtr<fs::PseudoDir> driver_host_dir_;
zx::channel diagnostics_client_;
inspect::Inspector inspect_;
zx::vmo inspect_vmo_;
inspect::UintProperty device_count_;
inspect::Node devices_;
// The inspect devfs instance
std::optional<InspectDevfs> devfs_;
};
class DeviceInspect {
public:
// |devices| and |device_count| should outlive DeviceInspect class
DeviceInspect(inspect::Node& devices, inspect::UintProperty& device_count, std::string name,
zx::vmo inspect_vmo);
~DeviceInspect();
inspect::Node& device_node() { return device_node_; }
zx::vmo& vmo() { return vmo_; }
void set_state(std::string state) { state_.Set(state); }
void set_local_id(uint64_t local_id) { local_id_.Set(local_id); }
// These methods below are for static values and should be called only once. Calling it more than
// once will lead to duplicate entries.
void set_topological_path(std::string path) {
device_node_.CreateString("topological_path", path, &static_values_);
}
void set_protocol_id(uint32_t value) {
device_node_.CreateUint("protocol_id", value, &static_values_);
}
void set_type(std::string type) { device_node_.CreateString("type", type, &static_values_); }
void set_flags(uint32_t flags) { device_node_.CreateUint("flags", flags, &static_values_); }
void set_properties(const fbl::Array<const zx_device_prop_t>& props);
void set_driver(std::string libname) {
device_node_.CreateString("driver", libname, &static_values_);
}
private:
inspect::UintProperty& device_count_node_;
inspect::Node device_node_;
// Reference to nodes with static properties
inspect::ValueList static_values_;
inspect::StringProperty state_;
// Unique id of the device in a driver host
inspect::UintProperty local_id_;
// Inspect VMO returned via devfs's inspect nodes.
zx::vmo vmo_;
};
#endif // SRC_DEVICES_BIN_DRIVER_MANAGER_INSPECT_H_