| // 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. |
| library fuchsia.driver.framework; |
| |
| using fuchsia.device.fs; |
| using fuchsia.component; |
| using fuchsia.component.decl; |
| using fuchsia.io; |
| |
| using zx; |
| |
| alias NodePropertyKeyString = string:256; |
| alias NodePropertyKeyUint = uint32; |
| alias NodePropertyValueUint = uint32; |
| alias NodePropertyValueString = string:256; |
| alias NodePropertyValueBool = bool; |
| alias NodePropertyValueEnum = string:256; |
| |
| const MAX_OFFER_COUNT uint32 = fuchsia.component.MAX_DYNAMIC_OFFER_COUNT; |
| const MAX_SYMBOL_COUNT uint8 = 64; |
| const MAX_PROPERTY_COUNT uint8 = 64; |
| |
| const MAX_NODE_NAME_LENGTH uint8 = 128; |
| const MAX_SYMBOL_NAME_LENGTH uint8 = 128; |
| |
| @available(added=27) |
| const MAX_MODULE_NAME_LENGTH uint8 = 128; |
| |
| @available(added=26) |
| const MAX_DEVICE_ADDRESS_ARRAY_LEN uint32 = 10; |
| @available(added=26) |
| const MAX_DEVICE_ADDRESS_STR_LEN uint32 = 32; |
| |
| @available(added=18) |
| const MAX_RESOURCE_NAME_LENGTH uint8 = 128; |
| |
| @available(added=18) |
| alias NodeOffersVector = vector<Offer>:MAX_OFFER_COUNT; |
| |
| alias NodePropertyVector = vector<NodeProperty>:MAX_PROPERTY_COUNT; |
| alias NodeName = string:MAX_NODE_NAME_LENGTH; |
| |
| @available(added=26) |
| alias NodeProperties = vector<NodeProperty2>:MAX_PROPERTY_COUNT; |
| |
| /// Definition of a symbol provided by a driver for a node. A symbol is local to |
| /// a driver host. |
| type NodeSymbol = table { |
| /// Module name that provided the symbol. |
| /// Will not be provided when the symbol originates from the primary parent. |
| @available(added=27) |
| 3: module_name string:MAX_MODULE_NAME_LENGTH; |
| |
| /// Name of the symbol. |
| 1: name string:MAX_SYMBOL_NAME_LENGTH; |
| |
| /// Virtual address of the symbol, within a driver host's process. |
| 2: address uint64; |
| }; |
| |
| type NodePropertyKey = strict union { |
| /// Integer-based keys are no longer supported. Use |string_value| instead. |
| 1: int_value NodePropertyKeyUint; |
| |
| 2: string_value NodePropertyKeyString; |
| }; |
| |
| type NodePropertyValue = flexible union { |
| 1: int_value NodePropertyValueUint; |
| 2: string_value NodePropertyValueString; |
| 3: bool_value NodePropertyValueBool; |
| 4: enum_value NodePropertyValueEnum; |
| }; |
| |
| /// Definition of a property for a node. A property is commonly used to match a |
| /// node to a driver for driver binding. |
| type NodeProperty = struct { |
| /// Key for the property. Integer-based keys are no longer supported. The NodePropertyKey |
| /// must be a string value. |
| key NodePropertyKey; |
| |
| /// Value for the property. |
| value NodePropertyValue; |
| }; |
| |
| @available(added=18) |
| type Offer = flexible union { |
| 1: zircon_transport fuchsia.component.decl.Offer; |
| 2: driver_transport fuchsia.component.decl.Offer; |
| }; |
| |
| @available(added=26) |
| type NodeProperty2 = struct { |
| /// Property key. |
| key NodePropertyKeyString; |
| |
| /// Property value. |
| value NodePropertyValue; |
| }; |
| |
| // Arguments for adding a node to the devfs filesystem. |
| type DevfsAddArgs = resource table { |
| /// This is the connector to be installed in devfs. |
| /// `Connect()` will be called when a client connects to this node in the filesystem. |
| /// Optional: If this is not provided then an empty node will appear in devfs. |
| 1: connector client_end:fuchsia.device.fs.Connector; |
| |
| /// This is the class name for installing this node in devfs. |
| /// The node will be placed within /dev/class/{class_name}. |
| /// If `class_name` does not exist under /dev/class/ it will be created. |
| /// Optional: If this is not provided then the node will only be added via topological path. |
| 2: class_name string:fuchsia.io.MAX_NAME_LENGTH; |
| |
| /// This is a vmo of inspect data that will be installed in devfs. |
| /// Optional: If this is not provided then the devfs's inspect data will be empty. |
| 3: inspect zx.Handle:VMO; |
| |
| /// The connection types that are supported by the |connector| given. |
| /// The driver framework should handle connection types that are not supported by the |
| /// connector. |
| /// If not provided, only the device type is assumed as supported by the connector. |
| @available(added=16) |
| 4: connector_supports fuchsia.device.fs.ConnectionType; |
| |
| /// This is the controller connector to be installed in devfs. |
| /// `Connect()` will be called when a client connects to the device_controller connection |
| /// for this node in the filesystem. |
| /// Optional: If this is not provided then the Node will handle the connection natively. |
| /// This option should only be used by the compat shim or in tests |
| @available(added=HEAD) |
| 5: controller_connector client_end:fuchsia.device.fs.Connector; |
| }; |
| |
| @available(added=26) |
| type BusType = flexible enum { |
| PLATFORM = 1; |
| ACPI = 2; |
| DEVICE_TREE = 3; |
| PCI = 4; |
| USB = 5; |
| GPIO = 6; |
| I2C = 7; |
| SPI = 8; |
| SDIO = 9; |
| UART = 10; |
| SPMI = 11; |
| }; |
| |
| @available(added=26) |
| type DeviceAddress = flexible union { |
| /// A fixed integer id, eg a spi bus address |
| 1: int_value uint8; |
| |
| /// An array of integers, eg a PCI BDF. |
| 2: array_int_value vector<uint8>:MAX_DEVICE_ADDRESS_ARRAY_LEN; |
| |
| /// A uint32 value that can be interpretted as a 4 character sequence. |
| 3: char_int_value string:4; |
| |
| /// An array of character sequences, eg a ACPI node path. |
| 4: array_char_int_value vector<string:4>:MAX_DEVICE_ADDRESS_ARRAY_LEN; |
| |
| /// A generic string, eg the device tree node path. |
| 5: string_value string:MAX_DEVICE_ADDRESS_STR_LEN; |
| }; |
| |
| @available(added=26) |
| type DeviceAddressStability = flexible enum { |
| /// When the driver is restarted, the device address may change. |
| UNSTABLE_BETWEEN_DRIVER_RESTART = 0; |
| |
| /// When the system is restarted, the device address may change. |
| UNSTABLE_BETWEEN_BOOT = 1; |
| |
| /// When the system is updated, the device address may change. |
| UNSTABLE_BETWEEN_SOFTWARE_UPDATE = 2; |
| |
| /// The device address on the bus is guaranteed stable for the lifetime of the system. |
| STABLE = 3; |
| }; |
| |
| @available(added=26) |
| type BusInfo = table { |
| /// The type of bus this node sits on. |
| 1: bus BusType; |
| |
| /// A unique identifier that describes the identity of this device on the given bus. |
| 2: address DeviceAddress; |
| |
| /// How stable the address. |
| 3: address_stability DeviceAddressStability; |
| }; |
| |
| /// Arguments for adding a node. |
| type NodeAddArgs = resource table { |
| /// Name of the node. |
| 1: name NodeName; |
| |
| /// Functions to provide to the driver that is bound to this node. |
| 3: symbols vector<NodeSymbol>:MAX_SYMBOL_COUNT; |
| |
| /// Properties of the node. Deprecated: all new usages should set properties2 and leave |
| /// this field blank. |
| @available( |
| deprecated=26, |
| note="Deprecated for 'properties2' which only supports string-based keys.") |
| 4: properties NodePropertyVector; |
| |
| /// Properties of the node. If set, the `properties` field must be blank. Otherwise, |
| /// adding the node will return an error. |
| @available(added=26) |
| 8: properties2 NodeProperties; |
| |
| /// The arguments for how this node should be added to devfs. |
| 5: devfs_args DevfsAddArgs; |
| |
| /// Capabilities to offer to the driver that is bound to this node. |
| /// The driver must ensure these capabilities are added to its outgoing directory |
| /// before adding the child node. |
| @available(added=18) |
| 6: offers2 NodeOffersVector; |
| |
| /// Information that feeds into a structured bus topology for the device. It should |
| /// only be specified by bus drivers, ideally those which are included by default. |
| @available(added=26) |
| 7: bus_info BusInfo; |
| }; |
| |
| /// Protocol through which a parent node controls one of its children. |
| open protocol NodeController { |
| /// Removes the node and all of its children. |
| flexible Remove(); |
| |
| /// Request that the framework attempts to bind a driver to this node. |
| /// This is an *additional* request for binding as the framework attempts to bind a node once |
| /// when the node is created. |
| /// * error `ZX_ERR_ALREADY_BOUND` if the node is already bound and `force_rebind` is false. |
| /// * error `ZX_ERR_ALREADY_EXISTS` if the node has an outstanding |RequestBind| call which has |
| /// not completed. |
| flexible RequestBind(table { |
| /// If this is true, then the node unbinds from its matched driver before it attempts to |
| /// bind through the normal bind process. |
| 1: force_rebind bool; |
| /// If this is set, then only drivers matching this URL suffix will be considered in |
| /// binding. |
| /// E.g: "gpt.cm", "meta/gpt.cm", "fuchsia-boot:///#meta/gpt.cm". |
| 2: driver_url_suffix string:MAX; |
| }) -> () error zx.Status; |
| |
| |
| /// Event that is triggered when the associated `Node` is bound to a driver. |
| flexible -> OnBind(resource table { |
| /// Provides a token representing this node which can be exchanged with the |
| /// driver framework to discern additional information about this node. |
| @available(added=28) |
| 1: node_token zx.Handle:EVENT; |
| }); |
| }; |
| |
| /// Error codes for the Node protocol. |
| type NodeError = flexible enum { |
| // An internal error occurred. |
| INTERNAL = 1; |
| // The Node was removed from the topology. |
| NODE_REMOVED = 2; |
| // The Node's name is missing. |
| NAME_MISSING = 3; |
| /// The Node's name is invalid. Specifically, it must not contain a period |
| /// in its name. |
| NAME_INVALID = 4; |
| /// A sibling Node exists with the same name. |
| NAME_ALREADY_EXISTS = 5; |
| /// An offer for this Node is missing a source name. |
| OFFER_SOURCE_NAME_MISSING = 6; |
| /// An offer for this Node should not have a source or target. |
| OFFER_REF_EXISTS = 7; |
| /// A symbol for this Node is missing a name. |
| SYMBOL_NAME_MISSING = 8; |
| /// A symbol for this Node is missing an address. |
| SYMBOL_ADDRESS_MISSING = 9; |
| /// There is another symbol for this Node with the same name. |
| SYMBOL_ALREADY_EXISTS = 10; |
| /// The node is in the process of unbinding all of its children. |
| @available(added=20) |
| UNBIND_CHILDREN_IN_PROGRESS = 11; |
| |
| /// The Node contains unsupported arguments, such as deprecated property keys or offers. |
| @available(added=26) |
| UNSUPPORTED_ARGS = 12; |
| |
| /// The Node contains multiple properties with the same key. |
| @available(added=28) |
| DUPLICATE_PROPERTY_KEYS = 13; |
| |
| /// The Node is missing source instance filters, |
| @available(added=NEXT) |
| OFFER_SOURCE_INSTANCE_FILTER_MISSING = 14; |
| |
| /// The Node is missing renamed instances, |
| @available(added=NEXT) |
| OFFER_RENAMED_INSTANCES_MISSING = 15; |
| }; |
| |
| /// Protocol through which a driver manages a node that it is bound to. |
| /// Drivers should maintain their client connection to the node. Dropping |
| /// the client connection while the driver is running will cause the |
| /// driver framework to remove the driver and node from the topology. |
| /// If the driver has set `host_restart_on_crash` to "true" in their |
| /// component manifest, dropping the connection will initiate a restart of |
| /// the driver host and driver. |
| open protocol Node { |
| /// Adds a child node to this node. |
| /// |
| /// If `node` is present, this driver takes responsibility for binding to |
| /// the newly created child. Otherwise, the driver framework will locate an |
| /// appropriate driver to bind the child to. |
| flexible AddChild(resource struct { |
| args NodeAddArgs; |
| controller server_end:NodeController; |
| node server_end:<Node, optional>; |
| }) -> () error NodeError; |
| }; |