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 <evdev.device.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 in 100 ('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}" ' 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 msg 112 113 def close(self): 114 # close InputDevice object 115 self.device.close() 116 117 # destroy the uinput device 118 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 are 124 queued until a synchronization event is received. 125 126 :param event: InputEvent instance or an object with an 127 ``event`` attribute (:class:`KeyEvent 128 <evdev.events.KeyEvent>`, :class:`RelEvent 129 <evdev.events.RelEvent>` 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.event 139 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 are 146 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 - down 155 ui.write(e.EV_KEY, e.KEY_A, 0) # key A - up 156 ''' 157 158 _uinput.write(self.fd, etype, code, value) 159 160 def syn(self): 161 ''' Inject a ``SYN_REPORT`` event into the input subsystem. Events 162 queued by :func:`write()` will be fired. If applicable, events 163 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 <evdev.device.InputDevice.capabilities>`.''' 169 return self.device.capabilities(verbose, absinfo) 170 171 def _verify(self): 172 ''' Verify that an uinput device exists and is readable and writable 173 by our process.''' 174 175 try: 176 m = os.stat(self.devnode)[stat.ST_MODE] 177 if not stat.S_ISCHR(m): 178 raise 179 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 udev 194 195 #:bug: the device node might not be immediately avaiable 196 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