uinput.py , python code of evdev module
1 # encoding: utf-8 2 3 import os 4 import stat 5 import time 6 7 from evdev import _uinput 8 from evdev import ecodes, util, device 9 10 11 class UInputError(Exception): 12 pass 13 14 15 class UInput(object): 16 ''' 17 A userland input (an `uinput`) device and that can inject input 18 events directly into the linux input subsystem. 19 ''' 20 21 __slots__ = ( 22 'name', 'vendor', 'product', 'version', 'bustype', 23 'events', 'devnode', 'fd', 'device', 24 ) 25 26 def __init__(self, 27 events=None, 28 name='py-evdev-uinput', 29 vendor=0x1, product=0x1, version=0x1, bustype=0x3, 30 devnode='/dev/uinput'): 31 ''' 32 33 :param events: the event types and codes that the uinput 34 device will be able to inject - defaults to all 35 key codes. 36 37 :type events: dictionary of event types mapping to lists of 38 event codes 39 40 :param name: the name of the input device 41 :param vendor: vendor identifier 42 :param product: product identifier 43 :param version: version identifier 44 :param bustype: bustype identifier 45 46 .. note:: If you do not specify any events, the uinput device 47 will by default be able to inject only KEY_* and 48 BTN_* event codes. 49 50 ''' 51 52 self.name = name #: uinput device name 53 self.vendor = vendor #: device vendor identifier 54 self.product = product #: device product identifier 55 self.version = version #: device version identifier 56 self.bustype = bustype #: device bustype - eg. ``BUS_USB`` 57 self.devnode = devnode #: uinput device node - eg. ``/dev/uinput/`` 58 59 if not events: 60 events = {ecodes.EV_KEY: ecodes.keys.keys()} 61 62 # the min, max, fuzz and flat values for the absolute axis for 63 # a given code 64 absinfo = [] 65 66 self._verify() 67 68 #: open write-only, nonblocking file descriptor to the uinput devnode 69 self.fd = _uinput.open(devnode) 70 71 # set device capabilities 72 for etype, codes in events.items(): 73 for code in codes: 74 # handle max,min,fuzz,flat 75 if isinstance(code, (tuple, list, device.AbsInfo)): 76 # flatten (ABS_Y, (0,255,0,0)) to (ABS_Y,0,255,0,0) 77 f = [code[0]] ; f += code[1] 78 absinfo.append(f) 79 code = code[0] 80 81 #:todo: a lot of unnecessary packing/unpacking 82 _uinput.enable(self.fd, etype, code) 83 84 # create uinput device 85 _uinput.create(self.fd, name, vendor, product, version, bustype, absinfo) 86 87 #: an :class:`InputDevice` instance 88 # to the fake input device 89 self.device = self._find_device() 90 91 def __enter__(self): 92 return self 93 94 def __exit__(self, type, value, tb): 95 self.close() 96 97 def __repr__(self): 98 # :todo: 99 v = (repr(getattr(self, i)) for i in100 ('name', 'bustype', 'vendor', 'product', 'version'))101 return '{0}({1})'.format(self.__class__.__name__, ', '.join(v))102 103 def __str__(self):104 msg = ('name "{0}", bus "{1}", vendor "{2:04x}", product "{3:04x}", version "{4:04x}"\n'105 'event types: {5}')106 107 evtypes = [i[0] for i in self.capabilities(True).keys()]108 msg = msg.format(self.name, ecodes.BUS[self.bustype], self.vendor, self.product,109 self.version, ' '.join(evtypes))110 111 return msg112 113 def close(self):114 # close InputDevice object115 self.device.close()116 117 # destroy the uinput device118 if self.fd and self.fd > 0:119 _uinput.close(self.fd)120 121 def write_event(self, event):122 '''123 Inject an input event into the input subsystem. Events are124 queued until a synchronization event is received.125 126 :param event: InputEvent instance or an object with an127 ``event`` attribute (:class:`KeyEvent128 `, :class:`RelEvent129 ` etc)130 131 Example::132 133 ev = InputEvent(1334414993, 274296, ecodes.EV_KEY, ecodes.KEY_A, 1)134 ui.write_event(ev)135 '''136 137 if hasattr(event, 'event'):138 event = event.event139 140 self.write(event.type, event.code, event.value)141 142 def write(self, etype, code, value):143 '''144 145 Inject an input event into the input subsystem. Events are146 queued until a synchronization event is received.147 148 :param etype: event type (eg. ``EV_KEY``)149 :param code: event code (eg. ``KEY_A``)150 :param value: event value (eg. 0 1 2 - depends on event type)151 152 Example::153 154 ui.write(e.EV_KEY, e.KEY_A, 1) # key A - down155 ui.write(e.EV_KEY, e.KEY_A, 0) # key A - up156 '''157 158 _uinput.write(self.fd, etype, code, value)159 160 def syn(self):161 ''' Inject a ``SYN_REPORT`` event into the input subsystem. Events162 queued by :func:`write()` will be fired. If applicable, events163 will be merged into an 'atomic' event.'''164 165 _uinput.write(self.fd, ecodes.EV_SYN, ecodes.SYN_REPORT, 0)166 167 def capabilities(self, verbose=False, absinfo=True):168 '''See :func:`capabilities `.'''169 return self.device.capabilities(verbose, absinfo)170 171 def _verify(self):172 ''' Verify that an uinput device exists and is readable and writable173 by our process.'''174 175 try:176 m = os.stat(self.devnode)[stat.ST_MODE]177 if not stat.S_ISCHR(m):178 raise179 except:180 msg = '"{0}" does not exist or is not a character device file '\181 '- verify that the uinput module is loaded'182 raise UInputError(msg.format(self.devnode))183 184 if not os.access(self.devnode, os.W_OK):185 msg = '"{0}" cannot be opened for writing'186 raise UInputError(msg.format(self.devnode))187 188 if len(self.name) > _uinput.maxnamelen:189 msg = 'uinput device name must not be longer than {0} characters'190 raise UInputError(msg.format(_uinput.maxnamelen))191 192 def _find_device(self):193 #:todo: use udev194 195 #:bug: the device node might not be immediately avaiable196 time.sleep(0.1)197 198 for fn in util.list_devices('/dev/input/'):199 d = device.InputDevice(fn)200 if d.name == self.name:201 return d