# Interface YAML D-Bus interfaces can be defined by creating a YAML file to describe the methods, properties, and signals they contain. From this YAML file, both documentation and binding code may be generated. ## YAML sections An interface YAML may have the following sections: - description - A small documentation section describing the purpose of the interface. - methods - A list of methods provided by this D-Bus interface. - properties - A list of properties provided by this D-Bus interface. - signals - A list of signals generated by this D-Bus interface. - enumerations - A list of enumerations defined by this D-Bus interface. - paths - A list of D-Bus paths where this D-Bus interface will be implemented. - service_names - A default service name or a list of service names which can host this D-Bus interface. ## Enumerations A common problem we have found with D-Bus interfaces is having a consistent way to define enumerations. Two common practices are to either assign special meaning to integers, as a C compiler might do, or to have specific strings representing the enumeration name. The [D-Bus API design guidelines][dbus-design-guidelines] specify both of these options: > For APIs being used in constrained situations, enumerated values should be > transmitted as unsigned integers. For APIs which need to be extended by third > parties or which are used in more loosely coupled systems, enumerated values > should be strings in some defined format. What we have done in `sdbus++` is to consider enumerations as a first-class type. Within an interface you can define an enumeration and the bindings will have a C++ enumeration defined for it. At a D-Bus level any property or method parameter will be a string, but the string will contain a fully-qualified name "interface.enum-name.enum-value" like "org.freedesktop.Example.Color.Red". Within the generated bindings, an automatic conversion is done between strings and C++ enumeration values and clients will get an "xyz.openbmc_project.sdbusplus.Error.InvalidEnumString" error response if they attempt to use an invalid string value. An enumeration must have the YAML properties `name` and `values` and may optionally contain a `description`. The `name` is a word corresponding to the desired "enum-name" portion of the fully-qualified name and the resulting C++ enum type. The `values` are a list of enumeration values each containing their own `name` and optional `description`. Example: ```yaml enumerations: - name: Suits description: > The suits found in a deck of cards. values: - name: Diamonds - name: Hearts - name: Clubs description: > This is the suit that looks like a clover. - name: Spades ``` ## Types ### Base types Types are identified in YAML using their typename found in the [D-Bus specification][dbus-spec], but listed using lowercases: `int64` instead of `INT64` or C++ `int64_t`. - `byte` - `boolean` - `int16` - `uint16` - ... - `uint64` - `size` - maps to the C `size_t` for the architecture. - `ssize` - maps to the C `ssize_t` for the architecture. - `double` - `unixfd` - `string` - `object_path` - `signature` ### Special type values Note: The special value identifiers are all case-insensitive. For floating-point types it is possible to express one of the special values: - `NaN` - A quiet-type not-a-number value. - `Infinity` : A positive infinity value. - `-Infinity` : A negative infinity value. - `Epsilon` : An epsilon value. For integer types it is possible to express one of the special values: - `minint` - The minimum value the integer type can hold. - `maxint` - The maximum value the integer type can hold. ### Container Types Container types can also be expressed, but the contained-type should be expressed within square-brackets `[]`. The following containers are supported: - `array[type]` - C++ type is `std::vector` - `dict[keytype, valuetype]` - C++ type is `std::map` - `set[type]` - C++ type is `std::set` - `struct[type0, type1, ...]` - C++ type is `std::tuple` - `variant[type0, type1, ...]` - C++ type is `std::variant` It may seem odd that variants are required to list the types they may contain, but this is due to C++ being a strongly-typed language. In order to generate bindings, to read from and append to a message, the binding generator must know all possible types the variant may contain. ### Enumeration Types Enumerations are expressed like a container, but the contained-type is an identifier of the fully-qualified enum-name or a shortened `self.` identifier for locally defined types. - enum[org.freedesktop.Example.Suits] - enum[self.Suits] ## Methods A method must have the YAML property `name` and may optionally have `parameters`, `returns`, `flags`, `errors`, and `description`. Each parameter must have a `name`, `type`, and optional `description`. Each return must have a `type` and may optionally have a `name` and `description`. Flags are a list of sd-bus vtable flags; the supported values are `deprecated`, `hidden`, `unprivileged`and `no_reply`, which corresponds to `SD_BUS_VTABLE_DEPRECATED`, `SD_BUS_VTABLE_HIDDEN`, `SD_BUS_VTABLE_UNPRIVILEGED`, `SD_BUS_VTABLE_METHOD_NO_REPLY`, respectively. Errors are a list of fully-qualified or shortened `self.` identifiers for errors the method may return, which must be defined in a corresponding errors YAML file. Example: ```yaml methods: - name: Shuffle flags: - unprivileged errors: - self.Error.TooTired - name: Deal description: > Deals a new hand to each player. errors: - self.Error.OutOfCards - name: LookAtTop returns: - name: Card type: struct[enum[self.Suit], byte] - name: MoveToTop flags: - deprecated - no_reply parameters: - name: Card type: struct[enum[self.Suit], byte] ``` ## Properties A property must have the YAML property `name` and `type` and may optionally have `description`, `flags`, `default`, and `errors`. The `default` defines the default value of the property. See the `Methods` section above for more information on errors. The supported values for `flags` are and their equivalent sd-bus flag setting: - `deprecated` - SD_BUS_VTABLE_DEPRECATED - `hidden` - SD_BUS_VTABLE_HIDDEN - `unprivileged` - SD_BUS_VTABLE_UNPRIVILEGED - `const` - SD_BUS_VTABLE_PROPERTY_CONST - `emits_change` - SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE - `emits_invalidation` - SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION - `explicit` - SD_BUS_VTABLE_PROPERTY_EXPLICIT - `readonly` - (N/A) If no flag is given, a property will default to `emits_change`. Both `const` and `readonly` prevent D-Bus clients from being able to write to a property. `const` is a D-Bus indication that the property can never change, while `readonly` properties can be changed by the D-Bus server itself. As examples, the `Version` property on a software object might be appropriate to be `const` and the `Value` property on a sensor object would likely be `readonly`. Example: ```yaml properties: - name: CardsRemaining type: uint32 default: 52 flags: - const description: > The number of cards remaining in the deck. errors: - self.Error.InvalidNumber ``` ## Signals A signal must have the YAML property `name` and may optionally have a `description` and list of `properties`. Properties are specified the same as interface properties. Example: ```yaml signals: - name: Shuffled description: > The deck has been shuffled. - name: Cheated properties: - name: CardToTop type: struct[enum[self.Suit], byte] ``` [dbus-design-guidelines]: https://dbus.freedesktop.org/doc/dbus-api-design.html [dbus-spec]: https://dbus.freedesktop.org/doc/dbus-specification.html ## Paths A path must have the YAML property `name` & `value` and may optionally have a `description` and `segments`. Each `segments` entry must have the YAML property `name` & `value` and may optionally have a `description` & nested `segments`. Example: ```yaml paths: - name: CardGames description: > The root path for the card games. value: /xyz/openbmc_project/card_games segments: - name: BlackJack description: > The relative path for the black jack game. value: black_jack - name: Rummy description: > The relative path for the rummy game. value: rummy ``` A common approach is to have a single path which is used as a root of all instances, which is often documented as a "namespace". For convenience, this can be represented with a single `namespace` value. If the interface is intended to be used as a singleton at a specific object path, similarly the `instance` value can be used. Example: ```yaml paths: - namespace: /xyz/openbmc_project/decks description: > The root path for all decks. - instance: /xyz/openbmc_projects/decks/standard description: > The root path for a standard deck of cards. ``` ## Service Name An interface can be implemented either by a single service or multiple services. ### Singleton host service name A singleton host service name must have the YAML property `default` and may optionally have a `description`. `xyz.openbmc_project.ObjectMapper` is one such example. Example: ```yaml service_names: default: xyz.openbmc_project.deck description: > The service name for the card deck manager. ``` ### Multiton host service names A multiton host service name must have the YAML property `name` & `value` and may optionally have a `description`. Example: ```yaml service_names: - name: BlackJack description: > The service name for the Back Jack game manager. value: xyz.openbmc_project.black_jack - name: Rummy description: > The service name for rummy game manager. value: xyz.openbmc_project.rummy ```