summaryrefslogtreecommitdiffstats
path: root/docs/interface.md
blob: f813e3132c4b2b2935e8e36082ac5a13fe992a54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# 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.

## 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](https://dbus.freedesktop.org/doc/dbus-api-design.html)
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:
```
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](https://dbus.freedesktop.org/doc/dbus-specification.html),
but listed using lowercases: `int64` instead of `INT64` or C++ `int64_t`.

* byte
* boolean
* int16
* uint16
* ...
* uint64
* double
* unixfd
* string
* object_path
* signature

### Containers
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`
* `struct[type0, type1, ...]`
    - C++ type is `std::tuple`
* `variant[type0, type1, ...]`
    - C++ type is `std::variant`
* `dict[keytype, valuetype]`
    - C++ type is `std::map`

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.

### Enumerations
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`, `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`.  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:
```
methods:
    - name: Shuffle
      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
      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 only current supported value for `flags` is `const`, which corresponds to
SD_BUS_VTABLE_PROPERTY_CONST, making the property read-only via D-Bus but
still writable by the app implementing it.

Example:
```
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:
```
signals:
    - name: Shuffled
      description: >
        The deck has been shuffled.
    - name: Cheated
      properties:
        - name: CardToTop
          type: struct[enum[self.Suit], byte]
```
OpenPOWER on IntegriCloud