| // 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); |
| }; |