Skip to content

Instantly share code, notes, and snippets.

@hrchu
Last active July 7, 2020 03:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hrchu/2b7fc9ca09c0f51a321b5ae13f83e28a to your computer and use it in GitHub Desktop.
Save hrchu/2b7fc9ca09c0f51a321b5ae13f83e28a to your computer and use it in GitHub Desktop.
Get input event device name via ioctl by CPython extension module
#include <Python.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
char* getDeviceName(char* device, char* name, size_t len)
{
int fd = -1;
int result = 0;
fd = open(device, O_RDONLY);
// EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) (linux/input.h)
int request = EVIOCGNAME(len);
result = ioctl(fd, request, name);
close(fd);
}
static PyObject * get_device_name(PyObject *self, PyObject *args) {
// parse input
const char *device;
if (!PyArg_ParseTuple(args, "s", &device))
return NULL;
char name[256] = "Unknown";
getDeviceName(device, name, 256);
// return name
return Py_BuildValue("s", name);
}
static PyMethodDef EVIOCG_Methods[] = {
{"get_device_name", get_device_name, METH_VARARGS,
"Get device name."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef EVIOCG_MODULE = {
PyModuleDef_HEAD_INIT,
"eviocg", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
EVIOCG_Methods
};
PyMODINIT_FUNC PyInit_eviocg(void) {
PyObject* m = PyModule_Create(&EVIOCG_MODULE);
if (m == NULL) {
return NULL;
}
return m;
}
"""
courtesy of https://github.com/vpelletier/python-ioctl-opt/blob/master/README.rst
"""
# -*- coding: utf-8 -*-
from ioctl_opt import IOC, IOC_READ
# porting from linux/input.h
EVIOCGNAME = lambda length: IOC(IOC_READ, ord('E'), 0x06, length)
import fcntl
def get_device_name(fd, length=1024):
name = bytearray(length)
actual_length = fcntl.ioctl(fd, EVIOCGNAME(length), name, True)
return name[:actual_length - 1].decode('UTF-8')
if __name__ == '__main__':
for i in range(7):
with open('/dev/input/event' + str(i)) as fd:
print(get_device_name(fd))
from setuptools import setup, Extension
module = Extension('eviocg', sources=['eviocgmodule.c'])
setup(name='eviocg', ext_modules=[module])
In [1]: import eviocg
In [2]: eviocg.get_device_name('/dev/input/event3')
Name : Video Bus
Out[2]: 'Video Bus'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment