blob: a354bb8cf7c20b8d838494c3aeca1ed0a0195999 [file] [log] [blame] [edit]
// 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 fuchsia.driver.framework as fdf;
using fuchsia.io;
using fuchsia.device;
using zx;
/// This has the same structure as zx_device_prop_t.
type DeviceProperty = struct {
id uint16;
reserved uint16;
value uint32;
};
type PropertyValue = strict union {
1: int_value uint32;
2: str_value string:STR_LENGTH_MAX;
3: bool_value bool;
4: enum_value string:STR_LENGTH_MAX;
};
type DeviceStrProperty = struct {
key string:STR_LENGTH_MAX;
value PropertyValue;
};
type DevicePropertyList = struct {
props vector<DeviceProperty>:PROPERTIES_MAX;
str_props vector<DeviceStrProperty>:STR_PROPERTIES_MAX;
};
// TODO(bwb): Make this descriptive of binding, not zx_bind_inst_t
// currently a magic bitfield defined in binding.h
type BindInstruction = struct {
/// bitfield that encodes the operation and execution conditions
op uint32;
/// bitfield that encodes the arguments
arg uint32;
/// bitfield that encodes debugging information
debug uint32;
};
// Identifier used to let the devcoordinator describe specific devices during
// composite construction
alias LocalDeviceId = uint64;
/// This definition must match `ZX_DEVICE_NAME_MAX` and is checked by a static assert.
const DEVICE_NAME_MAX uint32 = 31;
/// Maximum number of bytes in a path
// The simple name PATH_MAX collides with a musl #define on c++ bindings.
const DEVICE_PATH_MAX uint32 = 1024;
/// Maximum number of bytes in a device arguments string.
const DEVICE_ARGS_MAX uint32 = 1024;
/// Maximum number of bytes in a metadata payload
const METADATA_BYTES_MAX uint32 = 8192;
/// Maximum number of metadata that can be added to a device
const METADATA_MAX uint32 = 32;
/// Maximum number of properties that can be attached to a device
const PROPERTIES_MAX uint32 = 256;
/// Maximum number of string properties that can be attached to a device
const STR_PROPERTIES_MAX uint32 = 256;
/// Maximum length of a string property key and value.
const STR_LENGTH_MAX uint32 = 255;
/// Maximum number of fragments that a composite device can have
const FRAGMENTS_MAX uint32 = 16;
/// Maximum number of parts that a composite device fragment can have
const DEVICE_FRAGMENT_PARTS_MAX uint32 = 16;
/// Maximum number of instructions in the match program of a device fragment part
const DEVICE_FRAGMENT_PART_INSTRUCTIONS_MAX uint32 = 32;
// Maximum number of instructions in a driver bind program
const BIND_RULES_INSTRUCTIONS_MAX uint32 = 256;
/// Maximum length of a dispatcher scheduler role.
const MAX_SCHEDULER_ROLE_LENGTH uint32 = 2048;
/// Bit flags for device add configuration
type AddDeviceConfig = strict bits : uint32 {
/// Device can be a fragment in multiple composite devices
ALLOW_MULTI_COMPOSITE = 0x00000001;
/// Device should not trigger the auto-bind mechanism
SKIP_AUTOBIND = 0x00000004;
/// Device should run in an isolated driver host from its children.
MUST_ISOLATE = 0x00000008;
};
/// A part of a description of a DeviceFragment
type DeviceFragmentPart = struct {
match_program vector<BindInstruction>:DEVICE_FRAGMENT_PART_INSTRUCTIONS_MAX;
};
/// A piece of a composite device
type DeviceFragment = struct {
name string:32;
parts vector<DeviceFragmentPart>:DEVICE_FRAGMENT_PARTS_MAX;
};
/// Metadata that can be added to a device
type DeviceMetadata = struct {
key uint32;
data vector<uint8>:METADATA_BYTES_MAX;
};
/// Composite device parts and properties
type CompositeDeviceDescriptor = struct {
props vector<DeviceProperty>:PROPERTIES_MAX;
str_props vector<DeviceStrProperty>:STR_PROPERTIES_MAX;
fragments vector<DeviceFragment>:FRAGMENTS_MAX;
primary_fragment_index uint32;
spawn_colocated bool;
metadata vector<DeviceMetadata>:<METADATA_MAX, optional>;
};
/// Composite node specification parts and properties.
type CompositeNodeSpecDescriptor = struct {
parents vector<fdf.ParentSpec>:MAX;
metadata vector<DeviceMetadata>:<METADATA_MAX, optional>;
};
/// Protocol for controlling devices in a devhost process from the devcoordinator
closed protocol DeviceController {
/// Connect to the device's FIDL, but also include other FIDLs multiplexed on the same channel.
///
/// + request `include_node` if this is true then include fuchsia.io/Node on the channel.
/// + request `include_controller` if this is true then include fuchsia.device/Controller on the channel.
strict ConnectMultiplexed(resource struct {
server zx.Handle:CHANNEL;
include_node bool;
include_controller bool;
});
/// Connect to the device's fuchsia.device/Controller API.
strict ConnectToController(resource struct {
controller server_end:fuchsia.device.Controller;
});
/// Connect to the device's API.
///
/// NOTE: This is not multiplexed with fuchsia.io/Node or fuchsia.device/Controller.
strict ConnectToDeviceProtocol(resource struct {
server zx.Handle:CHANNEL;
});
/// 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. Returns a `status`
/// and optionally a channel to the driver's test output. `test_output` will be
/// not present unless the driver is configured to run its run_unit_tests hook, in
/// which case the other end of the channel will have been passed to the driver.
///
/// + request `default_dispatcher_scheduler_role` the scheduler role to set for
/// the default dispatcher created for the driver. The scheduler role determines
/// the thread pool that the dispatcher will be serviced by. This may be an empty
/// string if the driver does not require the dispatcher to run in a specific
/// thread pool. Setting a scheduler role is on a best-effort basis. If an invalid
/// scheduler role is specified, the dispatcher will be serviced by the default
/// thread pool, and this will not cause an error to be returned.
strict BindDriver(resource struct {
driver_path string:DEVICE_PATH_MAX;
driver zx.Handle:VMO;
default_dispatcher_scheduler_role string:MAX_SCHEDULER_ROLE_LENGTH;
}) -> (resource struct {
status zx.Status;
test_output zx.Handle:<CHANNEL, optional>;
});
/// Give this device a channel to its shadow in another process.
strict ConnectProxy(resource struct {
shadow zx.Handle:CHANNEL;
});
/// Ask devhost to call the device init hook.
strict Init() -> (struct {
status zx.Status;
});
/// Ask devhost to unbind this device. On success, the remote end of this
/// interface channel will close instead of returning a result.
strict Unbind() -> () error zx.Status;
/// Ask the devhost to complete the removal of this device, which previously had
/// invoked `ScheduleRemove`. This is a special case that can be removed
/// once `device_remove` invokes `unbind`.
strict CompleteRemoval() -> () error zx.Status;
/// Ask devhost to suspend this device, using the target state indicated by `flags`.
strict Suspend(struct {
flags uint32;
}) -> (struct {
status zx.Status;
});
/// Ask devhost to resume this device, using the target system state indicated by
/// 'target_system_state'.
strict Resume(struct {
target_system_state uint32;
}) -> (struct {
status zx.Status;
});
/// Informs the driver that it has been made visible in devfs.
strict SignalMadeVisible();
};
const FRAGMENT_NAME_MAX uint32 = 32;
type Fragment = struct {
name string:FRAGMENT_NAME_MAX;
id LocalDeviceId;
};
type StubDevice = struct {
protocol_id uint32;
};
type ProxyDevice = resource struct {
driver_path string:DEVICE_PATH_MAX;
driver zx.Handle:VMO;
parent_proxy zx.Handle:CHANNEL;
};
type FidlProxyDevice = resource struct {
/// If this is present this represents an incoming namespace directory that the
/// device can use to access FIDL protocols from its parent.
incoming_dir client_end:<fuchsia.io.Directory, optional>;
};
type CompositeDevice = struct {
fragments vector<Fragment>:FRAGMENTS_MAX;
name string:DEVICE_NAME_MAX;
};
type DeviceType = strict resource union {
/// The device has no parent to communicate with and no driver to load.
1: stub StubDevice;
/// The device acts as a proxy for its parent and talks to it via its
/// proxy channel.
2: proxy ProxyDevice;
/// This device is a proxy for its parent which lives in another driver host.
/// The parent exposes FIDL protocols in its outgoing directory, which have
/// been routed to this device.
3: fidl_proxy FidlProxyDevice;
/// The device is a composite device with several parents, referred to as
/// fragments. The device aggregates all parent devices together. The order of the
/// fragments will match the original composite creation request.
4: composite CompositeDevice;
};
/// Protocol for controlling a driver host process from the driver manager
closed protocol DriverHostController {
/// Create a device in the driver host. |type| describes what type of device
/// is set up, how it communicates with its parent (if it has one).
///
/// `local_device_id` will be a unique value within the device's devhost
strict CreateDevice(resource struct {
coordinator client_end:Coordinator;
device_controller server_end:DeviceController;
type DeviceType;
local_device_id LocalDeviceId;
}) -> (struct {
status zx.Status;
});
// TODO(fxbug.dev/68309): Currently unimplemented.
/// Request to restart the driver host. Also restarts all children devices and drivers and
/// rebinds them once the Driver Host has restarted.
strict Restart() -> (struct {
status zx.Status;
});
};
/// This struct holds non-resource arguments for creating a new device with the
/// Coordinator.
type AddDeviceArgs = struct {
/// The device name, used for debugging.
name string:DEVICE_NAME_MAX;
/// The protocol id, used for binding.
protocol_id uint32;
/// The property list of the device, used for binding.
property_list DevicePropertyList;
/// The driver path, used for debugging.
driver_path string:<DEVICE_PATH_MAX, optional>;
/// This should be used only for shadowed device. This will be forwarded to
/// the shadowed device.
args string:<DEVICE_ARGS_MAX, optional>;
device_add_config AddDeviceConfig;
has_init bool;
/// An address pointing to the DFv2 device symbol, which contains its banjo
/// ops. This exists on every DFv1 device, but it is only used by a DFv2
/// child.
dfv2_device_symbol uint64;
};
/// Interface for drivers in driver host to coordinate with the driver
/// manager.
closed protocol Coordinator {
/// Record the addition of a new device that can be communicated with via `device_controller`.
/// On success, the returned `local_device_id` is the identifier assigned by devmgr.
// TODO(fxb/74654): String properties are unimplemented.
strict AddDevice(resource struct {
args AddDeviceArgs;
coordinator server_end:Coordinator;
device_controller client_end:DeviceController;
inspect zx.Handle:<VMO, optional>;
outgoing_dir client_end:<fuchsia.io.Directory, optional>;
}) -> (struct {
local_device_id LocalDeviceId;
}) error zx.Status;
/// Requests the devcoordinator schedule the removal of this device,
/// and the unbinding of its children.
/// If `unbind_self` is true, the unbind hook for this device will also be called.
strict ScheduleRemove(struct {
unbind_self bool;
});
/// Requests the devcoordinator schedule the unbinding of this device's children.
/// If the device has no children, no request will be sent, and `has_children` will be false.
strict ScheduleUnbindChildren() -> (struct {
has_children bool;
}) error zx.Status;
/// Attempt to bind a driver against this device.
/// + request `driver_url_suffix` only driver's that match this URL suffix will try to bind to
/// the device (e.g: "fvm.cm").
/// If this is null, the API will autobind.
/// * error `ZX_ERR_ALREADY_BOUND` if the device is already bound.
/// * error `ZX_ERR_NOT_FOUND` no drivers were found.
strict BindDevice(struct {
driver_url_suffix string:<DEVICE_PATH_MAX, optional>;
}) -> () error zx.Status;
/// Returns the topological path of this device.
strict GetTopologicalPath() -> (struct {
path string:DEVICE_PATH_MAX;
}) error zx.Status;
/// Requests that the firmware at the given path be loaded and returned.
strict LoadFirmware(struct {
driver_path string:DEVICE_PATH_MAX;
fw_path string:DEVICE_PATH_MAX;
}) -> (resource struct {
vmo zx.Handle:VMO;
size uint64;
}) error zx.Status;
/// Retrieve the metadata blob associated with this device and the given key.
strict GetMetadata(struct {
key uint32;
}) -> (struct {
data vector<uint8>:METADATA_BYTES_MAX;
}) error zx.Status;
/// Retrieve the metadata size associated with this device and the given key.
strict GetMetadataSize(struct {
key uint32;
}) -> (struct {
size uint64;
}) error zx.Status;
/// Add metadata blob associated with this device and the given key.
/// If the same key is specified multiple times, the new data will be
/// ignored in favor of the data from first call with the specified key.
// TODO(fxbug.dev/112547): Return ZX_ERR_ALREADY_EXISTS on duplicate key
// instead.
strict AddMetadata(struct {
key uint32;
data vector<uint8>:<METADATA_BYTES_MAX, optional>;
}) -> () error zx.Status;
/// Adds the given composite device. This causes the driver manager to try to match the
/// fragments against the existing device tree, and to monitor all new device additions
/// in order to find the fragments as they are created.
strict AddCompositeDevice(struct {
name string:DEVICE_NAME_MAX;
comp_desc CompositeDeviceDescriptor;
}) -> () error zx.Status;
/// Adds the given composite node spec. This causes the driver manager to add the spec to
/// the driver index, and then try to match the parents against the node topology.
/// All device additions will be monitored to see if they matched to the remaining
/// unbound nodes.
strict AddCompositeNodeSpec(struct {
name string:DEVICE_NAME_MAX;
spec CompositeNodeSpecDescriptor;
}) -> () error zx.Status;
/// Connects the given FIDL protocol inside of a FIDL service. Connection is completed
/// asynchronously due to pipelining. Returning `ZX_OK` does not imply the service exists. A
/// two way call to the service via the retained client end of the channel pair must be issued
/// in order to ascertain whether the connection has been successfully established.
/// + |fragment_name| should be specified if the parent is a composite node.
/// + |service_name| should be specified if attempting to connect to a service. This will be
/// mandatory in the future: http://fxbug.dev/107155.
/// * error Reports `ZX_ERR_UNAVAILABLE` if the parent (or fragment) does not have an outgoing
/// directory.
/// * error Reports `ZX_ERR_NOT_FOUND` if |fragment_name| is not the name of a parent.
/// * error Reports `ZX_ERR_NOT_SUPPORTED` if |fragment_name| is specified by the device is not
/// a composite node
strict ConnectFidlProtocol(resource struct {
fragment_name string:<DEVICE_NAME_MAX, optional>;
service_name string:<STR_LENGTH_MAX, optional>;
protocol_name string:STR_LENGTH_MAX;
server zx.Handle:CHANNEL;
}) -> () error zx.Status;
};