CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-evdev

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

Pending
Overview
Eval results
Files

event-processing.mddocs/

Event Processing

Event classes and utilities for handling input events from Linux input devices. This includes the core event representation, specialized event types, and utilities for event categorization and processing.

Capabilities

Core Event Representation

The fundamental InputEvent class represents all input events from the Linux kernel.

class InputEvent:
    def __init__(self, sec: int, usec: int, type: int, code: int, value: int) -> None:
        """
        Initialize an input event.
        
        Parameters:
        - sec: Seconds since epoch when event occurred
        - usec: Microsecond portion of timestamp
        - type: Event type (EV_KEY, EV_REL, EV_ABS, etc.)
        - code: Event code specific to the event type
        - value: Event value
        """
    
    def timestamp(self) -> float:
        """
        Return event timestamp as float seconds since epoch.
        
        Returns:
        Combined sec + usec as floating point timestamp
        """
    
    # Attributes
    sec: int      # Seconds since epoch
    usec: int     # Microseconds portion
    type: int     # Event type (EV_*)
    code: int     # Event code
    value: int    # Event value

Key Events

Specialized class for keyboard and button events with enhanced key state information.

class KeyEvent:
    # Class constants for key states
    key_up: int = 0x0      # Key released
    key_down: int = 0x1    # Key pressed
    key_hold: int = 0x2    # Key held (repeat)
    
    def __init__(self, event: InputEvent, allow_unknown: bool = False) -> None:
        """
        Create KeyEvent from InputEvent.
        
        Parameters:
        - event: InputEvent with type EV_KEY
        - allow_unknown: If False, raise KeyError for unknown key codes.
                        If True, use hex value for unknown keys.
        
        Raises:
        - KeyError: If key code is unknown and allow_unknown=False
        """
    
    # Attributes
    scancode: int    # Raw scan code from event.code
    keycode: str     # Human-readable key name (e.g., "KEY_A", "BTN_LEFT")
    keystate: int    # Key state (key_up, key_down, or key_hold)
    event: InputEvent # Reference to original InputEvent

Relative Events

Events for relative positioning devices like mice and trackballs.

class RelEvent:
    def __init__(self, event: InputEvent) -> None:
        """
        Create RelEvent from InputEvent with type EV_REL.
        
        Parameters:
        - event: InputEvent with type EV_REL
        """
    
    # Attributes
    event: InputEvent # Reference to original InputEvent

Absolute Events

Events for absolute positioning devices like touchscreens and joysticks.

class AbsEvent:
    def __init__(self, event: InputEvent) -> None:
        """
        Create AbsEvent from InputEvent with type EV_ABS.
        
        Parameters:
        - event: InputEvent with type EV_ABS
        """
    
    # Attributes  
    event: InputEvent # Reference to original InputEvent

Synchronization Events

Events that mark boundaries between logical input events.

class SynEvent:
    def __init__(self, event: InputEvent) -> None:
        """
        Create SynEvent from InputEvent with type EV_SYN.
        
        Parameters:
        - event: InputEvent with type EV_SYN
        """
    
    # Attributes
    event: InputEvent # Reference to original InputEvent

Event Factory

Dictionary mapping event types to their corresponding event classes.

event_factory: Dict[int, Type] = {
    # Maps event type codes to event classes
    # EV_KEY -> KeyEvent
    # EV_REL -> RelEvent  
    # EV_ABS -> AbsEvent
    # EV_SYN -> SynEvent
}

Event Categorization

Utilities for converting generic InputEvent objects to specialized event types.

def categorize(event: InputEvent) -> Union[InputEvent, KeyEvent, RelEvent, AbsEvent, SynEvent]:
    """
    Categorize InputEvent according to its type.
    
    Uses event_factory dictionary to map event types to specialized classes.
    If event type is not found in factory, returns original InputEvent unchanged.
    
    Parameters:
    - event: InputEvent to categorize
    
    Returns:
    Specialized event object (KeyEvent, RelEvent, etc.) or original InputEvent
    """

Usage Examples

Basic Event Processing

from evdev import InputDevice, categorize, ecodes

device = InputDevice('/dev/input/event0')

for event in device.read_loop():
    # Categorize event based on type
    categorized_event = categorize(event)
    
    if isinstance(categorized_event, KeyEvent):
        print(f"Key event: {categorized_event.keycode} -> {categorized_event.keystate}")
    elif isinstance(categorized_event, RelEvent):
        print(f"Relative event: code={event.code}, value={event.value}")
    elif isinstance(categorized_event, AbsEvent):
        print(f"Absolute event: code={event.code}, value={event.value}")
    else:
        print(f"Other event: {event}")

Key State Processing

from evdev import InputDevice, categorize, ecodes, KeyEvent

device = InputDevice('/dev/input/event0')

for event in device.read_loop():
    if event.type == ecodes.EV_KEY:
        key_event = categorize(event)
        
        if key_event.keystate == KeyEvent.key_down:
            print(f"Key pressed: {key_event.keycode}")
        elif key_event.keystate == KeyEvent.key_up:
            print(f"Key released: {key_event.keycode}")
        elif key_event.keystate == KeyEvent.key_hold:
            print(f"Key held: {key_event.keycode}")

Event Filtering by Type

from evdev import InputDevice, categorize, ecodes

device = InputDevice('/dev/input/event0')

def process_events():
    for event in device.read_loop():
        if event.type == ecodes.EV_KEY:
            # Process keyboard/button events
            key_event = categorize(event)
            handle_key_event(key_event)
        
        elif event.type == ecodes.EV_REL:
            # Process mouse movement events
            rel_event = categorize(event)
            handle_mouse_movement(rel_event)
        
        elif event.type == ecodes.EV_ABS:
            # Process absolute positioning events
            abs_event = categorize(event)
            handle_absolute_positioning(abs_event)
        
        elif event.type == ecodes.EV_SYN:
            # Synchronization event - marks end of event sequence
            handle_sync_event(event)

def handle_key_event(key_event):
    print(f"Key: {key_event.keycode}, State: {key_event.keystate}")

def handle_mouse_movement(rel_event):
    event = rel_event.event
    if event.code == ecodes.REL_X:
        print(f"Mouse X movement: {event.value}")
    elif event.code == ecodes.REL_Y:
        print(f"Mouse Y movement: {event.value}")

def handle_absolute_positioning(abs_event):
    event = abs_event.event
    if event.code == ecodes.ABS_X:
        print(f"Touch X position: {event.value}")
    elif event.code == ecodes.ABS_Y:
        print(f"Touch Y position: {event.value}")

def handle_sync_event(event):
    if event.code == ecodes.SYN_REPORT:
        print("End of event sequence")

process_events()

Event Timestamp Processing

from evdev import InputDevice, categorize
import time

device = InputDevice('/dev/input/event0')
start_time = time.time()

for event in device.read_loop():
    # Get event timestamp
    event_time = event.timestamp()
    relative_time = event_time - start_time
    
    categorized = categorize(event)
    print(f"[{relative_time:.3f}s] {categorized}")
    
    # Alternative: access timestamp components directly
    print(f"Event at {event.sec}.{event.usec:06d}")

Handling Unknown Key Codes

from evdev import InputDevice, categorize, ecodes, KeyEvent

device = InputDevice('/dev/input/event0')

for event in device.read_loop():
    if event.type == ecodes.EV_KEY:
        try:
            # Default behavior - raises KeyError for unknown keys
            key_event = KeyEvent(event)
            print(f"Known key: {key_event.keycode}")
        except KeyError:
            # Handle unknown key codes
            key_event = KeyEvent(event, allow_unknown=True)
            print(f"Unknown key: {key_event.keycode} (code: {key_event.scancode})")

Event Stream Buffering

from evdev import InputDevice, categorize
from collections import deque

device = InputDevice('/dev/input/event0')
event_buffer = deque(maxlen=100)  # Keep last 100 events

def process_buffered_events():
    while True:
        # Read all available events
        events = device.read()
        
        # Add to buffer and categorize
        for event in events:
            categorized = categorize(event)
            event_buffer.append(categorized)
        
        # Process buffer
        while event_buffer:
            event = event_buffer.popleft()
            handle_event(event)

def handle_event(event):
    if isinstance(event, KeyEvent):
        print(f"Buffered key event: {event.keycode}")
    else:
        print(f"Buffered event: {event}")

process_buffered_events()

Install with Tessl CLI

npx tessl i tessl/pypi-evdev

docs

device-operations.md

event-codes.md

event-processing.md

force-feedback.md

index.md

virtual-devices.md

tile.json