evdev

The evdev driver reads touchscreen, mouse and keyboard input straight from Linux /dev/input event devices, with no user-space input library required.

Edit on GitHub

Overview

The Linux event device (evdev) interface exposes input events from a touchscreen, mouse, keyboard or anything else the kernel recognizes, through device files under /dev/input/.

It's the lightest input option on Linux and the natural pairing for the framebuffer and DRM display drivers, neither of which brings its own input.

Prerequisites

An input device under /dev/input/, typically /dev/input/event0, and permission to read it.

Configuration

Enable LV_USE_EVDEV.

Building

The driver always requires libevdev.

LVGL's CMake integration resolves both. Make sure the required libraries are present on your system or in your sysroot.

See Dependency Management.

Usage

Create an input device with lv_evdev_create, giving it the device type and node path, then attach it to a display with lv_indev_set_display.

 
lv_display_t * disp = lv_linux_fbdev_create();
lv_linux_fbdev_set_file(disp, "/dev/fb0");

lv_indev_t * touch = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event0");
lv_indev_set_display(touch, disp);

The type is LV_INDEV_TYPE_POINTER for mice and touchscreens, or LV_INDEV_TYPE_KEYPAD for keyboards. lv_evdev_create_fd takes an already open file descriptor instead of a path, and lv_evdev_delete removes a device.

Finding your input device

List what the kernel sees:

sh
cat /proc/bus/input/devices

Entries mention an event handler. event1 corresponds to /dev/input/event1. Confirm you picked the right one by watching its events:

sh
evtest /dev/input/event1

Calibrating a touchscreen

Raw touchscreens report device coordinates, not screen coordinates. Map them with lv_evdev_set_calibration, and correct a transposed panel with lv_evdev_set_swap_axes.

 
lv_evdev_set_swap_axes(touch, true);
lv_evdev_set_calibration(touch, min_x, min_y, max_x, max_y);

Automatic device discovery

Rather than naming device nodes, let the driver find them. lv_evdev_discovery_start scans /dev/input/ and keeps watching it, so devices plugged in later are added automatically. Passing NULL for both arguments is enough to enable it:

 
lv_evdev_discovery_start(NULL, NULL);

Supply a callback when you need to react to a new device — to attach a cursor image to a mouse, for example:

 
#include "lvgl/src/core/lv_global.h"

static void indev_deleted_cb(lv_event_t * e)
{
    if(LV_GLOBAL_DEFAULT()->deinit_in_progress) return;
    lv_obj_t * cursor_obj = lv_event_get_user_data(e);
    lv_obj_delete(cursor_obj);
}

static void discovery_cb(lv_indev_t * indev, lv_evdev_type_t type, void * user_data)
{
    LV_LOG_USER("new '%s' device discovered", type == LV_EVDEV_TYPE_REL ? "REL" :
                                             type == LV_EVDEV_TYPE_ABS ? "ABS" :
                                             type == LV_EVDEV_TYPE_KEY ? "KEY" :
                                             "unknown");

    if(type == LV_EVDEV_TYPE_REL) {
        LV_IMAGE_DECLARE(mouse_cursor_icon);
        lv_obj_t * cursor_obj = lv_image_create(lv_screen_active());
        lv_image_set_src(cursor_obj, &mouse_cursor_icon);
        lv_indev_set_cursor(indev, cursor_obj);
        lv_indev_add_event_cb(indev, indev_deleted_cb, LV_EVENT_DELETE, cursor_obj);
    }
}

int main(void)
{
    /* ... */
    lv_evdev_discovery_start(discovery_cb, NULL);
    /* ... */
}

lv_evdev_discovery_stop turns it off again.

Discovery relies on inotify and is not available on BSD. Create devices explicitly there.

Raw key codes

For keys LVGL does not map to one of its own, lv_evdev_is_raw_key tells you an event carries a raw code and lv_evdev_get_raw_key returns it. Use these when you need keys outside LVGL's navigation set.

Support

CapabilityValue
Device typesPointer (mouse, touchscreen) and keypad
Automatic discoveryYes — lv_evdev_discovery_start
HotplugYes — devices connected later are added automatically
Full keyboard (layouts, modifiers)No — use libinput with XKB
Touch calibrationYes — lv_evdev_set_calibration
Axis swapYes — lv_evdev_set_swap_axes
Find device by capabilityNo — pass a node path, or use discovery
BSDYes, except discovery and hotplug

See Also

Last updated on

On this page