or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

device-operations.mddocs/

0

# Device Operations

1

2

Core functionality for discovering, opening, and interacting with Linux input devices. This includes device enumeration, capability querying, event reading, and device control operations.

3

4

## Capabilities

5

6

### Device Discovery

7

8

Functions for finding and identifying available input devices on the system.

9

10

```python { .api }

11

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

12

"""

13

List readable character devices in input_device_dir.

14

15

Parameters:

16

- input_device_dir: Directory to search for input devices (default: "/dev/input")

17

18

Returns:

19

List of device paths (e.g., ["/dev/input/event0", "/dev/input/event1"])

20

"""

21

```

22

23

### Device Initialization

24

25

Opening and initializing input device connections.

26

27

```python { .api }

28

class InputDevice:

29

def __init__(self, dev: Union[str, bytes, os.PathLike]) -> None:

30

"""

31

Initialize InputDevice with device path.

32

33

Parameters:

34

- dev: Path to input device (e.g., "/dev/input/event0")

35

36

Raises:

37

- EvdevError: If device cannot be opened or accessed

38

"""

39

40

def close(self) -> None:

41

"""Close the device file descriptor and release resources."""

42

43

def fileno(self) -> int:

44

"""

45

Return file descriptor for the device.

46

Enables use with select.select() and asyncore.file_dispatcher.

47

"""

48

```

49

50

### Device Information

51

52

Methods for querying device properties, capabilities, and status information.

53

54

```python { .api }

55

class InputDevice:

56

@property

57

def path(self) -> str:

58

"""Path to the input device."""

59

60

@property

61

def fd(self) -> int:

62

"""File descriptor to the device."""

63

64

@property

65

def info(self) -> DeviceInfo:

66

"""Device identification information (vendor, product, etc.)."""

67

68

@property

69

def name(self) -> str:

70

"""Device name as reported by the kernel."""

71

72

@property

73

def phys(self) -> str:

74

"""Physical topology of the device."""

75

76

@property

77

def uniq(self) -> str:

78

"""Unique identifier for the device."""

79

80

@property

81

def version(self) -> int:

82

"""Evdev protocol version supported by the device."""

83

84

@property

85

def ff_effects_count(self) -> int:

86

"""Number of force feedback effects the device can store."""

87

88

def capabilities(self, verbose: bool = False, absinfo: bool = True) -> Dict:

89

"""

90

Get device capabilities and supported event types.

91

92

Parameters:

93

- verbose: Return human-readable names instead of numeric codes

94

- absinfo: Include AbsInfo for absolute axes

95

96

Returns:

97

Dictionary mapping event types to lists of supported event codes.

98

For absolute axes, includes (code, AbsInfo) tuples when absinfo=True.

99

"""

100

101

def input_props(self, verbose: bool = False) -> List:

102

"""

103

Get device input properties and quirks.

104

105

Parameters:

106

- verbose: Return human-readable names instead of numeric codes

107

108

Returns:

109

List of input property flags

110

"""

111

```

112

113

### Event Reading

114

115

Methods for reading input events from devices.

116

117

```python { .api }

118

class InputDevice:

119

def read_loop(self) -> Iterator[InputEvent]:

120

"""

121

Enter endless select() loop yielding input events.

122

Blocks until events are available.

123

"""

124

125

def read_one(self) -> Union[InputEvent, None]:

126

"""

127

Read single input event from device.

128

129

Returns:

130

InputEvent if available, None if no events pending

131

"""

132

133

def read(self) -> List[InputEvent]:

134

"""

135

Read multiple input events from device.

136

137

Returns:

138

List of available InputEvent objects

139

"""

140

```

141

142

### Device Control

143

144

Operations for controlling device behavior and state.

145

146

```python { .api }

147

class InputDevice:

148

def grab(self) -> None:

149

"""

150

Grant exclusive access to device using EVIOCGRAB ioctl.

151

Prevents other processes from receiving events from this device.

152

153

Raises:

154

- EvdevError: If grab fails (device already grabbed, insufficient permissions)

155

"""

156

157

def ungrab(self) -> None:

158

"""

159

Release exclusive access to device.

160

Allows other processes to receive events again.

161

"""

162

163

def grab_context(self):

164

"""

165

Context manager for device grabbing.

166

Automatically releases grab when exiting context.

167

168

Usage:

169

with device.grab_context():

170

# Device is exclusively grabbed

171

for event in device.read_loop():

172

process_event(event)

173

# Device is automatically ungrabbed

174

"""

175

```

176

177

### LED and Output Control

178

179

Methods for controlling device LEDs and output features.

180

181

```python { .api }

182

class InputDevice:

183

def leds(self, verbose: bool = False) -> List:

184

"""

185

Return currently active LED keys.

186

187

Parameters:

188

- verbose: Return human-readable names instead of numeric codes

189

190

Returns:

191

List of active LED codes/names

192

"""

193

194

def set_led(self, led_num: int, value: int) -> None:

195

"""

196

Set LED state on device.

197

198

Parameters:

199

- led_num: LED code (from ecodes.LED_*)

200

- value: LED state (0=off, 1=on)

201

"""

202

203

def active_keys(self, verbose: bool = False) -> List:

204

"""

205

Return currently pressed/active keys.

206

207

Parameters:

208

- verbose: Return human-readable names instead of numeric codes

209

210

Returns:

211

List of active key codes/names

212

"""

213

```

214

215

### Absolute Axis Control

216

217

Methods for working with absolute positioning devices (touchscreens, joysticks).

218

219

```python { .api }

220

class InputDevice:

221

def absinfo(self, axis_num: int) -> AbsInfo:

222

"""

223

Return AbsInfo for specified absolute axis.

224

225

Parameters:

226

- axis_num: Absolute axis code (from ecodes.ABS_*)

227

228

Returns:

229

AbsInfo namedtuple with axis information

230

"""

231

232

def set_absinfo(self, axis_num: int, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None) -> None:

233

"""

234

Update AbsInfo values for absolute axis.

235

236

Parameters:

237

- axis_num: Absolute axis code (from ecodes.ABS_*)

238

- value: Current value (optional)

239

- min: Minimum value (optional)

240

- max: Maximum value (optional)

241

- fuzz: Fuzz value for noise filtering (optional)

242

- flat: Flat value for center deadband (optional)

243

- resolution: Resolution in units per mm/radian (optional)

244

"""

245

```

246

247

### Keyboard Repeat Control

248

249

Methods for controlling keyboard repeat rate settings.

250

251

```python { .api }

252

class InputDevice:

253

@property

254

def repeat(self) -> KbdInfo:

255

"""

256

Get keyboard repeat rate information.

257

258

Returns:

259

KbdInfo namedtuple with delay and repeat rate

260

"""

261

262

@repeat.setter

263

def repeat(self, value: KbdInfo) -> None:

264

"""

265

Set keyboard repeat rate.

266

267

Parameters:

268

- value: KbdInfo with new delay and repeat values

269

"""

270

```

271

272

### Event Writing

273

274

Methods for injecting events into devices (feedback events).

275

276

```python { .api }

277

class InputDevice:

278

def write_event(self, event: InputEvent) -> None:

279

"""

280

Inject InputEvent into device.

281

282

Parameters:

283

- event: InputEvent to write to device

284

"""

285

286

def write(self, etype: int, code: int, value: int) -> None:

287

"""

288

Inject input event into device.

289

290

Parameters:

291

- etype: Event type (from ecodes.EV_*)

292

- code: Event code

293

- value: Event value

294

"""

295

296

def syn(self) -> None:

297

"""Inject SYN_REPORT event to synchronize event stream."""

298

```

299

300

### Force Feedback Control

301

302

Methods for managing force feedback effects on compatible devices.

303

304

```python { .api }

305

class InputDevice:

306

def upload_effect(self, effect: "ff.Effect") -> int:

307

"""

308

Upload force feedback effect to device.

309

310

Parameters:

311

- effect: Force feedback Effect structure

312

313

Returns:

314

Effect ID for managing the uploaded effect

315

"""

316

317

def erase_effect(self, ff_id: int) -> None:

318

"""

319

Remove force feedback effect from device.

320

321

Parameters:

322

- ff_id: Effect ID returned from upload_effect()

323

"""

324

```

325

326

## Usage Examples

327

328

### Basic Device Reading

329

330

```python

331

from evdev import InputDevice, list_devices

332

333

# Find all input devices

334

devices = list_devices()

335

print("Available devices:")

336

for device_path in devices:

337

device = InputDevice(device_path)

338

print(f" {device.path}: {device.name}")

339

device.close()

340

341

# Monitor specific device

342

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

343

print(f"Monitoring {device.name}")

344

345

try:

346

for event in device.read_loop():

347

print(f"Event: type={event.type}, code={event.code}, value={event.value}")

348

finally:

349

device.close()

350

```

351

352

### Device Capabilities

353

354

```python

355

from evdev import InputDevice, ecodes

356

357

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

358

359

# Get raw capabilities

360

caps = device.capabilities()

361

print("Device capabilities:", caps)

362

363

# Get human-readable capabilities

364

caps_verbose = device.capabilities(verbose=True)

365

print("Human-readable capabilities:", caps_verbose)

366

367

# Check for specific capabilities

368

if ecodes.EV_KEY in caps:

369

print("Device supports key events")

370

key_codes = caps[ecodes.EV_KEY]

371

print(f"Supported keys: {len(key_codes)} keys")

372

373

device.close()

374

```

375

376

### Exclusive Device Access

377

378

```python

379

from evdev import InputDevice

380

381

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

382

383

# Method 1: Manual grab/ungrab

384

device.grab()

385

try:

386

# Process events exclusively

387

for event in device.read():

388

process_event(event)

389

finally:

390

device.ungrab()

391

device.close()

392

393

# Method 2: Context manager (recommended)

394

with device.grab_context():

395

for event in device.read_loop():

396

process_event(event)

397

if should_stop():

398

break

399

```