evdi-sys 0.3.1

Low level bindings for evdi
Documentation
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
[TOC]

# API Details

## Functions by group

#### Versioning
    #!c
    evdi_get_lib_version(struct evdi_lib_version device);

Function returns library version.
It uses semantic versioning to mark compatibility changes.
Version consists of 3 components formatted as MAJOR.MINOR.PATCH

 * `MAJOR` number is changed for incompatibile API changes
 * `MINOR` number is changed for backwards-compatible changes
 * `PATCH` number is changed for backwards-compatibile bug fixes

#### Module parameters

User can modify driver behaviour by its parameters that can be set at module load time or changed during runtime.

 * `initial_device_count` Number of evdi devices added at module load time (default: 0)


### EVDI nodes

#### Finding an available EVDI node to use
    #!c
    evdi_device_status evdi_check_device(int device);

Use this function to check if a particular `/dev/dri/cardX` is EVDI or not.

**Arguments:** `device` is a number of card to check, e.g. passing `1` will mean `/dev/dri/card1`.

**Return value:**

* `AVAILABLE` if the device node is EVDI and is available to use.
* `UNRECOGNIZED` when a node has not been created by EVDI kernel module.
* `NOT_PRESENT` in other cases, e.g. when the device does not exist or cannot be opened to check.

#### Adding new EVDI node (pre v1.9.0)
    #!c
	int evdi_add_device()

Use this to tell the kernel module to create a new `cardX` node for your application to use.

**Return value:**
`1` when successful, `0` otherwise.

#### Opening device nodes (pre v1.9.0)
    #!c
	evdi_handle evdi_open(int device);

This function attempts to open a DRM device node with given number as EVDI.
Function performs compatibility check with underlying drm device. If version of the
library and module does not match then the device will not be opened.

**Arguments**: `device` is a number of card to open, e.g. `1` means `/dev/dri/card1`.

**Return value:** On success, a handle to the opened device to be used in following API calls. `EVDI_INVALID_HANDLE` otherwise.

#### Request evdi nodes (since v1.9.0)
    #!c
	evdi_handle evdi_open_attached_to(char *sysfs_parent_device);

This function attempts to add (if necessary) and open a DRM device node attached to given parent device.
Linking with another sysfs device is sometimes useful if it is required to reflect such relationship in sysfs.

The function performs a compatibility check with an underlying drm device. If version of the
library and module does not match, the device will not be opened.

**Arguments**: `sysfs_parent_device` is a string with the following format: `usb:[busNum]-[portNum1].[portNum2].[portNum3]...`, which describes the
device that evdi is linked to. Or `NULL` when evdi device node is not linked with any other device.

**Return value:** On success, a handle to the opened device to be used in following API calls. `EVDI_INVALID_HANDLE` otherwise.



#### Closing devices

    #!c
	void evdi_close(evdi_handle handle);

Closes an opened EVDI handle.

**Arguments**: `handle` to an opened device that is to be closed.

### Connection
#### Opening connections

    #!c
	void evdi_connect(evdi_handle handle,
			  const unsigned char* edid,
			  const unsigned edid_length,
			  const uint32_t sku_area_limit);

Creates a connection between the EVDI and Linux DRM subsystem, resulting in kernel mode driver processing a hot plug event.

**Arguments**:

* `handle` to an opened device
* `edid` should be a pointer to a memory block with contents of an EDID of a monitor that will be exposed to kernel
* `edid_length` is the length of the EDID block (typically 512 bytes, or more if extension blocks are present)
* `sku_area_limit` is maximum pixel area (width x height) connected device can display

#### Disconnecting

    #!c
	void evdi_disconnect(evdi_handle handle)

Breaks the connection between the device handle and DRM subsystem - resulting in an unplug event being processed.

**Arguments**: `handle` to an opened device.

### Buffers

Managing memory for frame buffers is left to the client applications.
The `evdi_buffer` structure is used to let the library know details about the frame buffer your application is working with.
For more details, see [struct evdi_buffer](details.md#evdi_buffer) description.

#### Registering
    #!c
	void evdi_register_buffer(evdi_handle handle, evdi_buffer buffer);

This function allows to register a `buffer` of type `evdi_buffer` with an opened EVDI device `handle`.

!!! warning
	Registering a buffer does not allocate memory for the frame.

#### Unregistering

    #!c
	void evdi_unregister_buffer(evdi_handle handle, int bufferId);

This function unregisters a buffer with a given `bufferId` from an opened EVDI device `handle`.

!!! warning
	Unregistering a buffer does not deallocate memory for the frame.


### Screen updates

#### Requesting an update
    #!c
	bool evdi_request_update(evdi_handle handle, int bufferId);

Requests an update for a buffer with a given `bufferId`. The buffer must be already registered with the library.

**Arguments**:

* `handle` to an opened device.
* `bufferId` is an identifier for a buffer that should be updated.

**Return value:**

The function can return `true` if the data for the buffer is ready to be grabbed immediately after the call.
If `false` is returned, then an update is not yet ready to grab and the application should wait until it gets
notified by the kernel module - see [Events and handlers](details.md#events-and-handlers).

#### Grabbing pixels

    #!c
	void evdi_grab_pixels(evdi_handle handle, evdi_rect *rects, int *num_rects);

Grabs pixels following the most recent update request (see [Requesting an update](details.md#requesting-an-update)).

This should be called either after a call to `evdi_request_update` (if it returns `true` which means pixels can be grabbed immediately),
or while handling the `update_ready` notification.

**Arguments**:

* `handle` to an opened device.
* `rects` is a pointer to the first `evdi_rect` that the library fills, based on what the kernel tells.

!!! note
    It is expected that this pointer is a beginning of an array of `evdi_rect`s, and current implementation assumes
    the array does not contain more than 16 slots for rects.

* `num_rects` is a pointer to an integer that will be modified to tell how many dirty rectangles are valid in the list,
   and the client should only care about as many. In particular, a failed grab will be indicated by `0` valid rectangles
   to take into account (this can happen when there was a mode change between the request and the grab).

### DDC/CI response

    #!c
	void evdi_ddcci_response(evdi_handle handle, const unsigned char *buffer,
		const uint32_t buffer_length, const bool result);

Pass back DDC/CI data following the most recent DDC/CI request to the EVDI kernel driver (see [DDC/CI data notification](details.md#ddcci-data-notification)).

**Arguments**:

* `handle` to an opened device.
* `buffer` a pointer to the response buffer. This will be copied into kernel space.
* `buffer_length` the length of the response buffer.
* `result` the boolean result. The caller should set `result` to true if the most recent DDC/CI request was successful and false if it was unsuccessful.  If false, `buffer` and `buffer_length` are ignored.

!!! note
	The `buffer_length` will be truncated to 64 bytes (`DDCCI_BUFFER_SIZE`).

### Events and handlers

#### DPMS mode change

    #!c
	void (*dpms_handler)(int dpms_mode, void* user_data);

This notification is sent when a DPMS mode changes.
The possible modes are as defined by the standard, and values are bit-compatible with DRM interface:

```
/* DPMS flags */
#define DRM_MODE_DPMS_ON        0
#define DRM_MODE_DPMS_STANDBY   1
#define DRM_MODE_DPMS_SUSPEND   2
#define DRM_MODE_DPMS_OFF       3
```

*[DPMS]: Display Power Management Signaling

#### Mode change notification

    #!c
	void (*mode_changed_handler)(evdi_mode mode, void* user_data);

This notification is sent when a display mode changes. Details of the new mode are sent in the `mode` argument.
See [evdi_mode](details.md#evdi_mode) for description of the structure.

#### Update ready notification

	#!c
	void (*update_ready_handler)(int buffer_to_be_updated, void* user_data);

This notification is sent when an update for a buffer, that had been earlier requested is ready to be consumed.
The buffer number to be updated is `buffer_to_be_updated`.

#### Cursor change notification

	#!c
	void (*cursor_set_handler)(struct evdi_cursor_set cursor_set, void* user_data);

This notification is sent for an update of cursor buffer or shape. It is also raised when cursor is enabled or disabled.
Such situation happens when cursor is moved on and off the screen respectively.

#### Cursor move notification

	#!c
	void (*cursor_move_handler)(struct evdi_cursor_move cursor_move, void* user_data);

This notification is sent for a cursor position change. It is raised only when cursor is positioned on virtual screen.

#### CRTC state change

	#!c
	void (*crtc_state_handler)(int state, void* user_data);

Sent when DRM's CRTC changes state. The `state` is a value that's forwarded from the kernel.

#### DDC/CI data notification

	#!c
	void (*ddcci_data_handler)(struct evdi_ddcci_data ddcci_data, void *user_data);

This notification is sent when an i2c request has been made to the DDC/CI address (0x37).

The module will wait for a maximum of DDCCI_TIMEOUT_MS (50ms - The default DDC request timeout) for a response to this request to be passed back via `evdi_ddcci_response`.

### Logging

Client can register their own callback to be used for logging instead of default `printf`.

	#!c
	void evdi_set_logging(struct evdi_logging evdi_logging);

For more on argument see [struct evdi_logging](details.md#Types).

## Types

### evdi_handle

This is a handle to an opened device node that you get from an `evdi_open` call,
and use in all following API calls to indicate which EVDI device you communicate with.

### evdi_selectable

A typedef denoting a file descriptor you can watch to know when there are events being signalled from the kernel module.
Each opened EVDI device handle has its own descriptor to watch.
When the descriptor becomes ready to read from, the application should call `evdi_handle_events` to dispatch notifications to its handlers.

### evdi_device_status

An enumerated type used while finding the DRM device node that is EVDI. Possible values are `AVAILABLE`, `UNRECOGNIZED` and `NOT_PRESENT`.

### evdi_rect

A simple structure used by the library to represent a rectangular area of a screen. Top left coordinates of the rectangle are `x1` and `y1`,
bottom right are `x2` and `y2`.

### evdi_mode

A structure used to describe a video mode that's set for a display. Contains details of resolution set (`width`, `height`), refresh rate (`refresh_rate`),
and details of a pixel format used to encode color value (`bits_per_pixel` and `pixel_format` - which are forwarded from kernel's DRM).

### evdi_buffer

A structure holding details about a buffer.

    #!c
	typedef struct {
		int id;
		void* buffer;
		int width;
		int height;
		int stride;

		evdi_rect* rects;
		int rect_count;
	} evdi_buffer;

Buffers have IDs, which can be arbitrarily chosen integer numbers - but typically a simple sequence of numbers starting
from `0` is used in client applications. The pointer to the beginning of an already allocated memory block should be assigned
to the `buffer` member of the structure. This memory will be filled by the kernel module when handling requests to grab pixels.

`width`, `height` and `stride` are properties of the buffer - the first two indicate what the size of the frame is,
and `stride` is a width stride - tells what is the increment in bytes between data for lines in memory.

Stride can be equal to width of a single line multiplied by the number of bytes necessary for encoding color value for one pixel (e.g. 4 for RGB32) if the data for lines are contigous in the memory,
but you can use larger value to indicate extra space/padding between them, e.g. oftentimes an additional requirement for the value of stride is it being divisbile by 8;
note that those values might be specific to particular hardware/graphic drivers.
Please consult documentation of your GPU for details.

Last two structure members, `rects` and `rect_counts` are updated during grabbing pixels to inform about the number and coordinates of areas that are changed from the last update.

### evdi_event_context

    #!c
	typedef struct {
	  void (*dpms_handler)(int dpms_mode, void* user_data);
	  void (*mode_changed_handler)(evdi_mode mode, void* user_data);
	  void (*update_ready_handler)(int buffer_to_be_updated, void* user_data);
	  void (*crtc_state_handler)(int state, void* user_data);
	  void (*cursor_set_handler)(struct evdi_cursor_set cursor_set, void *user_data);
	  void (*cursor_move_handler)(struct evdi_cursor_move cursor_move, void *user_data);
	  void (*ddcci_data_handler)(struct evdi_ddcci_data ddcci_data, void *user_data);
	  void* user_data;
	} evdi_event_context;

The `evdi_device_context` structure is used for holding pointers to handlers for all notifications that the application may receive from
the kernel module. The `user_data` member is a value that the library will use while dispatching the call back.
See [Events and handlers](details.md#events-and-handlers) for more information.

### evdi_lib_version

    #!c
	struct evdi_lib_version {
		int version_major;
		int version_minor;
		int version_patchlevel;
	};

The `evdi_lib_version` structure contains libevdi version.
Version can be used to check compatibility between library and a client application.

### evdi_cursor_set

    #!c
	struct evdi_cursor_set {
		int32_t hot_x;
		int32_t hot_y;
		uint32_t width;
		uint32_t height;
		uint8_t enabled;
		uint32_t buffer_length;
		uint32_t *buffer;
		uint32_t pixel_format;
		uint32_t stride;
	};

The `evdi_cursor_set` structure contains cursor state information. `hot_x` and `hot_y` define hotspot information.
`enabled` parameter is true when cursor bitmap is available and cursor is visible on virtual display.
Parameters `width` and `height` define size of the cursor bitmap stored in a `buffer` memory area of size `buffer_length`.

!!! warning
	Event handler or library user has to free buffer memory when it is not using it.

Remaining `stride` and `pixel_format` describe data organization in the buffer. `stride` is a size of a single line in a buffer.
Usually it is width of the cursor multiplied by bytes per pixel value plus additional extra padding. It ensures proper alignment of subsequent pixel rows.
Pixel encoding is described by FourCC code in `pixel_format` field.

### evdi_cursor_move

    #!c
	struct evdi_cursor_move {
		int32_t x;
		int32_t y;
	};

The `evdi_cursor_move` structure contains current cursor position.
It is defined as top left corner of the cursor bitmap.

### evdi_ddcci_data

    #!c
	struct evdi_ddcci_data {
		uint16_t address;
		uint16_t flags;
		uint32_t buffer_length;
		uint8_t *buffer;
	};

The `evdi_ddcci_data` structure contains:

* `address` i2c address, will always be 0x37.
* `flags` read/write flags.  Read = 1, Write = 0.
* `buffer_length` the length of the buffer.
* `buffer` pointer to the ddc/ci buffer.  For both read and write this will be truncated to 64 bytes (`DDCCI_BUFFER_SIZE`).

!!! warning
	Although the DDC spec advices the maximum buffer length is 32 bytes, we have identified monitors which support bigger buffers.

### evdi_logging

	#!c
	struct evdi_logging {
		void (*function)(void *user_data, const char *fmt, ...);
		void *user_data;
	};

Structure contains two fields:

* `function` which is a pointer to the actual callback. The `fmt` and `...` are the same as in case of `printf`.
* `user_data` a pointer provided by the client when registering callback

!!! note
    By setting `function` to NULL libevdi will switch to default behaviour of using `printf`.