blob: 3eae9cd93bba2efcb3ae17c881d3b5721b4fceb7 [file] [log] [blame]
// 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;
};