blob: cf373cddad10d5caef63c4cbcbb38285154f090b [file] [log] [blame]
// Copyright 2018 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.
library fuchsia.device.manager;
// TODO(teisenbe): Move these interfaces to be internal to the devmgr codebase
using zx;
// This definition must be the same size as zx_device_prop_t and is checked by
// static assert. Once the bindings better handle vectors of structs (FIDL-323)
// and we can move the binding struct definition into a more generate-able form,
// we can make this reflect the actual structure.
using DeviceProperty = uint64;
// Same as above, but for bind zx_bind_inst_t.
using BindInstruction = uint64;
// Identifier used to let the devcoordinator describe specific devices during
// composite construction
using LocalDeviceId = uint64;
/// This definition must match ZX_DEVICE_NAME_MAX and is checked by a static assert.
const uint32 DEVICE_NAME_MAX = 31;
/// Maximum number of bytes in a path
// The simple name PATH_MAX collides with a musl #define on c++ bindings.
const uint32 DEVICE_PATH_MAX = 1024;
/// Maximum number of bytes in a device arguments string.
const uint32 DEVICE_ARGS_MAX = 1024;
/// Maximum number of bytes in a metadata payload
const uint32 METADATA_MAX = 4096;
/// Maximum number of properties that can be attached to a device
const uint32 PROPERTIES_MAX = 256;
/// Maximum number of components that a composite device can have
const uint32 COMPONENTS_MAX = 8;
/// Maximum number of parts that a composite device component can have
const uint32 DEVICE_COMPONENT_PARTS_MAX = 16;
/// Maximum instructions in a match program
const uint32 DEVICE_COMPONENT_PART_INSTRUCTIONS_MAX = 32;
/// A part of a description of a DeviceComponent
struct DeviceComponentPart {
// This is an awful hack around the LLCPP bindings not being ready yet.
// Since we're using the C ones for now, we can only embed these structures as
// arrays instead of vectors.
uint32 match_program_count;
array<BindInstruction>:DEVICE_COMPONENT_PART_INSTRUCTIONS_MAX match_program;
};
/// A piece of a composite device
struct DeviceComponent {
// This is an awful hack around the LLCPP bindings not being ready yet.
// Since we're using the C ones for now, we can only embed these structures as
// arrays instead of vectors.
uint32 parts_count;
array<DeviceComponentPart>:DEVICE_COMPONENT_PARTS_MAX parts;
};
/// Protocol for controlling devices in a devhost process from the devcoordinator
[Layout = "Simple"]
protocol DeviceController {
/// Bind the requested driver to this device. |driver_path| is informational,
/// but all calls to BindDriver/CreateDevice should use the same |driver_path|
/// each time they use a |driver| VMO with the same contents.
BindDriver(string:DEVICE_PATH_MAX driver_path, handle<vmo> driver)
-> (zx.status status);
/// Give this device a channel to its shadow in another process.
ConnectProxy(handle<channel> shadow);
/// Ask devhost to unbind this device. On success, the remote end of this
/// interface channel will close instead of returning a result.
Unbind();
/// Ask the devhost to remove this device. On success, the remote end of
/// this interface channel will close instead of returning a result.
RemoveDevice();
/// Ask devhost to suspend this device, using the target state indicated by |flags|.
Suspend(uint32 flags) -> (zx.status status);
};
/// Protocol for controlling a devhost process from the devcoordinator
[Layout = "Simple"]
protocol DevhostController {
/// Create a device in the devhost that only implements the device protocol
/// and claims to support the given |protocol_id|. This device will communicate
/// with the devcoordinator via |rpc|.
CreateDeviceStub(handle<channel> rpc, uint32 protocol_id, LocalDeviceId local_device_id);
/// Create a device in the devhost representing the shadowed half of device
/// in another devhost. This new device will communicate with the devcoordinator
/// via |rpc|, and with its other half via |parent_proxy|.
///
/// The new device will have the given driver responsible for running its half
/// of the driver's cross-process protocol. It's create() method will be invoked,
/// giving it access to |parent_proxy| and |proxy_args|.
///
/// parent_proxy, if present, will usually be a channel to the upper half of
/// a shadowed device. The one exception is when this method is used
/// to create the Platform Bus, in which case it will be a channel to a
/// fuchsia.boot.Items protocol.
///
/// |local_device_id| will be a unique value within the device's devhost
CreateDevice(handle<channel> rpc, string:DEVICE_PATH_MAX driver_path,
handle<vmo> driver, handle? parent_proxy,
string:DEVICE_ARGS_MAX? proxy_args, LocalDeviceId local_device_id);
/// Introduce a composite device that has the given name and properties.
/// |components| will be a list of all of the composite's components,
/// described using devhost local device ids. The order of the components
/// will match the original composite creation request. The new device will
/// communicate with devcoordinator via |rpc|.
///
/// |local_device_id| will be a unique value within the device's devhost, identifying
/// the resulting composite device.
CreateCompositeDevice(handle<channel> rpc,
vector<LocalDeviceId>:COMPONENTS_MAX components,
string:DEVICE_NAME_MAX name, LocalDeviceId local_device_id)
-> (zx.status status);
};
/// Interface for the devices in devhosts to coordinate with the devcoordinator.
[Layout = "Simple"]
protocol Coordinator {
/// Record the addition of a new device that can be communicated with via |rpc|.
/// For binding purposes, it is has properties |props|. |name| and |driver_path|
/// are informational and used for debugging. The device will have |protocol_id|
/// as its primary protocol id. |args| should only be used for shadowed devices,
/// and will be forwarded to the shadow device. |client_remote|, if present,
/// will be passed to the device as an open connection for the client.
/// On success, the returned |local_device_id| is the identifier assigned by devmgr.
AddDevice(handle<channel> rpc,
vector<DeviceProperty>:PROPERTIES_MAX props,
string:DEVICE_NAME_MAX name, uint32 protocol_id,
string:DEVICE_PATH_MAX? driver_path, string:DEVICE_ARGS_MAX? args,
handle<channel>? client_remote)
-> (zx.status status, LocalDeviceId local_device_id);
/// Behaves as AddDevice, but marks the device as initially invisible. This means
/// that it will not be visible to other devices or the devfs until it is later marked
/// visible (via MakeVisible).
AddDeviceInvisible(handle<channel> rpc,
vector<DeviceProperty>:PROPERTIES_MAX props,
string:DEVICE_NAME_MAX name, uint32 protocol_id,
string:DEVICE_PATH_MAX? driver_path,
string:DEVICE_ARGS_MAX? args, handle<channel>? client_remote)
-> (zx.status status, LocalDeviceId local_device_id);
/// Record the removal of this device.
RemoveDevice() -> (zx.status status);
/// Mark this device as visible.
MakeVisible() -> (zx.status status);
/// Attempt to bind a driver against this device. If |driver_path| is null,
/// this will initiate the driver matching algorithm.
/// TODO(teisenbe): Specify the behavior of invoking this multiple times. I believe
/// the current behavior is a bug.
BindDevice(string:DEVICE_PATH_MAX? driver_path) -> (zx.status status);
/// Returns the topological path of this device.
GetTopologicalPath() -> (zx.status status, string:DEVICE_PATH_MAX? path);
/// Requests that the firmware at the given path be loaded and returned.
LoadFirmware(string:DEVICE_PATH_MAX fw_path)
-> (zx.status status, handle<vmo>? vmo, uint64 size);
/// Retrieve the metadata blob associated with this device and the given key.
GetMetadata(uint32 key)
-> (zx.status status, vector<uint8>:METADATA_MAX? data);
/// Retrieve the metadata size associated with this device and the given key.
GetMetadataSize(uint32 key)
-> (zx.status status, uint64 size);
/// Add metadata blob associated with this device and the given key.
/// TODO(teisenbe): Document the behavior of calling this twice with the same
/// key. I believe the current behavior results in inaccessible data that is
/// kept around for the lifetime of the device.
AddMetadata(uint32 key, vector<uint8>:METADATA_MAX? data)
-> (zx.status status);
/// Behaves like AddMetadata, but instead of associating it with the
/// requesting device, associates it with the device at |device_path|. If
/// the device at |device_path| is not a child of the requesting device AND
/// the requesting device is not running in the sys devhost, then this will
/// fail.
PublishMetadata(string:DEVICE_PATH_MAX device_path, uint32 key,
vector<uint8>:METADATA_MAX? data) -> (zx.status status);
/// Adds the given composite device. This causes the devcoordinator to try to match the
/// components against the existing device tree, and to monitor all new device additions
/// in order to find the components as they are created.
// The treatment of |components| is an awful hack around the LLCPP bindings not being ready
// yet. Since we're using the C ones for now, we can only embed these structures as arrays
// instead of vectors.
AddCompositeDevice(string:DEVICE_NAME_MAX name, vector<DeviceProperty>:PROPERTIES_MAX props,
array<DeviceComponent>:COMPONENTS_MAX components, uint32 components_count,
uint32 coresident_device_index) -> (zx.status status);
// Special commands for implementing the dmctl device.
// TODO(teisenbe): We should revisit how these are carried over.
/// Perform an mexec with the given kernel and bootdata.
/// See ZX-2069 for the thoughts on deprecating mexec.
DmMexec(handle<vmo> kernel, handle<vmo> bootdata);
/// Watches a directory, receiving events of added messages on the
/// watcher request channel.
/// See fuchsia.io.Directory for more information.
DirectoryWatch(uint32 mask, uint32 options, handle<channel> watcher)
-> (zx.status s);
};