evdev-binary 1.9.3__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- evdev/__init__.py +39 -0
- evdev/_ecodes.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/_input.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/_uinput.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/device.py +440 -0
- evdev/ecodes.py +3885 -0
- evdev/ecodes_runtime.py +111 -0
- evdev/eventio.py +152 -0
- evdev/eventio_async.py +106 -0
- evdev/events.py +192 -0
- evdev/evtest.py +181 -0
- evdev/ff.py +198 -0
- evdev/genecodes_c.py +147 -0
- evdev/genecodes_py.py +54 -0
- evdev/input.c +580 -0
- evdev/py.typed +0 -0
- evdev/uinput.c +417 -0
- evdev/uinput.py +375 -0
- evdev/util.py +146 -0
- evdev_binary-1.9.3.dist-info/METADATA +48 -0
- evdev_binary-1.9.3.dist-info/RECORD +24 -0
- evdev_binary-1.9.3.dist-info/WHEEL +5 -0
- evdev_binary-1.9.3.dist-info/licenses/LICENSE +29 -0
- evdev_binary-1.9.3.dist-info/top_level.txt +1 -0
evdev/input.c
ADDED
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Python bindings to certain linux input subsystem functions.
|
|
4
|
+
*
|
|
5
|
+
* While everything here can be implemented in pure Python with struct and
|
|
6
|
+
* fcntl.ioctl, imho, it is much more straightforward to do so in C.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#include <Python.h>
|
|
11
|
+
|
|
12
|
+
#include <stdio.h>
|
|
13
|
+
#include <stdint.h>
|
|
14
|
+
#include <string.h>
|
|
15
|
+
#include <errno.h>
|
|
16
|
+
#include <sys/types.h>
|
|
17
|
+
#include <sys/stat.h>
|
|
18
|
+
#include <fcntl.h>
|
|
19
|
+
#include <unistd.h>
|
|
20
|
+
|
|
21
|
+
#ifdef __FreeBSD__
|
|
22
|
+
#include <dev/evdev/input.h>
|
|
23
|
+
#else
|
|
24
|
+
#include <linux/input.h>
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
#ifndef input_event_sec
|
|
28
|
+
#define input_event_sec time.tv_sec
|
|
29
|
+
#define input_event_usec time.tv_usec
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
#define MAX_NAME_SIZE 256
|
|
33
|
+
|
|
34
|
+
extern char* EV_NAME[EV_CNT];
|
|
35
|
+
extern int EV_TYPE_MAX[EV_CNT];
|
|
36
|
+
extern char** EV_TYPE_NAME[EV_CNT];
|
|
37
|
+
extern char* BUS_NAME[];
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
int test_bit(const char* bitmask, int bit) {
|
|
41
|
+
return bitmask[bit/8] & (1 << (bit % 8));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
// Read input event from a device and return a tuple that mimics input_event
|
|
46
|
+
static PyObject *
|
|
47
|
+
device_read(PyObject *self, PyObject *args)
|
|
48
|
+
{
|
|
49
|
+
struct input_event event;
|
|
50
|
+
|
|
51
|
+
// get device file descriptor (O_RDONLY|O_NONBLOCK)
|
|
52
|
+
int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
|
|
53
|
+
|
|
54
|
+
int n = read(fd, &event, sizeof(event));
|
|
55
|
+
|
|
56
|
+
if (n < 0) {
|
|
57
|
+
if (errno == EAGAIN) {
|
|
58
|
+
Py_INCREF(Py_None);
|
|
59
|
+
return Py_None;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
63
|
+
return NULL;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
PyObject *py_input_event = PyTuple_New(5);
|
|
67
|
+
PyTuple_SET_ITEM(py_input_event, 0, PyLong_FromLong(event.input_event_sec));
|
|
68
|
+
PyTuple_SET_ITEM(py_input_event, 1, PyLong_FromLong(event.input_event_usec));
|
|
69
|
+
PyTuple_SET_ITEM(py_input_event, 2, PyLong_FromLong(event.type));
|
|
70
|
+
PyTuple_SET_ITEM(py_input_event, 3, PyLong_FromLong(event.code));
|
|
71
|
+
PyTuple_SET_ITEM(py_input_event, 4, PyLong_FromLong(event.value));
|
|
72
|
+
|
|
73
|
+
return py_input_event;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
// Read multiple input events from a device and return a list of tuples
|
|
78
|
+
static PyObject *
|
|
79
|
+
device_read_many(PyObject *self, PyObject *args)
|
|
80
|
+
{
|
|
81
|
+
// get device file descriptor (O_RDONLY|O_NONBLOCK)
|
|
82
|
+
int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
|
|
83
|
+
|
|
84
|
+
struct input_event event[64];
|
|
85
|
+
|
|
86
|
+
size_t event_size = sizeof(struct input_event);
|
|
87
|
+
ssize_t nread = read(fd, event, event_size*64);
|
|
88
|
+
|
|
89
|
+
if (nread < 0) {
|
|
90
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
91
|
+
return NULL;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Construct a tuple of event tuples. Each tuple is the arguments to InputEvent.
|
|
95
|
+
size_t num_events = nread / event_size;
|
|
96
|
+
|
|
97
|
+
PyObject* events = PyTuple_New(num_events);
|
|
98
|
+
for (size_t i = 0 ; i < num_events; i++) {
|
|
99
|
+
PyObject *py_input_event = PyTuple_New(5);
|
|
100
|
+
PyTuple_SET_ITEM(py_input_event, 0, PyLong_FromLong(event[i].input_event_sec));
|
|
101
|
+
PyTuple_SET_ITEM(py_input_event, 1, PyLong_FromLong(event[i].input_event_usec));
|
|
102
|
+
PyTuple_SET_ITEM(py_input_event, 2, PyLong_FromLong(event[i].type));
|
|
103
|
+
PyTuple_SET_ITEM(py_input_event, 3, PyLong_FromLong(event[i].code));
|
|
104
|
+
PyTuple_SET_ITEM(py_input_event, 4, PyLong_FromLong(event[i].value));
|
|
105
|
+
PyTuple_SET_ITEM(events, i, py_input_event);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return events;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
// Get the event types and event codes that the input device supports
|
|
113
|
+
static PyObject *
|
|
114
|
+
ioctl_capabilities(PyObject *self, PyObject *args)
|
|
115
|
+
{
|
|
116
|
+
int fd, ev_type, ev_code;
|
|
117
|
+
char ev_bits[EV_MAX/8 + 1], code_bits[KEY_MAX/8 + 1];
|
|
118
|
+
struct input_absinfo absinfo;
|
|
119
|
+
|
|
120
|
+
int ret = PyArg_ParseTuple(args, "i", &fd);
|
|
121
|
+
if (!ret) return NULL;
|
|
122
|
+
|
|
123
|
+
// @todo: figure out why fd gets zeroed on an ioctl after the
|
|
124
|
+
// refactoring and get rid of this workaround
|
|
125
|
+
const int _fd = fd;
|
|
126
|
+
|
|
127
|
+
// Capabilities is a mapping of supported event types to lists of handled
|
|
128
|
+
// events e.g: {1: [272, 273, 274, 275], 2: [0, 1, 6, 8]}
|
|
129
|
+
PyObject* capabilities = PyDict_New();
|
|
130
|
+
PyObject* eventcodes = NULL;
|
|
131
|
+
PyObject* evlong = NULL;
|
|
132
|
+
PyObject* capability = NULL;
|
|
133
|
+
PyObject* py_absinfo = NULL;
|
|
134
|
+
PyObject* absitem = NULL;
|
|
135
|
+
|
|
136
|
+
memset(&ev_bits, 0, sizeof(ev_bits));
|
|
137
|
+
|
|
138
|
+
if (ioctl(_fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0)
|
|
139
|
+
goto on_err;
|
|
140
|
+
|
|
141
|
+
// Build a dictionary of the device's capabilities
|
|
142
|
+
for (ev_type=0 ; ev_type<EV_MAX ; ev_type++) {
|
|
143
|
+
if (test_bit(ev_bits, ev_type)) {
|
|
144
|
+
|
|
145
|
+
capability = PyLong_FromLong(ev_type);
|
|
146
|
+
eventcodes = PyList_New(0);
|
|
147
|
+
|
|
148
|
+
memset(&code_bits, 0, sizeof(code_bits));
|
|
149
|
+
ioctl(_fd, EVIOCGBIT(ev_type, sizeof(code_bits)), code_bits);
|
|
150
|
+
|
|
151
|
+
for (ev_code = 0; ev_code < KEY_MAX; ev_code++) {
|
|
152
|
+
if (test_bit(code_bits, ev_code)) {
|
|
153
|
+
// Get abs{min,max,fuzz,flat} values for ABS_* event codes
|
|
154
|
+
if (ev_type == EV_ABS) {
|
|
155
|
+
memset(&absinfo, 0, sizeof(absinfo));
|
|
156
|
+
ioctl(_fd, EVIOCGABS(ev_code), &absinfo);
|
|
157
|
+
|
|
158
|
+
py_absinfo = Py_BuildValue("(iiiiii)",
|
|
159
|
+
absinfo.value,
|
|
160
|
+
absinfo.minimum,
|
|
161
|
+
absinfo.maximum,
|
|
162
|
+
absinfo.fuzz,
|
|
163
|
+
absinfo.flat,
|
|
164
|
+
absinfo.resolution);
|
|
165
|
+
|
|
166
|
+
evlong = PyLong_FromLong(ev_code);
|
|
167
|
+
absitem = Py_BuildValue("(OO)", evlong, py_absinfo);
|
|
168
|
+
|
|
169
|
+
// absitem -> tuple(ABS_X, (0, 255, 0, 0))
|
|
170
|
+
PyList_Append(eventcodes, absitem);
|
|
171
|
+
|
|
172
|
+
Py_DECREF(absitem);
|
|
173
|
+
Py_DECREF(py_absinfo);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
evlong = PyLong_FromLong(ev_code);
|
|
177
|
+
PyList_Append(eventcodes, evlong);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
Py_DECREF(evlong);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// capabilities[EV_KEY] = [KEY_A, KEY_B, KEY_C, ...]
|
|
184
|
+
// capabilities[EV_ABS] = [(ABS_X, (0, 255, 0, 0)), ...]
|
|
185
|
+
PyDict_SetItem(capabilities, capability, eventcodes);
|
|
186
|
+
|
|
187
|
+
Py_DECREF(capability);
|
|
188
|
+
Py_DECREF(eventcodes);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return capabilities;
|
|
193
|
+
|
|
194
|
+
on_err:
|
|
195
|
+
Py_XDECREF(capabilities);
|
|
196
|
+
Py_XDECREF(eventcodes);
|
|
197
|
+
Py_XDECREF(capability);
|
|
198
|
+
Py_XDECREF(py_absinfo);
|
|
199
|
+
Py_XDECREF(absitem);
|
|
200
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
201
|
+
return NULL;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
// An all-in-one function for describing an input device
|
|
206
|
+
static PyObject *
|
|
207
|
+
ioctl_devinfo(PyObject *self, PyObject *args)
|
|
208
|
+
{
|
|
209
|
+
int fd;
|
|
210
|
+
|
|
211
|
+
struct input_id iid;
|
|
212
|
+
char name[MAX_NAME_SIZE];
|
|
213
|
+
char phys[MAX_NAME_SIZE] = {0};
|
|
214
|
+
char uniq[MAX_NAME_SIZE] = {0};
|
|
215
|
+
|
|
216
|
+
int ret = PyArg_ParseTuple(args, "i", &fd);
|
|
217
|
+
if (!ret) return NULL;
|
|
218
|
+
|
|
219
|
+
memset(&iid, 0, sizeof(iid));
|
|
220
|
+
|
|
221
|
+
if (ioctl(fd, EVIOCGID, &iid) < 0) goto on_err;
|
|
222
|
+
if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) goto on_err;
|
|
223
|
+
|
|
224
|
+
// Some devices do not have a physical topology associated with them
|
|
225
|
+
ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys);
|
|
226
|
+
|
|
227
|
+
// Some kernels have started reporting bluetooth controller MACs as phys.
|
|
228
|
+
// This lets us get the real physical address. As with phys, it may be blank.
|
|
229
|
+
ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq);
|
|
230
|
+
|
|
231
|
+
return Py_BuildValue("hhhhsss", iid.bustype, iid.vendor, iid.product, iid.version,
|
|
232
|
+
name, phys, uniq);
|
|
233
|
+
|
|
234
|
+
on_err:
|
|
235
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
236
|
+
return NULL;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
static PyObject *
|
|
241
|
+
ioctl_EVIOCGABS(PyObject *self, PyObject *args)
|
|
242
|
+
{
|
|
243
|
+
int fd, ev_code;
|
|
244
|
+
struct input_absinfo absinfo;
|
|
245
|
+
PyObject* py_absinfo = NULL;
|
|
246
|
+
|
|
247
|
+
int ret = PyArg_ParseTuple(args, "ii", &fd, &ev_code);
|
|
248
|
+
if (!ret) return NULL;
|
|
249
|
+
|
|
250
|
+
memset(&absinfo, 0, sizeof(absinfo));
|
|
251
|
+
ret = ioctl(fd, EVIOCGABS(ev_code), &absinfo);
|
|
252
|
+
if (ret == -1) {
|
|
253
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
254
|
+
return NULL;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
py_absinfo = Py_BuildValue("(iiiiii)",
|
|
258
|
+
absinfo.value,
|
|
259
|
+
absinfo.minimum,
|
|
260
|
+
absinfo.maximum,
|
|
261
|
+
absinfo.fuzz,
|
|
262
|
+
absinfo.flat,
|
|
263
|
+
absinfo.resolution);
|
|
264
|
+
return py_absinfo;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
static PyObject *
|
|
269
|
+
ioctl_EVIOCSABS(PyObject *self, PyObject *args)
|
|
270
|
+
{
|
|
271
|
+
int fd, ev_code;
|
|
272
|
+
struct input_absinfo absinfo;
|
|
273
|
+
|
|
274
|
+
int ret = PyArg_ParseTuple(args,
|
|
275
|
+
"ii(iiiiii)",
|
|
276
|
+
&fd,
|
|
277
|
+
&ev_code,
|
|
278
|
+
&absinfo.value,
|
|
279
|
+
&absinfo.minimum,
|
|
280
|
+
&absinfo.maximum,
|
|
281
|
+
&absinfo.fuzz,
|
|
282
|
+
&absinfo.flat,
|
|
283
|
+
&absinfo.resolution);
|
|
284
|
+
if (!ret) return NULL;
|
|
285
|
+
|
|
286
|
+
ret = ioctl(fd, EVIOCSABS(ev_code), &absinfo);
|
|
287
|
+
if (ret == -1) {
|
|
288
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
289
|
+
return NULL;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
Py_INCREF(Py_None);
|
|
293
|
+
return Py_None;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
static PyObject *
|
|
298
|
+
ioctl_EVIOCGREP(PyObject *self, PyObject *args)
|
|
299
|
+
{
|
|
300
|
+
int fd, ret;
|
|
301
|
+
unsigned int rep[REP_CNT] = {0};
|
|
302
|
+
ret = PyArg_ParseTuple(args, "i", &fd);
|
|
303
|
+
if (!ret) return NULL;
|
|
304
|
+
|
|
305
|
+
ret = ioctl(fd, EVIOCGREP, &rep);
|
|
306
|
+
if (ret == -1)
|
|
307
|
+
return NULL;
|
|
308
|
+
|
|
309
|
+
return Py_BuildValue("(ii)", rep[REP_DELAY], rep[REP_PERIOD]);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
static PyObject *
|
|
314
|
+
ioctl_EVIOCSREP(PyObject *self, PyObject *args)
|
|
315
|
+
{
|
|
316
|
+
int fd, ret;
|
|
317
|
+
unsigned int rep[REP_CNT] = {0};
|
|
318
|
+
|
|
319
|
+
ret = PyArg_ParseTuple(args, "iii", &fd, &rep[0], &rep[1]);
|
|
320
|
+
if (!ret) return NULL;
|
|
321
|
+
|
|
322
|
+
ret = ioctl(fd, EVIOCSREP, &rep);
|
|
323
|
+
if (ret == -1)
|
|
324
|
+
return NULL;
|
|
325
|
+
|
|
326
|
+
return Py_BuildValue("i", ret);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
static PyObject *
|
|
331
|
+
ioctl_EVIOCGVERSION(PyObject *self, PyObject *args)
|
|
332
|
+
{
|
|
333
|
+
int fd, ret, res;
|
|
334
|
+
ret = PyArg_ParseTuple(args, "i", &fd);
|
|
335
|
+
if (!ret) return NULL;
|
|
336
|
+
|
|
337
|
+
ret = ioctl(fd, EVIOCGVERSION, &res);
|
|
338
|
+
if (ret == -1)
|
|
339
|
+
return NULL;
|
|
340
|
+
|
|
341
|
+
return Py_BuildValue("i", res);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
static PyObject *
|
|
346
|
+
ioctl_EVIOCGRAB(PyObject *self, PyObject *args)
|
|
347
|
+
{
|
|
348
|
+
int fd, ret, flag;
|
|
349
|
+
ret = PyArg_ParseTuple(args, "ii", &fd, &flag);
|
|
350
|
+
if (!ret) return NULL;
|
|
351
|
+
|
|
352
|
+
ret = ioctl(fd, EVIOCGRAB, (intptr_t)flag);
|
|
353
|
+
if (ret != 0) {
|
|
354
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
355
|
+
return NULL;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
Py_INCREF(Py_None);
|
|
359
|
+
return Py_None;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
static PyObject *
|
|
364
|
+
ioctl_EVIOCG_bits(PyObject *self, PyObject *args)
|
|
365
|
+
{
|
|
366
|
+
int max, fd, evtype, ret;
|
|
367
|
+
|
|
368
|
+
ret = PyArg_ParseTuple(args, "ii", &fd, &evtype);
|
|
369
|
+
if (!ret) return NULL;
|
|
370
|
+
|
|
371
|
+
switch (evtype) {
|
|
372
|
+
case EV_LED:
|
|
373
|
+
max = LED_MAX; break;
|
|
374
|
+
case EV_SND:
|
|
375
|
+
max = SND_MAX; break;
|
|
376
|
+
case EV_KEY:
|
|
377
|
+
max = KEY_MAX; break;
|
|
378
|
+
case EV_SW:
|
|
379
|
+
max = SW_MAX; break;
|
|
380
|
+
default:
|
|
381
|
+
return NULL;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
char bytes[(max+7)/8];
|
|
385
|
+
memset(bytes, 0, sizeof bytes);
|
|
386
|
+
|
|
387
|
+
switch (evtype) {
|
|
388
|
+
case EV_LED:
|
|
389
|
+
ret = ioctl(fd, EVIOCGLED(sizeof(bytes)), &bytes);
|
|
390
|
+
break;
|
|
391
|
+
case EV_SND:
|
|
392
|
+
ret = ioctl(fd, EVIOCGSND(sizeof(bytes)), &bytes);
|
|
393
|
+
break;
|
|
394
|
+
case EV_KEY:
|
|
395
|
+
ret = ioctl(fd, EVIOCGKEY(sizeof(bytes)), &bytes);
|
|
396
|
+
break;
|
|
397
|
+
case EV_SW:
|
|
398
|
+
ret = ioctl(fd, EVIOCGSW(sizeof(bytes)), &bytes);
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (ret == -1)
|
|
403
|
+
return NULL;
|
|
404
|
+
|
|
405
|
+
PyObject* res = PyList_New(0);
|
|
406
|
+
for (int i=0; i<=max; i++) {
|
|
407
|
+
if (test_bit(bytes, i)) {
|
|
408
|
+
PyObject *val = PyLong_FromLong(i);
|
|
409
|
+
PyList_Append(res, val);
|
|
410
|
+
Py_DECREF(val);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return res;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
static PyObject *
|
|
419
|
+
ioctl_EVIOCGEFFECTS(PyObject *self, PyObject *args)
|
|
420
|
+
{
|
|
421
|
+
int fd, ret, res;
|
|
422
|
+
ret = PyArg_ParseTuple(args, "i", &fd);
|
|
423
|
+
if (!ret) return NULL;
|
|
424
|
+
|
|
425
|
+
ret = ioctl(fd, EVIOCGEFFECTS, &res);
|
|
426
|
+
if (ret == -1)
|
|
427
|
+
return NULL;
|
|
428
|
+
|
|
429
|
+
return Py_BuildValue("i", res);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
void print_ff_effect(struct ff_effect* effect) {
|
|
433
|
+
fprintf(stderr,
|
|
434
|
+
"ff_effect:\n"
|
|
435
|
+
" type: %d \n"
|
|
436
|
+
" id: %d \n"
|
|
437
|
+
" direction: %d\n"
|
|
438
|
+
" trigger: (%d, %d)\n"
|
|
439
|
+
" replay: (%d, %d)\n",
|
|
440
|
+
effect->type, effect->id, effect->direction,
|
|
441
|
+
effect->trigger.button, effect->trigger.interval,
|
|
442
|
+
effect->replay.length, effect->replay.delay
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
switch (effect->type) {
|
|
447
|
+
case FF_CONSTANT:
|
|
448
|
+
fprintf(stderr, " constant: (%d, (%d, %d, %d, %d))\n", effect->u.constant.level,
|
|
449
|
+
effect->u.constant.envelope.attack_length,
|
|
450
|
+
effect->u.constant.envelope.attack_level,
|
|
451
|
+
effect->u.constant.envelope.fade_length,
|
|
452
|
+
effect->u.constant.envelope.fade_level);
|
|
453
|
+
break;
|
|
454
|
+
case FF_RUMBLE:
|
|
455
|
+
fprintf(stderr, " rumble: (%d, %d)\n",
|
|
456
|
+
effect->u.rumble.strong_magnitude,
|
|
457
|
+
effect->u.rumble.weak_magnitude);
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
static PyObject *
|
|
464
|
+
upload_effect(PyObject *self, PyObject *args)
|
|
465
|
+
{
|
|
466
|
+
int fd, ret;
|
|
467
|
+
PyObject* effect_data;
|
|
468
|
+
ret = PyArg_ParseTuple(args, "iO", &fd, &effect_data);
|
|
469
|
+
if (!ret) return NULL;
|
|
470
|
+
|
|
471
|
+
void* data = PyBytes_AsString(effect_data);
|
|
472
|
+
struct ff_effect effect = {};
|
|
473
|
+
memmove(&effect, data, sizeof(struct ff_effect));
|
|
474
|
+
|
|
475
|
+
// print_ff_effect(&effect);
|
|
476
|
+
|
|
477
|
+
ret = ioctl(fd, EVIOCSFF, &effect);
|
|
478
|
+
if (ret != 0) {
|
|
479
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
480
|
+
return NULL;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return Py_BuildValue("i", effect.id);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
static PyObject *
|
|
488
|
+
erase_effect(PyObject *self, PyObject *args)
|
|
489
|
+
{
|
|
490
|
+
int fd, ret;
|
|
491
|
+
PyObject* ff_id_obj;
|
|
492
|
+
ret = PyArg_ParseTuple(args, "iO", &fd, &ff_id_obj);
|
|
493
|
+
if (!ret) return NULL;
|
|
494
|
+
|
|
495
|
+
long ff_id = PyLong_AsLong(ff_id_obj);
|
|
496
|
+
ret = ioctl(fd, EVIOCRMFF, ff_id);
|
|
497
|
+
if (ret != 0) {
|
|
498
|
+
PyErr_SetFromErrno(PyExc_OSError);
|
|
499
|
+
return NULL;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
Py_INCREF(Py_None);
|
|
503
|
+
return Py_None;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
static PyObject *
|
|
507
|
+
ioctl_EVIOCGPROP(PyObject *self, PyObject *args)
|
|
508
|
+
{
|
|
509
|
+
int fd, ret;
|
|
510
|
+
|
|
511
|
+
ret = PyArg_ParseTuple(args, "i", &fd);
|
|
512
|
+
if (!ret) return NULL;
|
|
513
|
+
|
|
514
|
+
char bytes[(INPUT_PROP_MAX+7)/8];
|
|
515
|
+
memset(bytes, 0, sizeof bytes);
|
|
516
|
+
|
|
517
|
+
ret = ioctl(fd, EVIOCGPROP(sizeof(bytes)), &bytes);
|
|
518
|
+
|
|
519
|
+
if (ret == -1)
|
|
520
|
+
return NULL;
|
|
521
|
+
|
|
522
|
+
PyObject* res = PyList_New(0);
|
|
523
|
+
for (int i=0; i<INPUT_PROP_MAX; i++) {
|
|
524
|
+
if (test_bit(bytes, i)) {
|
|
525
|
+
PyObject *val = PyLong_FromLong(i);
|
|
526
|
+
PyList_Append(res, val);
|
|
527
|
+
Py_DECREF(val);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return res;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
static PyMethodDef MethodTable[] = {
|
|
536
|
+
{ "ioctl_devinfo", ioctl_devinfo, METH_VARARGS, "fetch input device info" },
|
|
537
|
+
{ "ioctl_capabilities", ioctl_capabilities, METH_VARARGS, "fetch input device capabilities" },
|
|
538
|
+
{ "ioctl_EVIOCGABS", ioctl_EVIOCGABS, METH_VARARGS, "get input device absinfo"},
|
|
539
|
+
{ "ioctl_EVIOCSABS", ioctl_EVIOCSABS, METH_VARARGS, "set input device absinfo"},
|
|
540
|
+
{ "ioctl_EVIOCGREP", ioctl_EVIOCGREP, METH_VARARGS},
|
|
541
|
+
{ "ioctl_EVIOCSREP", ioctl_EVIOCSREP, METH_VARARGS},
|
|
542
|
+
{ "ioctl_EVIOCGVERSION", ioctl_EVIOCGVERSION, METH_VARARGS},
|
|
543
|
+
{ "ioctl_EVIOCGRAB", ioctl_EVIOCGRAB, METH_VARARGS},
|
|
544
|
+
{ "ioctl_EVIOCGEFFECTS", ioctl_EVIOCGEFFECTS, METH_VARARGS, "fetch the number of effects the device can keep in its memory." },
|
|
545
|
+
{ "ioctl_EVIOCG_bits", ioctl_EVIOCG_bits, METH_VARARGS, "get state of KEY|LED|SND|SW"},
|
|
546
|
+
{ "ioctl_EVIOCGPROP", ioctl_EVIOCGPROP, METH_VARARGS, "get device properties"},
|
|
547
|
+
{ "device_read", device_read, METH_VARARGS, "read an input event from a device" },
|
|
548
|
+
{ "device_read_many", device_read_many, METH_VARARGS, "read all available input events from a device" },
|
|
549
|
+
{ "upload_effect", upload_effect, METH_VARARGS, "" },
|
|
550
|
+
{ "erase_effect", erase_effect, METH_VARARGS, "" },
|
|
551
|
+
|
|
552
|
+
{ NULL, NULL, 0, NULL}
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
static struct PyModuleDef moduledef = {
|
|
557
|
+
PyModuleDef_HEAD_INIT,
|
|
558
|
+
"_input",
|
|
559
|
+
"Python bindings to certain linux input subsystem functions",
|
|
560
|
+
-1, /* m_size */
|
|
561
|
+
MethodTable, /* m_methods */
|
|
562
|
+
NULL, /* m_reload */
|
|
563
|
+
NULL, /* m_traverse */
|
|
564
|
+
NULL, /* m_clear */
|
|
565
|
+
NULL, /* m_free */
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
static PyObject *
|
|
569
|
+
moduleinit(void)
|
|
570
|
+
{
|
|
571
|
+
PyObject* m = PyModule_Create(&moduledef);
|
|
572
|
+
if (m == NULL) return NULL;
|
|
573
|
+
return m;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
PyMODINIT_FUNC
|
|
577
|
+
PyInit__input(void)
|
|
578
|
+
{
|
|
579
|
+
return moduleinit();
|
|
580
|
+
}
|
evdev/py.typed
ADDED
|
File without changes
|