or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

device-operations.mdevent-codes.mdevent-processing.mdforce-feedback.mdindex.mdvirtual-devices.md
tile.json

tessl/pypi-evdev

Python bindings to the Linux input handling subsystem for reading input events and creating virtual input devices

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/evdev@1.9.x

To install, run

npx @tessl/cli install tessl/pypi-evdev@1.9.0

index.mddocs/

evdev

Python bindings to the Linux input handling subsystem, providing access to input events from devices like keyboards, mice, joysticks, and touchscreens. The package enables both reading input events from existing devices and creating virtual input devices to inject events into the Linux input subsystem.

Package Information

  • Package Name: evdev
  • Language: Python
  • Installation: pip install evdev
  • Minimum Python: 3.8+
  • Platform: Linux (requires kernel with evdev support)

Core Imports

import evdev

Common patterns:

import os
from evdev import InputDevice, UInput, categorize, ecodes

For specific functionality:

from evdev import list_devices, resolve_ecodes, resolve_ecodes_dict
from evdev.ff import Effect, Rumble, Constant, Periodic, Condition

Basic Usage

Reading from Input Devices

from evdev import InputDevice, categorize, ecodes

# Open an input device
device = InputDevice('/dev/input/event0')

# Read events continuously
for event in device.read_loop():
    if event.type == ecodes.EV_KEY:
        key_event = categorize(event)
        print(f'Key {key_event.keycode} {key_event.keystate}')

Creating Virtual Input Devices

from evdev import UInput, ecodes

# Create a virtual input device
ui = UInput()

# Send a key press
ui.write(ecodes.EV_KEY, ecodes.KEY_A, 1)  # Press
ui.write(ecodes.EV_KEY, ecodes.KEY_A, 0)  # Release
ui.syn()

ui.close()

Discovering Available Devices

from evdev import list_devices, InputDevice

# List all available input devices
devices = list_devices()
for device_path in devices:
    device = InputDevice(device_path)
    print(f'{device.path}: {device.name}')

Architecture

The evdev package is built around several core components:

  • InputDevice: Represents physical input devices for reading events and device information
  • UInput: Creates virtual input devices for event injection
  • Event System: Hierarchical event classes (InputEvent, KeyEvent, etc.) for structured event handling
  • Event Codes: Comprehensive constants mapping (ecodes module) for all Linux input event types
  • Utilities: Helper functions for device discovery, event categorization, and code resolution
  • Force Feedback: Support for haptic feedback effects on compatible devices

The design closely mirrors the Linux kernel's input subsystem, providing a Pythonic interface to evdev character devices while maintaining full access to low-level capabilities.

Capabilities

Device Operations

Core functionality for opening, reading from, and controlling input devices. Includes device discovery, capability querying, event reading, and exclusive device access.

class InputDevice:
    def __init__(self, dev: Union[str, bytes, os.PathLike]) -> None: ...
    def capabilities(self, verbose: bool = False, absinfo: bool = True) -> Dict: ...
    def read_loop(self) -> Iterator[InputEvent]: ...
    def read_one(self) -> Union[InputEvent, None]: ...
    def grab(self) -> None: ...
    def close(self) -> None: ...

def list_devices(input_device_dir: Union[str, bytes, os.PathLike] = "/dev/input") -> List[str]: ...

Device Operations

Event Processing

Event classes and utilities for handling, categorizing, and interpreting input events from devices. Includes typed event classes and event processing utilities.

class InputEvent:
    def __init__(self, sec: int, usec: int, type: int, code: int, value: int) -> None: ...
    def timestamp(self) -> float: ...

class KeyEvent:
    def __init__(self, event: InputEvent, allow_unknown: bool = False) -> None: ...

def categorize(event: InputEvent) -> Union[InputEvent, KeyEvent, RelEvent, AbsEvent, SynEvent]: ...

Event Processing

Virtual Input Devices

Creating and managing virtual input devices using UInput to inject events into the Linux input subsystem. Supports creating devices with custom capabilities and sending events programmatically.

class UInput:
    def __init__(
        self,
        events: Optional[Dict[int, Sequence[int]]] = None,
        name: str = "py-evdev-uinput",
        vendor: int = 0x1,
        product: int = 0x1,
        version: int = 0x1,
        bustype: int = 0x3,
        devnode: str = "/dev/uinput",
        phys: str = "py-evdev-uinput",
        input_props=None,
        max_effects: int = 96
    ) -> None: ...
    
    def write(self, etype: int, code: int, value: int) -> None: ...
    def syn(self) -> None: ...
    def close(self) -> None: ...

Virtual Input Devices

Event Codes and Constants

Comprehensive mapping of Linux input subsystem constants and utilities for resolving event codes to human-readable names. Includes all event types, key codes, and constant mappings.

# Event type constants
EV_KEY: int
EV_REL: int  
EV_ABS: int
EV_SYN: int

# Key code dictionaries
KEY: Dict[int, str]
BTN: Dict[int, str]
ABS: Dict[int, str]
REL: Dict[int, str]

def resolve_ecodes(ecode_dict, ecode_list, unknown: str = "?") -> List: ...
def resolve_ecodes_dict(typecodemap, unknown: str = "?") -> Iterator: ...
def find_ecodes_by_regex(regex) -> Dict[int, List[int]]: ...

Event Codes and Constants

Force Feedback

Support for force feedback effects on compatible devices. Includes effect structures, uploading effects, and controlling haptic feedback.

class Effect(ctypes.Structure): ...
class Rumble(ctypes.Structure): ...
class Constant(ctypes.Structure): ...
class Periodic(ctypes.Structure): ...

Force Feedback

Async Support

The evdev package provides async support for non-blocking event reading through the eventio_async module (when available):

class ReadIterator:
    """Async iterator for reading input events"""
    def __aiter__(self) -> ReadIterator: ...
    def __anext__(self) -> Awaitable[InputEvent]: ...

Async usage:

import asyncio
from evdev import InputDevice

async def read_events():
    device = InputDevice('/dev/input/event0')
    
    # Async event reading
    async for event in device.async_read_loop():
        print(f'Event: {event.type} {event.code} {event.value}')
        
    # Single async read
    event = await device.async_read_one()
    if event:
        print(f'Single event: {event}')

Error Handling

The package defines specific exceptions for different error conditions:

class EvdevError(Exception):
    """Base exception for evdev-related errors"""

class UInputError(Exception):
    """Exception for UInput-specific errors"""

Common error scenarios include device access permissions, invalid device paths, and UInput device creation failures.

Types

class AbsInfo(NamedTuple):
    """Absolute axis information"""
    value: int
    min: int
    max: int
    fuzz: int
    flat: int
    resolution: int

class DeviceInfo(NamedTuple):
    """Device identification information"""
    bustype: int
    vendor: int
    product: int
    version: int

class KbdInfo(NamedTuple):
    """Keyboard repeat rate information"""
    delay: int
    repeat: int

Usage examples:

# Get current repeat settings
device = InputDevice('/dev/input/event0')
kbd_info = device.repeat
print(f"Delay: {kbd_info.delay}ms, Rate: {kbd_info.repeat} chars/sec")

# Set new repeat settings  
device.repeat = KbdInfo(500, 30)  # 500ms delay, 30 chars/sec