| // 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 has the same structure as zx_device_prop_t. |
| struct DeviceProperty { |
| uint16 id; |
| uint16 reserved; |
| uint32 value; |
| }; |
| |
| // TODO(bwb): Make this descriptive of binding, not zx_bind_inst_t |
| // currently a magic bitfield defined in binding.h |
| struct BindInstruction { |
| /// bitfield that encodes the operation and execution conditions |
| uint32 op; |
| /// bitfield that encodes the arguments |
| uint32 arg; |
| /// bitfield that encodes debugging information |
| uint32 debug; |
| }; |
| |
| // 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 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_BYTES_MAX = 8192; |
| |
| /// Maximum number of metadata that can be added to a device |
| const uint32 METADATA_MAX = 32; |
| |
| /// Maximum number of properties that can be attached to a device |
| const uint32 PROPERTIES_MAX = 256; |
| |
| /// Maximum number of fragments that a composite device can have |
| const uint32 FRAGMENTS_MAX = 16; |
| |
| /// Maximum number of parts that a composite device fragment can have |
| const uint32 DEVICE_FRAGMENT_PARTS_MAX = 16; |
| |
| /// Maximum number of instructions in the match program of a device fragment part |
| const uint32 DEVICE_FRAGMENT_PART_INSTRUCTIONS_MAX = 32; |
| |
| // Maximum number of instructions in a driver bind program |
| const uint32 BIND_PROGRAM_INSTRUCTIONS_MAX = 256; |
| |
| /// Bit flags for device add configuration |
| bits AddDeviceConfig : uint32 { |
| /// Device can be a fragment in multiple composite devices |
| ALLOW_MULTI_COMPOSITE = 0x00000001; |
| /// Device should be marked invisible initially (used for deprecated DEVICE_ADD_INVISIBLE) |
| INVISIBLE = 0x00000002; |
| /// Device should not trigger the auto-bind mechanism |
| SKIP_AUTOBIND = 0x00000004; |
| }; |
| |
| /// A part of a description of a DeviceFragment |
| struct DeviceFragmentPart { |
| // 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_FRAGMENT_PART_INSTRUCTIONS_MAX match_program; |
| }; |
| |
| /// A piece of a composite device |
| struct DeviceFragment { |
| // 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. |
| string:32 name; |
| uint32 parts_count; |
| array<DeviceFragmentPart>:DEVICE_FRAGMENT_PARTS_MAX parts; |
| }; |
| |
| /// Metadata that can be added to a device |
| struct DeviceMetadata { |
| uint32 key; |
| vector<uint8>:METADATA_BYTES_MAX data; |
| }; |
| |
| /// Composite device parts and properties |
| struct CompositeDeviceDescriptor { |
| vector<DeviceProperty>:PROPERTIES_MAX props; |
| vector<DeviceFragment>:FRAGMENTS_MAX fragments; |
| uint32 coresident_device_index; |
| vector<DeviceMetadata>:METADATA_MAX? metadata; |
| }; |
| |
| /// A enum of CompatibilityTestStatus |
| enum CompatibilityTestStatus : uint32 { |
| OK = 1; |
| ERR_BIND_NO_DDKADD = 2; |
| ERR_BIND_TIMEOUT = 3; |
| ERR_UNBIND_NO_DDKREMOVE = 4; |
| ERR_UNBIND_TIMEOUT = 5; |
| ERR_SUSPEND_DDKREMOVE = 6; |
| ERR_INTERNAL = 7; |
| }; |
| |
| /// Protocol for controlling devices in a devhost process from the devcoordinator |
| 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. 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. |
| BindDriver(string:DEVICE_PATH_MAX driver_path, zx.handle:VMO driver) |
| -> (zx.status status, zx.handle:CHANNEL? test_output); |
| |
| /// Give this device a channel to its shadow in another process. |
| ConnectProxy(zx.handle:CHANNEL shadow); |
| |
| /// Ask devhost to call the device init hook. |
| Init() -> (zx.status status); |
| |
| /// Ask devhost to unbind this device. On success, the remote end of this |
| /// interface channel will close instead of returning a result. |
| 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`. |
| CompleteRemoval() -> () error zx.status; |
| |
| /// Ask devhost to suspend this device, using the target state indicated by `flags`. |
| Suspend(uint32 flags) -> (zx.status status); |
| |
| /// Ask devhost to resume this device, using the target system state indicated by |
| /// 'target_system_state'. |
| Resume(uint32 target_system_state) -> (zx.status status); |
| |
| /// Inform devhost about the compatibility test status when compatibility tests |
| /// fail or complete successfully. |
| // TODO(ravoorir) : This should be an asynchronous call from devhost to |
| // devcoordinator as a reply to RunCompatibilityTests, when llcpp can support |
| // making an asynchronous fidl call. |
| CompleteCompatibilityTests(CompatibilityTestStatus status); |
| }; |
| |
| const uint32 FRAGMENT_NAME_MAX = 32; |
| |
| [ForDeprecatedCBindings] |
| struct Fragment { |
| string:FRAGMENT_NAME_MAX name; |
| LocalDeviceId id; |
| }; |
| |
| /// Protocol for controlling a devhost process from the devcoordinator |
| 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 `coordinator`. Implements DeviceController on device_controller_rpc |
| CreateDeviceStub(Coordinator coordinator_rpc, request<DeviceController> device_controller_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(Coordinator coordinator_rpc, request<DeviceController> device_controller_rpc, string:DEVICE_PATH_MAX driver_path, |
| zx.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. |
| /// `fragments` will be a list of all of the composite's fragments, |
| /// described using devhost local device ids. The order of the fragments |
| /// 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(Coordinator coordinator_rpc, request<DeviceController> device_controller_rpc, |
| vector<Fragment>:FRAGMENTS_MAX fragments, |
| string:DEVICE_NAME_MAX name, LocalDeviceId local_device_id) |
| -> (zx.status 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. |
| Restart() -> (zx.status status); |
| }; |
| |
| /// Interface for the devices in devhosts to coordinate with the devcoordinator. |
| 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(request<Coordinator> coordinator, DeviceController device_controller, |
| vector<DeviceProperty>:PROPERTIES_MAX props, |
| string:DEVICE_NAME_MAX name, uint32 protocol_id, |
| string:DEVICE_PATH_MAX? driver_path, string:DEVICE_ARGS_MAX? args, |
| AddDeviceConfig device_add_config, bool has_init, zx.handle:VMO? inspect, |
| zx.handle:CHANNEL? client_remote) |
| -> (LocalDeviceId local_device_id) 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. |
| ScheduleRemove(bool unbind_self); |
| |
| /// Requests the devcoordinator schedule the unbinding of this device's children. |
| ScheduleUnbindChildren(); |
| |
| /// Mark this device as visible. |
| MakeVisible() -> () error zx.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) -> () error zx.status; |
| |
| /// Returns the topological path of this device. |
| GetTopologicalPath() -> (string:DEVICE_PATH_MAX path) error zx.status; |
| |
| /// Requests that the firmware at the given path be loaded and returned. |
| LoadFirmware(string:DEVICE_PATH_MAX fw_path) |
| -> (zx.handle:VMO vmo, uint64 size) error zx.status; |
| |
| /// Retrieve the metadata blob associated with this device and the given key. |
| GetMetadata(uint32 key) |
| -> (vector<uint8>:METADATA_BYTES_MAX data) error zx.status; |
| |
| /// Retrieve the metadata size associated with this device and the given key. |
| GetMetadataSize(uint32 key) |
| -> (uint64 size) error zx.status; |
| |
| /// 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_BYTES_MAX? data) |
| -> () error zx.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_BYTES_MAX? data) -> () error zx.status; |
| |
| /// Adds the given composite device. This causes the devcoordinator 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. |
| AddCompositeDevice(string:DEVICE_NAME_MAX name, CompositeDeviceDescriptor comp_desc) |
| -> () error zx.status; |
| |
| /// Run Compatibility tests for the driver that binds to this device. |
| /// The hook_wait_time is the time that the driver expects to take for |
| /// each device hook in nanoseconds. |
| /// Returns whether the compatibility tests started, and does not convey |
| /// anything about the status of the test. |
| RunCompatibilityTests(int64 hook_wait_time) -> () error zx.status; |
| }; |
| |
| /// Protocol for getting the information needed to debug bind programs from the devcoordinator. |
| [Discoverable] |
| protocol BindDebugger { |
| /// Returns the bind program of the given driver. |
| /// ZX_ERR_NOT_FOUND indicates that there is no driver matching the given path. |
| /// ZX_ERR_BUFFER_TOO_SMALL indicates that the driver's bind program is longer than the |
| /// maximum number of instructions (BIND_PROGRAM_INSTRUCTIONS_MAX). |
| GetBindProgram(string:DEVICE_PATH_MAX driver_path) |
| -> (vector<BindInstruction>:BIND_PROGRAM_INSTRUCTIONS_MAX instructions) |
| error zx.status; |
| |
| /// Returns the list of properties of the given device. |
| /// ZX_ERR_NOT_FOUND indicates that there is no device matching the given path. |
| /// ZX_ERR_BAD_PATH indicates that the given path is not valid. |
| /// ZX_ERR_BUFFER_TOO_SMALL indicates either that the given path is too long, |
| /// or that the device has more than the maximum number of properties (PROPERTIES_MAX). |
| GetDeviceProperties(string:DEVICE_PATH_MAX device_path) |
| -> (vector<DeviceProperty>:PROPERTIES_MAX props) error zx.status; |
| }; |