mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2025-12-27 18:30:09 +01:00
doc/proto: address a few documentation issues
A few clarifications as suggested by Benjamin Tissoires.
This commit is contained in:
parent
150ac5b4ac
commit
c5aa2c0b60
5 changed files with 96 additions and 43 deletions
|
|
@ -14,21 +14,32 @@ server side, typically a Wayland compositor, is called the **"EIS Implementation
|
|||
This documentation details the protocol to communicate between the client side
|
||||
and the EIS implementation.
|
||||
|
||||
A typical setup using the [C libraries]({{< ref "libraries" >}}) looks like this:
|
||||
A typical Compositor setup using the `libei` and `libeis` [C libraries]({{< ref "libraries" >}}) looks like this:
|
||||
|
||||
{{< mermaid >}}
|
||||
graph LR;
|
||||
flowchart LR;
|
||||
libwayland-server --> c1
|
||||
libwayland-server --> c2
|
||||
/dev/input/event0 ---> libinput
|
||||
libeis-- ei protocol ---libei
|
||||
/dev/input/event1 ---> libinput
|
||||
libei -.-> libeis
|
||||
libinput --> inputstack
|
||||
inputstack --> libwayland-server
|
||||
libeis -.-> inputstack
|
||||
subgraph Kernel
|
||||
/dev/input/event0
|
||||
/dev/input/event1
|
||||
end
|
||||
subgraph Wayland Compositor
|
||||
libwayland-server
|
||||
inputstack[input stack]
|
||||
libinput
|
||||
libeis
|
||||
end
|
||||
subgraph Wayland client A
|
||||
subgraph EI client
|
||||
libei
|
||||
end
|
||||
subgraph Wayland client A
|
||||
c1[libwayland-client]
|
||||
end
|
||||
subgraph Wayland client B
|
||||
|
|
@ -36,6 +47,19 @@ graph LR;
|
|||
end
|
||||
{{< /mermaid >}}
|
||||
|
||||
Note how the EI client is roughly equivalent to a physical input device coming
|
||||
from the kernel and its events feed into the normal input stack.
|
||||
However, the events are distinguishable inside the compositor to allow for
|
||||
fine-grained access control on which events may be emulated and when emulation is
|
||||
permitted.
|
||||
|
||||
Events from the EIS implementation would usually feed into the input stack in the
|
||||
same way as input events from physical devices. To Wayland clients, they are
|
||||
indistinguishable from real devices.
|
||||
|
||||
The EI client may be a Wayland client itself.
|
||||
|
||||
## EI Protocol
|
||||
|
||||
The ei protocol is a public protocol that may be used directly by clients or
|
||||
EIS implementations. This documentation describes the protocol, its interfaces
|
||||
|
|
|
|||
|
|
@ -59,10 +59,21 @@ sequenceDiagram
|
|||
Note over client, EIS: ei_handshake object is destroyed
|
||||
|
||||
EIS-->>client: ei_connection.seat(new_id, version)
|
||||
EIS-->>client: ei_seat.name(some seat)
|
||||
EIS-->>client: ei_seat.capabilities()
|
||||
EIS-->>client: ei_seat.done()
|
||||
client->>EIS: ei_seat.bind()
|
||||
EIS-->>client: ei_seat.device(new_id, version)
|
||||
EIS-->>client: ei_device.name(some name)
|
||||
EIS-->>client: ei_device.device_type()
|
||||
EIS-->>client: ei_device.capabilities(some name)
|
||||
EIS-->>client: ei_device.pointer(new_id, version)
|
||||
EIS-->>client: ei_device.keyboard(new_id, version)
|
||||
EIS-->>client: ei_seat.device(new_id, version)
|
||||
EIS-->>client: ei_device.name(some name)
|
||||
EIS-->>client: ei_device.device_type()
|
||||
EIS-->>client: ei_device.capabilities(some name)
|
||||
EIS-->>client: ei_device.region()
|
||||
EIS-->>client: ei_device.touchscreen(new_id, version)
|
||||
|
||||
EIS-->>client: ei_device.resume()
|
||||
|
|
|
|||
|
|
@ -7,52 +7,67 @@ weight: 1
|
|||
|
||||
## Protocol Components
|
||||
|
||||
The ei protocol has three components: **objects**, **requests** and
|
||||
**events**. It is designed to be connect two processes over a UNIX socket -
|
||||
an ei client and an EIS implementation (typically a Wayland compositor). The
|
||||
protocol is asynchronous and object-based.
|
||||
The protocol is designed to connect two processes over a UNIX socket - an ei
|
||||
client and an EIS implementation (typically a Wayland compositor).
|
||||
|
||||
Whenever a message (request or event) is sent, that message carries an
|
||||
identifier for the object. The type of an object is defined by its interface -
|
||||
the interfaces are detailed here in this protocol. Thus, when a message for an
|
||||
object arrives, the client or EIS implementation can invoke the corresponding
|
||||
function on the object.
|
||||
{{< mermaid >}}
|
||||
flowchart LR;
|
||||
subgraph EIS implementation
|
||||
socket[[ei.socket]]
|
||||
end
|
||||
c1[ei client 1] -- ei protocol --> socket
|
||||
c2[ei client 2] -- ei protocol --> socket
|
||||
{{< /mermaid >}}
|
||||
|
||||
An object has exactly one interface but there may be multiple objects with
|
||||
the same interface (e.g. multiple devices all use the ei_device interface).
|
||||
The protocol is asynchronous and object-oriented. Each object on the wire supports
|
||||
zero or more **requests** and zero or more **events**. Requests are messages
|
||||
sent from an ei client to an EIS implementation, events are messages sent from
|
||||
the EIS implementation to the client.
|
||||
|
||||
Requests are messages sent from an ei client to an EIS implementation, events
|
||||
are messages sent from the EIS implementation to the client. This is the same
|
||||
nomenclature that the Wayland protocol uses.
|
||||
{{< mermaid >}}
|
||||
flowchart LR;
|
||||
ei -- request --> eis
|
||||
eis -- event --> ei
|
||||
{{< /mermaid >}}
|
||||
|
||||
Objects are identified by a unique object ID, assigned at creation of the object.
|
||||
The type of an object is defined by its [interface]({{< relref "interfaces" >}})
|
||||
and agreed on at object creation. Each object has exactly one interface, but
|
||||
there may be multiple objects with that interface. For example, a compositor
|
||||
may create multiple objects with the [`ei_device`]({{< relref "interfaces/ei_device" >}})
|
||||
interface.
|
||||
|
||||
All data on the protocol (e.g. object IDs) is private to that client's
|
||||
connection.
|
||||
|
||||
The ei protocol is modelled closely after the Wayland protocol, but it is not
|
||||
binary compatible.
|
||||
|
||||
## Wire Format
|
||||
|
||||
The wire format consists of a 3-element header comprising the `sender-id` of
|
||||
The wire format consists of a 3-element header comprising the `object-id` of
|
||||
the object, the length of the message and the opcode representing the message
|
||||
itself.
|
||||
|
||||
```
|
||||
byte: |0 |4 |8 |12 |16
|
||||
content: |sender-id |length |opcode |...
|
||||
content: |object-id |length |opcode |...
|
||||
```
|
||||
|
||||
Where:
|
||||
- `sender-id` is one 64-bit unsigned integer
|
||||
- `length` and `opcode` are 32-bit unsigned integers
|
||||
- all integers are in the EIS implementation's native byte order.
|
||||
- `length` is the length of the message in bytes, including the 16 header bytes
|
||||
for `sender-id`, `length` and `opcode`.
|
||||
- `sender-id` is the id of the object sending the request/event. The sender-id
|
||||
- `object-id` is one 64-bit unsigned integer that uniquely identifies
|
||||
the object sending the request/event. The `object-id`
|
||||
0 is reserved for the special [`ei_handshake`]({{< relref "interfaces/ei_handshake" >}}) object.
|
||||
- `opcode` is the event or request-specific opcode, starting at 0.
|
||||
requests and events have overlapping opcode ranges, i.e. the first request
|
||||
and the first event both have opcode 0.
|
||||
- `length` is a 32-bit integer that specifies the length of the message in
|
||||
bytes, including the 16 header bytes for `object-id`, `length` and `opcode`.
|
||||
- `opcode` is a 32-bit integer that specifies the event or request-specific
|
||||
opcode, starting at 0. Requests and events have overlapping opcode ranges,
|
||||
i.e. the first request and the first event both have opcode 0.
|
||||
|
||||
The header is followed by the message-specific arguments. All arguments are 4 bytes or
|
||||
padded to a multiple of 4 bytes.
|
||||
The header is followed by the message-specific arguments (if any). All
|
||||
arguments are 4 bytes or padded to a multiple of 4 bytes.
|
||||
|
||||
All integers are in the EIS implementation's native byte order.
|
||||
|
||||
## Version negotiation
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ archetype: "chapter"
|
|||
weight: 3
|
||||
---
|
||||
|
||||
The current protocol specification is available [in xml format here](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.xml) and the corresponding [XML DTD here](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.dtd).
|
||||
The current protocol specification is available [in XML format here](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.xml) and the corresponding [XML DTD here](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.dtd).
|
||||
|
||||
|
||||
In that protocol specification:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ weight: 2
|
|||
|
||||
## Protocol Types
|
||||
|
||||
The protocol types are described as used in the [protocol specification](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.xml)
|
||||
The protocol types are described as used in the [protocol specification](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.xml).
|
||||
|
||||
All types are encoded in the EIS implementation's native byte order.
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ All types are encoded in the EIS implementation's native byte order.
|
|||
| int64 | 64 | signed integer | `int64_t` | |
|
||||
| float | 32 | IEEE-754 float | `float` | |
|
||||
| fd | 0 | file descriptor | `int` | see [^1] |
|
||||
| string | 4 + N | length + string | `int`, `char *` | see [String Encoding]({{< ref "#string-encoding" >}}) |
|
||||
| string | 32 + N| length + string | `int`, `char[]` | see [String Encoding]({{< ref "#string-encoding" >}}) |
|
||||
| new_id | 64 | object id allocated by the caller | `uint64_t` | see [Object IDs]({{< ref "#object-ids" >}}) |
|
||||
| object_id | 64 | previously allocated object id | `uint64_t` | see [Object IDs]({{< ref "#object-ids" >}}) |
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ length field thus takes 12 bytes in total. Full (le) encoding:
|
|||
|
||||
Object IDs are unique, monotonically increasing 64-bit integers that must not
|
||||
be re-used by the client or the EIS implementation. Object IDs created by the
|
||||
client at 1 and must be less than `0xff00000000000000`. Object IDs allocated by
|
||||
client start at 1 and must be less than `0xff00000000000000`. Object IDs allocated by
|
||||
the EIS implementation start at and must not be less than `0xff00000000000000`.
|
||||
|
||||
Where a request or event specifies a `new_id` argument, it is the caller's responsibility
|
||||
|
|
@ -73,17 +73,20 @@ and must not be re-used.
|
|||
|
||||
Some requests and events, for example `ei_handshake.interface_version` require arguments
|
||||
that represent interface names. Interface names on the wire are always in the
|
||||
form "`ei_foo`, i.e. lowercase snake_case spelling, as used in the [protocol specification](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.xml).
|
||||
form "`ei_foo`", i.e. lowercase snake_case spelling, as used in the [protocol specification](https://gitlab.freedesktop.org/libinput/libei/-/tree/main/proto/protocol.xml).
|
||||
|
||||
### Serial numbers
|
||||
|
||||
Some events have serial numbers assigned by the EIS implementation. A serial is
|
||||
a monotonically increasing unsigned 32-bit number (that wraps, clients must handle
|
||||
this). Clients must use the most recently seen EIS serial number in requests that have
|
||||
a last_serial argument.
|
||||
Some events have a `serial` argument corresponding to a serial number assigned
|
||||
by the EIS implementation. The serial number is a monotonically increasing
|
||||
unsigned 32-bit number (that wraps, clients must handle this). Some requests
|
||||
have a `last_serial` argument that clients must set to the most recently seen
|
||||
EIS serial number.
|
||||
|
||||
The serial number aims to help a client track failure cases and the EIS
|
||||
implementation to detect errors caused by the protocol's asynchronicity.
|
||||
For example, if the EIS implementation removes a device at the serial number N,
|
||||
client-initiated events for N-1 are caused by the client lagging behind and are not
|
||||
a protocol violation.
|
||||
For example, if the EIS implementation pauses a device at the serial number N and
|
||||
subsequently receives an event with a `last_serial` of N-1, the EIS implementation
|
||||
knows that the events were caused by the client lagging behind and are not
|
||||
a protocol violation. The events can thus be discarded but the client does not
|
||||
need to be disconnected.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue