Python bindings to the Linux input handling subsystem for reading input events and creating virtual input devices
—
Comprehensive mapping of Linux input subsystem constants and utilities for resolving event codes to human-readable names. The ecodes module provides access to all kernel-defined constants for event types, key codes, and device properties.
Primary event type classifications from the Linux input subsystem.
# Core event types
EV_SYN: int # Synchronization events
EV_KEY: int # Key/button events
EV_REL: int # Relative axis events (mouse movement)
EV_ABS: int # Absolute axis events (touchscreen, joystick)
EV_MSC: int # Miscellaneous events
EV_SW: int # Switch events
EV_LED: int # LED events
EV_SND: int # Sound events
EV_REP: int # Repeat events
EV_FF: int # Force feedback events
EV_PWR: int # Power button events
EV_FF_STATUS: int # Force feedback status
# Event type mapping dictionary
EV: Dict[int, str] # Maps event type codes to namesConstants for keyboard keys and button identifiers.
# Keyboard key constants (examples - hundreds available)
KEY_A: int # 'A' key
KEY_B: int # 'B' key
KEY_SPACE: int # Space bar
KEY_ENTER: int # Enter key
KEY_ESC: int # Escape key
KEY_BACKSPACE: int # Backspace key
KEY_TAB: int # Tab key
KEY_LEFTSHIFT: int # Left shift key
KEY_RIGHTCTRL: int # Right control key
KEY_LEFTALT: int # Left alt key
# Function keys
KEY_F1: int # F1 key
KEY_F2: int # F2 key
# ... F1-F24
# Arrow keys
KEY_UP: int # Up arrow
KEY_DOWN: int # Down arrow
KEY_LEFT: int # Left arrow
KEY_RIGHT: int # Right arrow
# Numeric keypad
KEY_KP0: int # Keypad 0
KEY_KP1: int # Keypad 1
# ... KP0-KP9
# Button constants
BTN_LEFT: int # Left mouse button
BTN_RIGHT: int # Right mouse button
BTN_MIDDLE: int # Middle mouse button
BTN_SIDE: int # Side mouse button
BTN_EXTRA: int # Extra mouse button
# Gamepad buttons
BTN_A: int # Gamepad A button
BTN_B: int # Gamepad B button
BTN_X: int # Gamepad X button
BTN_Y: int # Gamepad Y button
BTN_START: int # Start button
BTN_SELECT: int # Select button
# Key/button mapping dictionaries
KEY: Dict[int, str] # Maps key codes to names
BTN: Dict[int, str] # Maps button codes to names
keys: Dict[int, str] # Combined KEY and BTN mappingsConstants for relative positioning devices (mice, trackballs).
# Relative axis constants
REL_X: int # X-axis movement
REL_Y: int # Y-axis movement
REL_Z: int # Z-axis movement
REL_RX: int # X-axis rotation
REL_RY: int # Y-axis rotation
REL_RZ: int # Z-axis rotation
REL_HWHEEL: int # Horizontal wheel
REL_DIAL: int # Dial rotation
REL_WHEEL: int # Vertical wheel
REL_MISC: int # Miscellaneous
# Relative axis mapping dictionary
REL: Dict[int, str] # Maps relative axis codes to namesConstants for absolute positioning devices (touchscreens, joysticks, tablets).
# Absolute axis constants
ABS_X: int # X-axis position
ABS_Y: int # Y-axis position
ABS_Z: int # Z-axis position
ABS_RX: int # X-axis rotation
ABS_RY: int # Y-axis rotation
ABS_RZ: int # Z-axis rotation
ABS_THROTTLE: int # Throttle
ABS_RUDDER: int # Rudder
ABS_WHEEL: int # Wheel
ABS_GAS: int # Gas pedal
ABS_BRAKE: int # Brake pedal
# Multi-touch constants
ABS_MT_SLOT: int # Multi-touch slot
ABS_MT_TOUCH_MAJOR: int # Touch major axis
ABS_MT_TOUCH_MINOR: int # Touch minor axis
ABS_MT_WIDTH_MAJOR: int # Width major axis
ABS_MT_WIDTH_MINOR: int # Width minor axis
ABS_MT_ORIENTATION: int # Touch orientation
ABS_MT_POSITION_X: int # Multi-touch X position
ABS_MT_POSITION_Y: int # Multi-touch Y position
ABS_MT_TOOL_TYPE: int # Tool type
ABS_MT_BLOB_ID: int # Blob identifier
ABS_MT_TRACKING_ID: int # Tracking identifier
ABS_MT_PRESSURE: int # Touch pressure
ABS_MT_DISTANCE: int # Distance from surface
# Absolute axis mapping dictionary
ABS: Dict[int, str] # Maps absolute axis codes to namesConstants for event synchronization and timing.
# Sync event constants
SYN_REPORT: int # Synchronization report
SYN_CONFIG: int # Configuration sync
SYN_MT_REPORT: int # Multi-touch report
SYN_DROPPED: int # Events dropped
# Sync mapping dictionary
SYN: Dict[int, str] # Maps sync codes to namesConstants for LED indicators on devices.
# LED constants
LED_NUML: int # Num Lock LED
LED_CAPSL: int # Caps Lock LED
LED_SCROLLL: int # Scroll Lock LED
LED_COMPOSE: int # Compose LED
LED_KANA: int # Kana LED
LED_SLEEP: int # Sleep LED
LED_SUSPEND: int # Suspend LED
LED_MUTE: int # Mute LED
LED_MISC: int # Miscellaneous LED
# LED mapping dictionary
LED: Dict[int, str] # Maps LED codes to namesConstants for switch events (lid switches, tablet mode, etc.).
# Switch constants
SW_LID: int # Lid switch
SW_TABLET_MODE: int # Tablet mode
SW_HEADPHONE_INSERT: int # Headphone insertion
SW_RFKILL_ALL: int # RF kill switch
SW_RADIO: int # Radio switch
SW_MICROPHONE_INSERT: int # Microphone insertion
SW_DOCK: int # Dock switch
SW_LINEOUT_INSERT: int # Line out insertion
SW_JACK_PHYSICAL_INSERT: int # Physical jack insertion
# Switch mapping dictionary
SW: Dict[int, str] # Maps switch codes to namesConstants for force feedback effects and status.
# Force feedback effect types
FF_RUMBLE: int # Rumble effect
FF_PERIODIC: int # Periodic effect
FF_CONSTANT: int # Constant force effect
FF_SPRING: int # Spring effect
FF_FRICTION: int # Friction effect
FF_DAMPER: int # Damper effect
FF_INERTIA: int # Inertia effect
FF_RAMP: int # Ramp effect
# Periodic waveforms
FF_SQUARE: int # Square wave
FF_TRIANGLE: int # Triangle wave
FF_SINE: int # Sine wave
FF_SAW_UP: int # Sawtooth up
FF_SAW_DOWN: int # Sawtooth down
FF_CUSTOM: int # Custom waveform
# Force feedback mapping dictionaries
FF: Dict[int, str] # Maps FF codes to names
FF_STATUS: Dict[int, str] # Maps FF status codes to namesConstants for device bus types.
# Bus type constants
BUS_PCI: int # PCI bus
BUS_ISAPNP: int # ISA Plug and Play
BUS_USB: int # USB bus
BUS_HIL: int # HIL bus
BUS_BLUETOOTH: int # Bluetooth
BUS_VIRTUAL: int # Virtual bus
BUS_ISA: int # ISA bus
BUS_I8042: int # i8042 controller
BUS_XTKBD: int # XT keyboard
BUS_RS232: int # RS232 serial
BUS_GAMEPORT: int # Gameport
BUS_PARPORT: int # Parallel port
BUS_AMIGA: int # Amiga bus
BUS_ADB: int # Apple Desktop Bus
BUS_I2C: int # I2C bus
BUS_HOST: int # Host bus
BUS_GSC: int # GSC bus
BUS_ATARI: int # Atari bus
BUS_SPI: int # SPI bus
# Bus type mapping dictionary
BUS: Dict[int, str] # Maps bus type codes to namesConstants for device input properties and quirks.
# Input property constants
INPUT_PROP_POINTER: int # Device is a pointer
INPUT_PROP_DIRECT: int # Direct input device
INPUT_PROP_BUTTONPAD: int # Device is a buttonpad
INPUT_PROP_SEMI_MT: int # Semi-multitouch device
INPUT_PROP_TOPBUTTONPAD: int # Top button pad
INPUT_PROP_POINTING_STICK: int # Pointing stick
INPUT_PROP_ACCELEROMETER: int # Accelerometer
# Input properties mapping dictionary
INPUT_PROP: Dict[int, str] # Maps property codes to namesFunctions for converting between numeric codes and human-readable names.
def resolve_ecodes(ecode_dict: Dict, ecode_list: List, unknown: str = "?") -> List:
"""
Resolve event codes to their verbose names.
Parameters:
- ecode_dict: Dictionary mapping codes to names (e.g., ecodes.KEY)
- ecode_list: List of numeric codes to resolve
- unknown: String to use for unknown codes
Returns:
List of resolved code names or tuples for complex cases
Example:
>>> resolve_ecodes(ecodes.KEY, [30, 48, 46])
[('KEY_A', 30), ('KEY_B', 48), ('KEY_C', 46)]
"""
def resolve_ecodes_dict(typecodemap: Dict, unknown: str = "?") -> Iterator:
"""
Resolve event types and codes to verbose names.
Parameters:
- typecodemap: Dictionary mapping event types to code lists
{1: [272, 273], 3: [(0, AbsInfo(...))]}
- unknown: String to use for unknown types/codes
Yields:
Tuples of ((type_name, type_code), resolved_codes)
Example:
>>> resolve_ecodes_dict({1: [272, 273, 274]})
(('EV_KEY', 1), [('BTN_MOUSE', 272), ('BTN_RIGHT', 273), ('BTN_MIDDLE', 274)])
"""
def find_ecodes_by_regex(regex) -> Dict[int, List[int]]:
"""
Find ecodes matching a regex pattern and return mapping of event type to event codes.
Parameters:
- regex: Pattern string or compiled regular expression object
Returns:
Dictionary mapping event type codes to lists of matching event codes
Example:
>>> find_ecodes_by_regex(r'(ABS|KEY)_BR(AKE|EAK)')
{1: [411], 3: [10]}
>>> res = find_ecodes_by_regex(r'BTN_(A|B|X|Y)')
>>> resolve_ecodes_dict(res)
(('EV_KEY', 1), [('BTN_A', 304), ('BTN_B', 305), ('BTN_X', 307), ('BTN_Y', 308)])
"""Central mapping of all constant names to their numeric values.
ecodes: Dict[str, int] # Maps all constant names to values
# Example: ecodes['KEY_A'] == 30, ecodes['EV_KEY'] == 1
# Reverse mappings by event type
bytype: Dict[int, Dict[int, str]] # Maps event types to their code dictionaries
# Example: bytype[EV_KEY] == KEY dictionary, bytype[EV_REL] == REL dictionaryfrom evdev import ecodes
# Access constants directly
print(f"KEY_A code: {ecodes.KEY_A}")
print(f"EV_KEY type: {ecodes.EV_KEY}")
# Resolve code to name
key_name = ecodes.KEY[ecodes.KEY_A]
print(f"Code {ecodes.KEY_A} is: {key_name}")
# Check if code exists
if ecodes.KEY_SPACE in ecodes.KEY:
print(f"Space key name: {ecodes.KEY[ecodes.KEY_SPACE]}")from evdev import ecodes, resolve_ecodes, resolve_ecodes_dict
# Resolve multiple key codes
key_codes = [ecodes.KEY_A, ecodes.KEY_B, ecodes.KEY_C]
resolved = resolve_ecodes(ecodes.KEY, key_codes)
print("Resolved keys:", resolved)
# Resolve device capabilities
capabilities = {
ecodes.EV_KEY: [ecodes.KEY_A, ecodes.KEY_B, ecodes.BTN_LEFT],
ecodes.EV_REL: [ecodes.REL_X, ecodes.REL_Y, ecodes.REL_WHEEL]
}
for (type_name, type_code), codes in resolve_ecodes_dict(capabilities):
print(f"Event type {type_name} ({type_code}):")
for code_info in codes:
if isinstance(code_info, tuple):
code_name, code_num = code_info
print(f" {code_name} ({code_num})")
else:
print(f" {code_info}")from evdev import ecodes
import re
# Find all function key constants
function_keys = [name for name in dir(ecodes) if name.startswith('KEY_F')]
print("Function keys:", function_keys)
# Find mouse button constants
mouse_buttons = [name for name in dir(ecodes) if 'BTN' in name and 'MOUSE' in name]
print("Mouse buttons:", mouse_buttons)
# Using regex search (if available)
try:
from evdev.util import find_ecodes_by_regex
gamepad_codes = find_ecodes_by_regex(r'BTN_(A|B|X|Y|START|SELECT)')
print("Gamepad buttons:", gamepad_codes)
except ImportError:
# Alternative manual search
gamepad_buttons = [name for name in dir(ecodes)
if any(btn in name for btn in ['BTN_A', 'BTN_B', 'BTN_X', 'BTN_Y'])]
print("Gamepad buttons:", gamepad_buttons)from evdev import ecodes
# Multi-touch axis codes
mt_axes = [
ecodes.ABS_MT_POSITION_X,
ecodes.ABS_MT_POSITION_Y,
ecodes.ABS_MT_PRESSURE,
ecodes.ABS_MT_TRACKING_ID
]
print("Multi-touch axes:")
for axis in mt_axes:
axis_name = ecodes.ABS[axis]
print(f" {axis_name}: {axis}")from evdev import InputDevice, ecodes
def analyze_device_type(device_path):
device = InputDevice(device_path)
caps = device.capabilities()
device_types = []
# Check for keyboard
if ecodes.EV_KEY in caps:
key_codes = caps[ecodes.EV_KEY]
if any(code in key_codes for code in [ecodes.KEY_A, ecodes.KEY_SPACE]):
device_types.append("keyboard")
if any(code in key_codes for code in [ecodes.BTN_LEFT, ecodes.BTN_RIGHT]):
device_types.append("mouse")
if any(code in key_codes for code in [ecodes.BTN_A, ecodes.BTN_B]):
device_types.append("gamepad")
# Check for mouse movement
if ecodes.EV_REL in caps:
rel_codes = caps[ecodes.EV_REL]
if ecodes.REL_X in rel_codes and ecodes.REL_Y in rel_codes:
device_types.append("pointer")
# Check for touchscreen/tablet
if ecodes.EV_ABS in caps:
abs_codes = [code[0] if isinstance(code, tuple) else code
for code in caps[ecodes.EV_ABS]]
if ecodes.ABS_X in abs_codes and ecodes.ABS_Y in abs_codes:
if any(code in abs_codes for code in [ecodes.ABS_MT_POSITION_X]):
device_types.append("touchscreen")
else:
device_types.append("tablet/joystick")
print(f"Device: {device.name}")
print(f"Types: {', '.join(device_types) if device_types else 'unknown'}")
device.close()
return device_types
# Analyze all devices
from evdev import list_devices
for device_path in list_devices():
analyze_device_type(device_path)from evdev import ecodes
# Create custom mappings for specific use cases
WASD_KEYS = {
'w': ecodes.KEY_W,
'a': ecodes.KEY_A,
's': ecodes.KEY_S,
'd': ecodes.KEY_D
}
ARROW_KEYS = {
'up': ecodes.KEY_UP,
'down': ecodes.KEY_DOWN,
'left': ecodes.KEY_LEFT,
'right': ecodes.KEY_RIGHT
}
# Function to get key code by name
def get_key_code(key_name):
# Try direct lookup
attr_name = f'KEY_{key_name.upper()}'
if hasattr(ecodes, attr_name):
return getattr(ecodes, attr_name)
# Try custom mappings
if key_name.lower() in WASD_KEYS:
return WASD_KEYS[key_name.lower()]
if key_name.lower() in ARROW_KEYS:
return ARROW_KEYS[key_name.lower()]
raise ValueError(f"Unknown key: {key_name}")
# Usage
try:
code = get_key_code('a')
print(f"Key 'a' has code: {code}")
except ValueError as e:
print(e)Install with Tessl CLI
npx tessl i tessl/pypi-evdev