1 #include <Python.h>
2 
3 #include <stdio.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 
11 #include <linux/input.h>
12 #include <linux/uinput.h>
13 
14 #ifndef input_event_sec
15 #define input_event_sec time.tv_sec
16 #define input_event_usec time.tv_usec
17 #endif
18 
19 // Workaround for installing on kernels newer than 4.4.
20 #ifndef FF_MAX_EFFECTS
21 #define FF_MAX_EFFECTS FF_GAIN;
22 #endif
23 
_uinput_close(int fd)24 int _uinput_close(int fd)
25 {
26     if (ioctl(fd, UI_DEV_DESTROY) < 0) {
27         int oerrno = errno;
28         close(fd);
29         errno = oerrno;
30         return -1;
31     }
32 
33     return close(fd);
34 }
35 
36 
37 static PyObject *
uinput_open(PyObject * self,PyObject * args)38 uinput_open(PyObject *self, PyObject *args)
39 {
40     const char* devnode;
41 
42     int ret = PyArg_ParseTuple(args, "s", &devnode);
43     if (!ret) return NULL;
44 
45     int fd = open(devnode, O_RDWR | O_NONBLOCK);
46     if (fd < 0) {
47         PyErr_SetString(PyExc_IOError, "could not open uinput device in write mode");
48         return NULL;
49     }
50 
51     return Py_BuildValue("i", fd);
52 }
53 
54 
55 static PyObject *
uinput_set_phys(PyObject * self,PyObject * args)56 uinput_set_phys(PyObject *self, PyObject *args)
57 {
58     int fd;
59     const char* phys;
60 
61     int ret = PyArg_ParseTuple(args, "is", &fd, &phys);
62     if (!ret) return NULL;
63 
64     if (ioctl(fd, UI_SET_PHYS, phys) < 0)
65         goto on_err;
66 
67     Py_RETURN_NONE;
68 
69     on_err:
70         _uinput_close(fd);
71         PyErr_SetFromErrno(PyExc_IOError);
72         return NULL;
73 }
74 
75 static PyObject *
uinput_set_prop(PyObject * self,PyObject * args)76 uinput_set_prop(PyObject *self, PyObject *args)
77 {
78     int fd;
79     uint16_t prop;
80 
81     int ret = PyArg_ParseTuple(args, "ih", &fd, &prop);
82     if (!ret) return NULL;
83 
84     if (ioctl(fd, UI_SET_PROPBIT, prop) < 0)
85         goto on_err;
86 
87     Py_RETURN_NONE;
88 
89     on_err:
90         _uinput_close(fd);
91         PyErr_SetFromErrno(PyExc_IOError);
92         return NULL;
93 }
94 
95 
96 // Different kernel versions have different device setup methods. You can read
97 // more about it here:
98 // https://github.com/torvalds/linux/commit/052876f8e5aec887d22c4d06e54aa5531ffcec75
99 
100 // Setup function for kernel >= v4.5
101 #if defined(UI_DEV_SETUP) && defined(UI_ABS_SETUP)
102 static PyObject *
uinput_setup(PyObject * self,PyObject * args)103 uinput_setup(PyObject *self, PyObject *args) {
104     int fd, len, i;
105     uint16_t vendor, product, version, bustype;
106 
107     PyObject *absinfo = NULL, *item = NULL;
108 
109     struct uinput_abs_setup abs_setup;
110 
111     const char* name;
112     int ret = PyArg_ParseTuple(args, "isHHHHO", &fd, &name, &vendor,
113                                &product, &version, &bustype, &absinfo);
114     if (!ret) return NULL;
115 
116     // Setup absinfo:
117     len = PyList_Size(absinfo);
118     for (i=0; i<len; i++) {
119 
120         // item -> (ABS_X, 0, 255, 0, 0, 0, 0)
121         item = PyList_GetItem(absinfo, i);
122 
123         memset(&abs_setup, 0, sizeof(abs_setup)); // Clear struct
124         abs_setup.code = PyLong_AsLong(PyList_GetItem(item, 0));
125         abs_setup.absinfo.value = PyLong_AsLong(PyList_GetItem(item, 1));
126         abs_setup.absinfo.minimum = PyLong_AsLong(PyList_GetItem(item, 2));
127         abs_setup.absinfo.maximum = PyLong_AsLong(PyList_GetItem(item, 3));
128         abs_setup.absinfo.fuzz = PyLong_AsLong(PyList_GetItem(item, 4));
129         abs_setup.absinfo.flat = PyLong_AsLong(PyList_GetItem(item, 5));
130         abs_setup.absinfo.resolution = PyLong_AsLong(PyList_GetItem(item, 6));
131 
132         if(ioctl(fd, UI_ABS_SETUP, &abs_setup) < 0)
133             goto on_err;
134     }
135 
136     // Setup evdev:
137     struct uinput_setup usetup;
138 
139     memset(&usetup, 0, sizeof(usetup));
140     strncpy(usetup.name, name, sizeof(usetup.name) - 1);
141     usetup.id.vendor  = vendor;
142     usetup.id.product = product;
143     usetup.id.version = version;
144     usetup.id.bustype = bustype;
145     usetup.ff_effects_max = FF_MAX_EFFECTS;
146 
147     if(ioctl(fd, UI_DEV_SETUP, &usetup) < 0)
148         goto on_err;
149 
150     Py_RETURN_NONE;
151 
152     on_err:
153         _uinput_close(fd);
154         PyErr_SetFromErrno(PyExc_IOError);
155         return NULL;
156 }
157 
158 // Fallback setup function (Linux <= 4.5 and FreeBSD).
159 #else
160 static PyObject *
uinput_setup(PyObject * self,PyObject * args)161 uinput_setup(PyObject *self, PyObject *args) {
162     int fd, len, i, abscode;
163     uint16_t vendor, product, version, bustype;
164 
165     PyObject *absinfo = NULL, *item = NULL;
166 
167     struct uinput_user_dev uidev;
168     const char* name;
169 
170     int ret = PyArg_ParseTuple(args, "isHHHHO", &fd, &name, &vendor,
171                                &product, &version, &bustype, &absinfo);
172     if (!ret) return NULL;
173 
174     memset(&uidev, 0, sizeof(uidev));
175     strncpy(uidev.name, name, sizeof(uidev.name) - 1);
176     uidev.id.vendor  = vendor;
177     uidev.id.product = product;
178     uidev.id.version = version;
179     uidev.id.bustype = bustype;
180     uidev.ff_effects_max = FF_MAX_EFFECTS;
181 
182     len = PyList_Size(absinfo);
183     for (i=0; i<len; i++) {
184         // item -> (ABS_X, 0, 255, 0, 0, 0, 0)
185         item = PyList_GetItem(absinfo, i);
186         abscode = (int)PyLong_AsLong(PyList_GetItem(item, 0));
187 
188         /* min/max/fuzz/flat start from index 2 because index 1 is value */
189         uidev.absmin[abscode]  = PyLong_AsLong(PyList_GetItem(item, 2));
190         uidev.absmax[abscode]  = PyLong_AsLong(PyList_GetItem(item, 3));
191         uidev.absfuzz[abscode] = PyLong_AsLong(PyList_GetItem(item, 4));
192         uidev.absflat[abscode] = PyLong_AsLong(PyList_GetItem(item, 5));
193     }
194 
195     if (write(fd, &uidev, sizeof(uidev)) != sizeof(uidev))
196         goto on_err;
197 
198     Py_RETURN_NONE;
199 
200     on_err:
201         _uinput_close(fd);
202         PyErr_SetFromErrno(PyExc_IOError);
203         return NULL;
204 }
205 #endif
206 
207 
208 static PyObject *
uinput_create(PyObject * self,PyObject * args)209 uinput_create(PyObject *self, PyObject *args)
210 {
211     int fd;
212 
213     int ret = PyArg_ParseTuple(args, "i", &fd);
214     if (!ret) return NULL;
215 
216     if (ioctl(fd, UI_DEV_CREATE) < 0)
217         goto on_err;
218 
219     Py_RETURN_NONE;
220 
221     on_err:
222         _uinput_close(fd);
223         PyErr_SetFromErrno(PyExc_IOError);
224         return NULL;
225 }
226 
227 
228 static PyObject *
uinput_close(PyObject * self,PyObject * args)229 uinput_close(PyObject *self, PyObject *args)
230 {
231     int fd;
232 
233     int ret = PyArg_ParseTuple(args, "i", &fd);
234     if (!ret) return NULL;
235 
236     if (_uinput_close(fd) < 0) {
237         PyErr_SetFromErrno(PyExc_IOError);
238         return NULL;
239     }
240 
241     Py_RETURN_NONE;
242 }
243 
244 
245 static PyObject *
uinput_write(PyObject * self,PyObject * args)246 uinput_write(PyObject *self, PyObject *args)
247 {
248     int fd, type, code, value;
249 
250     int ret = PyArg_ParseTuple(args, "iiii", &fd, &type, &code, &value);
251     if (!ret) return NULL;
252 
253     struct input_event event;
254     struct timeval tval;
255     memset(&event, 0, sizeof(event));
256     gettimeofday(&tval, 0);
257     event.input_event_usec = tval.tv_usec;
258     event.input_event_sec = tval.tv_sec;
259     event.type = type;
260     event.code = code;
261     event.value = value;
262 
263     if (write(fd, &event, sizeof(event)) != sizeof(event)) {
264         // @todo: elaborate
265         // PyErr_SetString(PyExc_IOError, "error writing event to uinput device");
266         PyErr_SetFromErrno(PyExc_IOError);
267         return NULL;
268     }
269 
270     Py_RETURN_NONE;
271 }
272 
273 
274 static PyObject *
uinput_enable_event(PyObject * self,PyObject * args)275 uinput_enable_event(PyObject *self, PyObject *args)
276 {
277     int fd;
278     uint16_t type, code;
279     unsigned long req;
280 
281     int ret = PyArg_ParseTuple(args, "ihh", &fd, &type, &code);
282     if (!ret) return NULL;
283 
284     switch (type) {
285         case EV_KEY: req = UI_SET_KEYBIT; break;
286         case EV_ABS: req = UI_SET_ABSBIT; break;
287         case EV_REL: req = UI_SET_RELBIT; break;
288         case EV_MSC: req = UI_SET_MSCBIT; break;
289         case EV_SW:  req = UI_SET_SWBIT;  break;
290         case EV_LED: req = UI_SET_LEDBIT; break;
291         case EV_FF:  req = UI_SET_FFBIT;  break;
292         case EV_SND: req = UI_SET_SNDBIT; break;
293         default:
294             errno = EINVAL;
295             goto on_err;
296     }
297 
298     if (ioctl(fd, UI_SET_EVBIT, type) < 0)
299         goto on_err;
300 
301     if (ioctl(fd, req, code) < 0)
302         goto on_err;
303 
304     Py_RETURN_NONE;
305 
306     on_err:
307         _uinput_close(fd);
308         PyErr_SetFromErrno(PyExc_IOError);
309         return NULL;
310 }
311 
_uinput_begin_upload(int fd,struct uinput_ff_upload * upload)312 int _uinput_begin_upload(int fd, struct uinput_ff_upload *upload)
313 {
314     return ioctl(fd, UI_BEGIN_FF_UPLOAD, upload);
315 }
316 
_uinput_end_upload(int fd,struct uinput_ff_upload * upload)317 int _uinput_end_upload(int fd, struct uinput_ff_upload *upload)
318 {
319     return ioctl(fd, UI_END_FF_UPLOAD, upload);
320 }
321 
_uinput_begin_erase(int fd,struct uinput_ff_erase * upload)322 int _uinput_begin_erase(int fd, struct uinput_ff_erase *upload)
323 {
324     return ioctl(fd, UI_BEGIN_FF_ERASE, upload);
325 }
326 
_uinput_end_erase(int fd,struct uinput_ff_erase * upload)327 int _uinput_end_erase(int fd, struct uinput_ff_erase *upload)
328 {
329     return ioctl(fd, UI_END_FF_ERASE, upload);
330 }
331 
332 #define MODULE_NAME "_uinput"
333 #define MODULE_HELP "Python bindings for parts of linux/uinput.c"
334 
335 static PyMethodDef MethodTable[] = {
336     { "open",  uinput_open, METH_VARARGS,
337       "Open uinput device node."},
338 
339     { "setup",  uinput_setup, METH_VARARGS,
340       "Set an uinput device up."},
341 
342     { "create",  uinput_create, METH_VARARGS,
343       "Create an uinput device."},
344 
345     { "close",  uinput_close, METH_VARARGS,
346       "Destroy uinput device."},
347 
348     { "write",  uinput_write, METH_VARARGS,
349       "Write event to uinput device."},
350 
351     { "enable", uinput_enable_event, METH_VARARGS,
352       "Enable a type of event."},
353 
354     { "set_phys", uinput_set_phys, METH_VARARGS,
355       "Set physical path"},
356 
357     { "set_prop", uinput_set_prop, METH_VARARGS,
358       "Set device input property"},
359 
360     { NULL, NULL, 0, NULL}
361 };
362 
363 #if PY_MAJOR_VERSION >= 3
364 static struct PyModuleDef moduledef = {
365     PyModuleDef_HEAD_INIT,
366     MODULE_NAME,
367     MODULE_HELP,
368     -1,          /* m_size */
369     MethodTable, /* m_methods */
370     NULL,        /* m_reload */
371     NULL,        /* m_traverse */
372     NULL,        /* m_clear */
373     NULL,        /* m_free */
374 };
375 
376 static PyObject *
moduleinit(void)377 moduleinit(void)
378 {
379     PyObject* m = PyModule_Create(&moduledef);
380     if (m == NULL) return NULL;
381 
382     PyModule_AddIntConstant(m, "maxnamelen", UINPUT_MAX_NAME_SIZE);
383     return m;
384 }
385 
386 PyMODINIT_FUNC
PyInit__uinput(void)387 PyInit__uinput(void)
388 {
389     return moduleinit();
390 }
391 
392 #else
393 static PyObject *
moduleinit(void)394 moduleinit(void)
395 {
396     PyObject* m = Py_InitModule3(MODULE_NAME, MethodTable, MODULE_HELP);
397     if (m == NULL) return NULL;
398 
399     PyModule_AddIntConstant(m, "maxnamelen", UINPUT_MAX_NAME_SIZE);
400     return m;
401 }
402 
403 PyMODINIT_FUNC
init_uinput(void)404 init_uinput(void)
405 {
406     moduleinit();
407 }
408 #endif
409