evdev module-----uinput.py

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
原文地址:https://www.cnblogs.com/winditsway/p/5665830.html