diff --git a/recipes/evdev/patches/evcnt.patch b/recipes/evdev/patches/evcnt.patch new file mode 100644 index 0000000000..f140ddd655 --- /dev/null +++ b/recipes/evdev/patches/evcnt.patch @@ -0,0 +1,21 @@ +diff -Naur orig/evdev/input.c v0.4.7/evdev/input.c +--- orig/evdev/input.c 2015-06-11 13:56:43.483891914 -0500 ++++ v0.4.7/evdev/input.c 2015-06-11 13:57:29.079529095 -0500 +@@ -24,6 +24,8 @@ + #include + #endif + ++#define EV_CNT (EV_MAX+1) ++ + #define MAX_NAME_SIZE 256 + + extern char* EV_NAME[EV_CNT]; +@@ -190,7 +192,7 @@ + absinfo.maximum, + absinfo.fuzz, + absinfo.flat, +- absinfo.resolution); ++ 0); + + evlong = PyLong_FromLong(ev_code); + absitem = Py_BuildValue("(OO)", evlong, py_absinfo); diff --git a/recipes/evdev/patches/evdev-permissions.patch b/recipes/evdev/patches/evdev-permissions.patch new file mode 100644 index 0000000000..0faa6e786c --- /dev/null +++ b/recipes/evdev/patches/evdev-permissions.patch @@ -0,0 +1,57 @@ +diff -Naur orig/evdev/util.py v0.4.7/evdev/util.py +--- orig/evdev/util.py 2015-06-12 16:31:46.532994729 -0500 ++++ v0.4.7/evdev/util.py 2015-06-12 16:32:59.489933840 -0500 +@@ -3,15 +3,53 @@ + import os + import stat + import glob ++import subprocess + + from evdev import ecodes + from evdev.events import event_factory + + ++su = False ++ ++ ++def get_su_binary(): ++ global su ++ if su is not False: ++ return su ++ ++ su_files = ['/sbin/su', '/system/bin/su', '/system/xbin/su', '/data/local/xbin/su', ++ '/data/local/bin/su', '/system/sd/xbin/su', '/system/bin/failsafe/su', ++ '/data/local/su'] ++ su = None ++ ++ for fn in su_files: ++ if os.path.exists(fn): ++ try: ++ cmd = [fn, '-c', 'id'] ++ output = subprocess.check_output(cmd) ++ except Exception: ++ pass ++ else: ++ if 'uid=0' in output: ++ su = fn ++ break ++ ++ return su ++ ++ ++def fix_permissions(nodes): ++ su = get_su_binary() ++ if su: ++ cmd = 'chmod 666 ' + ' '.join(nodes) ++ print cmd ++ subprocess.check_call(['su', '-c', cmd]) ++ ++ + def list_devices(input_device_dir='/dev/input'): + '''List readable character devices in ``input_device_dir``.''' + + fns = glob.glob('{}/event*'.format(input_device_dir)) ++ fix_permissions(fns) + fns = list(filter(is_device, fns)) + + return fns diff --git a/recipes/evdev/patches/include-dir.patch b/recipes/evdev/patches/include-dir.patch new file mode 100644 index 0000000000..01187b64d3 --- /dev/null +++ b/recipes/evdev/patches/include-dir.patch @@ -0,0 +1,12 @@ +diff -Naur orig/setup.py v0.4.7/setup.py +--- orig/setup.py 2015-06-11 14:16:31.315765908 -0500 ++++ v0.4.7/setup.py 2015-06-11 14:17:05.800263536 -0500 +@@ -64,7 +64,7 @@ + + #----------------------------------------------------------------------------- + def create_ecodes(): +- header = '/usr/include/linux/input.h' ++ header = '##INCLUDE_DIR##/usr/include/linux/input.h' + + if not os.path.isfile(header): + msg = '''\ diff --git a/recipes/evdev/patches/keycnt.patch b/recipes/evdev/patches/keycnt.patch new file mode 100644 index 0000000000..c0f9c128ba --- /dev/null +++ b/recipes/evdev/patches/keycnt.patch @@ -0,0 +1,20 @@ +diff -Naur orig/evdev/genecodes.py v0.4.7/evdev/genecodes.py +--- orig/evdev/genecodes.py 2015-06-12 11:18:39.460538902 -0500 ++++ v0.4.7/evdev/genecodes.py 2015-06-12 11:20:49.004337615 -0500 +@@ -17,6 +17,8 @@ + #include + #endif + ++#define KEY_CNT (KEY_MAX+1) ++ + /* Automatically generated by evdev.genecodes */ + /* Generated on %s */ + +@@ -88,6 +88,7 @@ + macro = regex.search(line) + if macro: + yield ' PyModule_AddIntMacro(m, %s);' % macro.group(1) ++ yield ' PyModule_AddIntMacro(m, KEY_CNT);' + + uname = list(os.uname()); del uname[1] + uname = ' '.join(uname) diff --git a/recipes/evdev/patches/remove-uinput.patch b/recipes/evdev/patches/remove-uinput.patch new file mode 100644 index 0000000000..82af122e08 --- /dev/null +++ b/recipes/evdev/patches/remove-uinput.patch @@ -0,0 +1,523 @@ +diff -Naur orig/evdev/device.py v0.4.7/evdev/device.py +--- orig/evdev/device.py 2015-06-11 14:05:00.452884781 -0500 ++++ v0.4.7/evdev/device.py 2015-06-11 14:05:47.606553546 -0500 +@@ -4,7 +4,7 @@ + from select import select + from collections import namedtuple + +-from evdev import _input, _uinput, ecodes, util ++from evdev import _input, ecodes, util + from evdev.events import InputEvent + + +@@ -203,7 +203,7 @@ + + .. + ''' +- _uinput.write(self.fd, ecodes.EV_LED, led_num, value) ++ pass + + def __eq__(self, other): + '''Two devices are equal if their :data:`info` attributes are equal.''' +diff -Naur orig/evdev/__init__.py v0.4.7/evdev/__init__.py +--- orig/evdev/__init__.py 2015-06-11 14:05:00.452884781 -0500 ++++ v0.4.7/evdev/__init__.py 2015-06-11 14:05:22.973204070 -0500 +@@ -6,7 +6,6 @@ + + from evdev.device import DeviceInfo, InputDevice, AbsInfo + from evdev.events import InputEvent, KeyEvent, RelEvent, SynEvent, AbsEvent, event_factory +-from evdev.uinput import UInput, UInputError + from evdev.util import list_devices, categorize, resolve_ecodes + from evdev import ecodes + from evdev import ff +diff -Naur orig/evdev/uinput.c v0.4.7/evdev/uinput.c +--- orig/evdev/uinput.c 2015-06-11 14:05:00.453884795 -0500 ++++ v0.4.7/evdev/uinput.c 1969-12-31 18:00:00.000000000 -0600 +@@ -1,255 +0,0 @@ +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifdef __FreeBSD__ +-#include +-#include +-#else +-#include +-#include +-#endif +- +-int _uinput_close(int fd) +-{ +- if (ioctl(fd, UI_DEV_DESTROY) < 0) { +- int oerrno = errno; +- close(fd); +- errno = oerrno; +- return -1; +- } +- +- return close(fd); +-} +- +- +-static PyObject * +-uinput_open(PyObject *self, PyObject *args) +-{ +- const char* devnode; +- +- int ret = PyArg_ParseTuple(args, "s", &devnode); +- if (!ret) return NULL; +- +- int fd = open(devnode, O_WRONLY | O_NONBLOCK); +- if (fd < 0) { +- PyErr_SetString(PyExc_IOError, "could not open uinput device in write mode"); +- return NULL; +- } +- +- return Py_BuildValue("i", fd); +-} +- +- +-static PyObject * +-uinput_create(PyObject *self, PyObject *args) { +- int fd, len, i, abscode; +- uint16_t vendor, product, version, bustype; +- +- PyObject *absinfo = NULL, *item = NULL; +- +- struct uinput_user_dev uidev; +- const char* name; +- +- int ret = PyArg_ParseTuple(args, "ishhhhO", &fd, &name, &vendor, +- &product, &version, &bustype, &absinfo); +- if (!ret) return NULL; +- +- memset(&uidev, 0, sizeof(uidev)); +- strncpy(uidev.name, name, UINPUT_MAX_NAME_SIZE); +- uidev.id.vendor = vendor; +- uidev.id.product = product; +- uidev.id.version = version; +- uidev.id.bustype = bustype; +- +- len = PyList_Size(absinfo); +- for (i=0; i (ABS_X, 0, 255, 0, 0) +- item = PyList_GetItem(absinfo, i); +- abscode = (int)PyLong_AsLong(PyList_GetItem(item, 0)); +- +- uidev.absmin[abscode] = PyLong_AsLong(PyList_GetItem(item, 1)); +- uidev.absmax[abscode] = PyLong_AsLong(PyList_GetItem(item, 2)); +- uidev.absfuzz[abscode] = PyLong_AsLong(PyList_GetItem(item, 3)); +- uidev.absflat[abscode] = PyLong_AsLong(PyList_GetItem(item, 4)); +- } +- +- if (write(fd, &uidev, sizeof(uidev)) != sizeof(uidev)) +- goto on_err; +- +- /* if (ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0) */ +- /* goto on_err; */ +- /* int i; */ +- /* for (i=0; i= 3 +-static struct PyModuleDef moduledef = { +- PyModuleDef_HEAD_INIT, +- MODULE_NAME, +- MODULE_HELP, +- -1, /* m_size */ +- MethodTable, /* m_methods */ +- NULL, /* m_reload */ +- NULL, /* m_traverse */ +- NULL, /* m_clear */ +- NULL, /* m_free */ +-}; +- +-static PyObject * +-moduleinit(void) +-{ +- PyObject* m = PyModule_Create(&moduledef); +- if (m == NULL) return NULL; +- +- PyModule_AddIntConstant(m, "maxnamelen", UINPUT_MAX_NAME_SIZE); +- return m; +-} +- +-PyMODINIT_FUNC +-PyInit__uinput(void) +-{ +- return moduleinit(); +-} +- +-#else +-static PyObject * +-moduleinit(void) +-{ +- PyObject* m = Py_InitModule3(MODULE_NAME, MethodTable, MODULE_HELP); +- if (m == NULL) return NULL; +- +- PyModule_AddIntConstant(m, "maxnamelen", UINPUT_MAX_NAME_SIZE); +- return m; +-} +- +-PyMODINIT_FUNC +-init_uinput(void) +-{ +- moduleinit(); +-} +-#endif +diff -Naur orig/evdev/uinput.py v0.4.7/evdev/uinput.py +--- orig/evdev/uinput.py 2015-06-11 14:05:00.453884795 -0500 ++++ v0.4.7/evdev/uinput.py 1969-12-31 18:00:00.000000000 -0600 +@@ -1,208 +0,0 @@ +-# encoding: utf-8 +- +-import os +-import stat +-import time +- +-from evdev import _uinput +-from evdev import ecodes, util, device +- +- +-class UInputError(Exception): +- pass +- +- +-class UInput(object): +- ''' +- A userland input device and that can inject input events into the +- linux input subsystem. +- ''' +- +- __slots__ = ( +- 'name', 'vendor', 'product', 'version', 'bustype', +- 'events', 'devnode', 'fd', 'device', +- ) +- +- def __init__(self, +- events=None, +- name='py-evdev-uinput', +- vendor=0x1, product=0x1, version=0x1, bustype=0x3, +- devnode='/dev/uinput'): +- ''' +- :param events: the event types and codes that the uinput +- device will be able to inject - defaults to all +- key codes. +- +- :type events: dictionary of event types mapping to lists of +- event codes. +- +- :param name: the name of the input device. +- :param vendor: vendor identifier. +- :param product: product identifier. +- :param version: version identifier. +- :param bustype: bustype identifier. +- +- .. note:: If you do not specify any events, the uinput device +- will be able to inject only ``KEY_*`` and ``BTN_*`` +- event codes. +- ''' +- +- self.name = name #: Uinput device name. +- self.vendor = vendor #: Device vendor identifier. +- self.product = product #: Device product identifier. +- self.version = version #: Device version identifier. +- self.bustype = bustype #: Device bustype - eg. ``BUS_USB``. +- self.devnode = devnode #: Uinput device node - eg. ``/dev/uinput/``. +- +- if not events: +- events = {ecodes.EV_KEY: ecodes.keys.keys()} +- +- # the min, max, fuzz and flat values for the absolute axis for +- # a given code +- absinfo = [] +- +- self._verify() +- +- #: Write-only, non-blocking file descriptor to the uinput device node. +- self.fd = _uinput.open(devnode) +- +- # set device capabilities +- for etype, codes in events.items(): +- for code in codes: +- # handle max, min, fuzz, flat +- if isinstance(code, (tuple, list, device.AbsInfo)): +- # flatten (ABS_Y, (0, 255, 0, 0)) to (ABS_Y, 0, 255, 0, 0) +- f = [code[0]]; f += code[1] +- absinfo.append(f) +- code = code[0] +- +- #:todo: a lot of unnecessary packing/unpacking +- _uinput.enable(self.fd, etype, code) +- +- # create uinput device +- _uinput.create(self.fd, name, vendor, product, version, bustype, absinfo) +- +- #: An :class:`InputDevice ` instance +- #: for the fake input device. ``None`` if the device cannot be +- #: opened for reading and writing. +- self.device = self._find_device() +- +- def __enter__(self): +- return self +- +- def __exit__(self, type, value, tb): +- if hasattr(self, 'fd'): +- self.close() +- +- def __repr__(self): +- # :todo: +- v = (repr(getattr(self, i)) for i in +- ('name', 'bustype', 'vendor', 'product', 'version')) +- return '{}({})'.format(self.__class__.__name__, ', '.join(v)) +- +- def __str__(self): +- msg = ('name "{}", bus "{}", vendor "{:04x}", product "{:04x}", version "{:04x}"\n' +- 'event types: {}') +- +- evtypes = [i[0] for i in self.capabilities(True).keys()] +- msg = msg.format(self.name, ecodes.BUS[self.bustype], +- self.vendor, self.product, +- self.version, ' '.join(evtypes)) +- +- return msg +- +- def close(self): +- # close the associated InputDevice, if it was previously opened +- if self.device is not None: +- self.device.close() +- +- # destroy the uinput device +- if self.fd > -1: +- _uinput.close(self.fd) +- self.fd = -1 +- +- def write_event(self, event): +- ''' +- Inject an input event into the input subsystem. Events are +- queued until a synchronization event is received. +- +- :param event: InputEvent instance or an object with an +- ``event`` attribute (:class:`KeyEvent +- `, :class:`RelEvent +- ` etc). +- +- Example:: +- +- ev = InputEvent(1334414993, 274296, ecodes.EV_KEY, ecodes.KEY_A, 1) +- ui.write_event(ev) +- ''' +- +- if hasattr(event, 'event'): +- event = event.event +- +- self.write(event.type, event.code, event.value) +- +- def write(self, etype, code, value): +- ''' +- Inject an input event into the input subsystem. Events are +- queued until a synchronization event is received. +- +- :param etype: event type (eg. ``EV_KEY``). +- :param code: event code (eg. ``KEY_A``). +- :param value: event value (eg. 0 1 2 - depends on event type). +- +- Example:: +- +- ui.write(e.EV_KEY, e.KEY_A, 1) # key A - down +- ui.write(e.EV_KEY, e.KEY_A, 0) # key A - up +- ''' +- +- _uinput.write(self.fd, etype, code, value) +- +- def syn(self): +- ''' +- Inject a ``SYN_REPORT`` event into the input subsystem. Events +- queued by :func:`write()` will be fired. If possible, events +- will be merged into an 'atomic' event. +- ''' +- +- _uinput.write(self.fd, ecodes.EV_SYN, ecodes.SYN_REPORT, 0) +- +- def capabilities(self, verbose=False, absinfo=True): +- '''See :func:`capabilities `.''' +- if self.device is None: +- raise UInputError('input device not opened - cannot read capabilites') +- +- return self.device.capabilities(verbose, absinfo) +- +- def _verify(self): +- ''' +- Verify that an uinput device exists and is readable and writable +- by the current process. +- ''' +- +- try: +- m = os.stat(self.devnode)[stat.ST_MODE] +- if not stat.S_ISCHR(m): +- raise +- except (IndexError, OSError): +- msg = '"{}" does not exist or is not a character device file '\ +- '- verify that the uinput module is loaded' +- raise UInputError(msg.format(self.devnode)) +- +- if not os.access(self.devnode, os.W_OK): +- msg = '"{}" cannot be opened for writing' +- raise UInputError(msg.format(self.devnode)) +- +- if len(self.name) > _uinput.maxnamelen: +- msg = 'uinput device name must not be longer than {} characters' +- raise UInputError(msg.format(_uinput.maxnamelen)) +- +- def _find_device(self): +- #:bug: the device node might not be immediately available +- time.sleep(0.1) +- +- for fn in util.list_devices('/dev/input/'): +- d = device.InputDevice(fn) +- if d.name == self.name: +- return d +diff -Naur orig/setup.py v0.4.7/setup.py +--- orig/setup.py 2015-06-11 14:05:00.450884753 -0500 ++++ v0.4.7/setup.py 2015-06-11 14:06:13.050914776 -0500 +@@ -37,7 +37,6 @@ + #----------------------------------------------------------------------------- + cflags = ['-std=c99', '-Wno-error=declaration-after-statement'] + input_c = Extension('evdev._input', sources=['evdev/input.c'], extra_compile_args=cflags) +-uinput_c = Extension('evdev._uinput', sources=['evdev/uinput.c'], extra_compile_args=cflags) + ecodes_c = Extension('evdev._ecodes', sources=['evdev/ecodes.c'], extra_compile_args=cflags) + + #----------------------------------------------------------------------------- +@@ -56,7 +55,7 @@ + 'classifiers': classifiers, + + 'packages': ['evdev'], +- 'ext_modules': [input_c, uinput_c, ecodes_c], ++ 'ext_modules': [input_c, ecodes_c], + 'include_package_data': False, + 'zip_safe': True, + 'cmdclass': {}, diff --git a/recipes/evdev/recipe.sh b/recipes/evdev/recipe.sh new file mode 100644 index 0000000000..9e9d5d46f0 --- /dev/null +++ b/recipes/evdev/recipe.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# NOTE: This recipe probably requires root in order to do anything useful, +# though that requirement may vary by device. It will automatically +# try to gain root and fix permissions on /dev/input/event*. On the +# test device (Nexus 10, 2012 version), root was necessary to overcome +# the default permissions. +# +# Also, support for UInput has been removed from the package, as +# UInput is not supported by the Android kernel. + + +VERSION_evdev=v0.4.7 +URL_evdev=https://github.com/gvalkov/python-evdev/archive/${VERSION_evdev}.zip +DEPS_evdev=(python) +MD5_evdev=0952529ea9ae45edb9db148415b7ddba +BUILD_evdev=$BUILD_PATH/evdev/$(get_directory $URL_evdev) +RECIPE_evdev=$RECIPES_PATH/evdev + +function prebuild_evdev() { + cd $BUILD_evdev + + if [ -f .patched ]; then + return + fi + + try patch -p1 < $RECIPE_evdev/patches/evcnt.patch + try patch -p1 < $RECIPE_evdev/patches/keycnt.patch + try patch -p1 < $RECIPE_evdev/patches/remove-uinput.patch + try patch -p1 < $RECIPE_evdev/patches/include-dir.patch + try patch -p1 < $RECIPE_evdev/patches/evdev-permissions.patch + + try sed -i 's,##INCLUDE_DIR##,'$NDKPLATFORM',' setup.py + + touch .patched +} + +function shouldbuild_evdev() { + if [ -d "$SITEPACKAGES_PATH/evdev" ]; then + DO_BUILD=0 + fi +} + +function build_evdev() { + cd $BUILD_evdev + + push_arm + + export LDFLAGS="$LDFLAGS -L$LIBS_PATH" + export LDSHARED="$LIBLINK" + + try $HOSTPYTHON setup.py build -v + try find build/lib.* -name "*.o" -exec $STRIP {} \; + try $HOSTPYTHON setup.py install -O2 + + unset LDSHARED + pop_arm +} + +function postbuild_evdev() { + true +}