cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
Input.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 # @COPYRIGHT_begin
3 #
4 # Copyright [2010-2014] Institute of Nuclear Physics PAN, Krakow, Poland
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # @COPYRIGHT_end
19 
20 #!/usr/bin/python2.4
21 # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
22 #
23 # $Id$
24 #
25 # Copyright (C) 1999-2006 Keith Dart <keith@kdart.com>
26 #
27 # This library is free software; you can redistribute it and/or
28 # modify it under the terms of the GNU Lesser General Public
29 # License as published by the Free Software Foundation; either
30 # version 2.1 of the License, or (at your option) any later version.
31 #
32 # This library is distributed in the hope that it will be useful,
33 # but WITHOUT ANY WARRANTY; without even the implied warranty of
34 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 # Lesser General Public License for more details.
36 
37 ##
38 #
39 # Interface to /dev/input/eventX devices. This module provides base classes and
40 # constant values for accessing the Linux input interface. This includes
41 # keyboard, mouse, joystick, and a general event interface.
42 #
43 #
44 
45 import os, struct, time, fcntl
46 
47 from collections import deque
48 
49 INT = "i"
50 INT2 = "ii"
51 INT5 = "iiiii"
52 SHORT = "h"
53 USHORT = "H"
54 SHORT4 = "hhhh"
55 
56 SIZEOF_INT2 = struct.calcsize(INT2)
57 
58 # Initialize the ioctl constants
59 from ioctl import _IOC, _IO, _IOW, _IOR, _IOC_READ
60 # taken from /usr/include/linux/input.h
61 
62 EVIOCGVERSION = _IOR(69, 0x01, INT) # get driver version */
63 EVIOCGID = _IOR(69, 0x02, SHORT4) # get device ID */
64 EVIOCGREP = _IOR(69, 0x03, INT2) # get repeat settings */
65 EVIOCSREP = _IOW(69, 0x03, INT2) # set repeat settings */
66 EVIOCGKEYCODE = _IOR(69, 0x04, INT2) # get keycode */
67 EVIOCSKEYCODE = _IOW(69, 0x04, INT2) # set keycode */
68 EVIOCGKEY = _IOR(69, 0x05, INT2) # get key value */
69 EVIOCGNAME = _IOC(_IOC_READ, 69, 0x06, 255)# get device name */
70 EVIOCGPHYS = _IOC(_IOC_READ, 69, 0x07, 255)# get physical location */
71 EVIOCGUNIQ = _IOC(_IOC_READ, 69, 0x08, 255)# get unique identifier */
72 EVIOCRMFF = _IOW(69, 0x81, INT) # Erase a force effect */
73 EVIOCSGAIN = _IOW(69, 0x82, USHORT) # Set overall gain */
74 EVIOCSAUTOCENTER= _IOW(69, 0x83, USHORT) # Enable or disable auto-centering */
75 EVIOCGEFFECTS = _IOR(69, 0x84, INT) # Report number of effects playable at the same time */
76 EVIOCGRAB = _IOW(69, 0x90, INT) # Grab/Release device */
77 
78 
79 class Queue(deque):
80  def push(self, obj):
81  self.appendleft(obj)
82 
83 
84 # these take parameters.
85 def EVIOCGBIT(evtype, len=255):
86  return _IOC(_IOC_READ, 69, 0x20 + evtype, len) # get event bits */
87 
88 
89 def EVIOCGABS(abs):
90  return _IOR(69, 0x40 + abs, INT5) # get abs value/limits */
91 
92 
93 def EVIOCGSW(len):
94  return _IOC(_IOC_READ, 69, 0x1b, len) # get all switch states */
95 
96 
97 def EVIOCGLED(len):
98  return _IOC(_IOC_READ, 69, 0x19, len) # get all LEDs */
99 
100 #struct input_event {
101 # struct timeval time; = {long seconds, long microseconds}
102 # unsigned short type;
103 # unsigned short code;
104 # unsigned int value;
105 #};
106 
107 EVFMT = "llHHi"
108 EVsize = struct.calcsize(EVFMT)
109 
110 EV_SYN = 0x00
111 EV_KEY = 0x01
112 EV_REL = 0x02
113 EV_ABS = 0x03
114 EV_MSC = 0x04
115 EV_SW = 0x05
116 EV_LED = 0x11
117 EV_SND = 0x12
118 EV_REP = 0x14
119 EV_FF = 0x15
120 EV_PWR = 0x16
121 EV_FF_STATUS = 0x17
122 EV_MAX = 0x1f
123 
124 
125 ##
126 # Contains a set of base features. May be actual set as returned by a
127 # feature request, or a desired set to find.
128 #
129 class Features(object):
130  NAMES = {
131  EV_SYN: "Sync",
132  EV_KEY: "Keys or Buttons",
133  EV_REL: "Relative Axes",
134  EV_ABS: "Absolute Axes",
135  EV_MSC: "Miscellaneous",
136  EV_SW: "Switches",
137  EV_LED: "Leds",
138  EV_SND: "Sound",
139  EV_REP: "Repeat",
140  EV_FF: "Force Feedback",
141  EV_PWR: "Power Management",
142  EV_FF_STATUS: "Force Feedback Status",
143  }
144 
145  def __init__(self, bits=0):
146  self._bits = bits
147 
148  def has_keys(self):
149  return (self._bits >> EV_KEY) & 1
150 
151  def has_leds(self):
152  return (self._bits >> EV_LED) & 1
153 
154  def has_sound(self):
155  return (self._bits >> EV_SND) & 1
156 
157  def has_relative_axes(self):
158  return (self._bits >> EV_REL) & 1
159 
160  def has_absolute_axes(self):
161  return (self._bits >> EV_ABS) & 1
162 
163  def has_misc(self):
164  return (self._bits >> EV_MSC) & 1
165 
166  def has_switches(self):
167  return (self._bits >> EV_SW) & 1
168 
169  def has_repeat(self):
170  return (self._bits >> EV_REP) & 1
171 
172  def has_forcefeedback(self):
173  return (self._bits >> EV_FF) & 1
174 
176  return (self._bits >> EV_FF_STATUS) & 1
177 
178  def has_power(self):
179  return (self._bits >> EV_PWR) & 1
180 
181  def _make_set(self):
182  featureset = set()
183  bits = self._bits
184  for bit in (EV_KEY, EV_REL, EV_ABS, EV_MSC, EV_SW, EV_LED, EV_SND, EV_REP, EV_FF, EV_PWR, EV_FF_STATUS):
185  if (bits >> bit) & 1:
186  featureset.add(bit)
187  return featureset
188 
189  def match(self, other):
190  pass # XXX
191 
192  def __str__(self):
193  s = []
194  bits = self._bits
195  for bit, name in self.NAMES.items():
196  if (bits >> bit) & 1:
197  s.append(name)
198  return ", ".join(s)
199 
200 
201 ##
202 # This structure is the collection of data for the general event
203 # interface. You can create one to write to an event device. If you read from
204 # the event device using a subclass of the EventDevice object you will get one of these.
205 #
206 class Event(object):
207  def __init__(self, time=0.0, evtype=0, code=0, value=0):
208  self.time = time # timestamp of the event in Unix time.
209  self.evtype = evtype # even type (one of EV_* constants)
210  self.code = code # a code related to the event type
211  self.value = value # custom data - meaning depends on type above
212 
213  def __str__(self):
214  return "Event:\n time: %f\n evtype: 0x%x\n code: 0x%x\n value: 0x%x\n" % \
215  (self.time, self.evtype, self.code, self.value)
216 
217  def encode(self):
218  tv_sec, tv_usec = divmod(self.time, 1.0)
219  return struct.pack(EVFMT, long(tv_sec), long(tv_usec * 1000000.0), self.evtype, self.code, self.value)
220 
221  def decode(self, ev):
222  tv_sec, tv_usec, self.evtype, self.code, self.value = struct.unpack(EVFMT, ev)
223  self.time = float(tv_sec) + float(tv_usec) / 1000000.0
224 
225  def set(self, evtype, code, value):
226  self.time = time.time()
227  self.evtype = int(evtype)
228  self.code = int(code)
229  self.value = int(value)
230 
231 
232 ##
233 # Read from a file containing raw recorded events.
234 class EventFile(object):
235  def __init__(self, fname, mode="r"):
236  self._fo = open(fname, mode)
237  self._eventq = Queue()
238 
239  ##
240  # Read a single Event object from stream.
241  def read(self, amt=None): # amt not used, provided for compatibility.
242  if not self._eventq:
243  if not self._fill():
244  return None
245  return self._eventq.pop()
246 
247  def readall(self):
248  ev = self.read()
249  while ev:
250  yield ev
251  ev = self.read()
252 
253  def _fill(self):
254  raw = self._fo.read(EVsize * 32)
255  if raw:
256  for i in xrange(len(raw) / EVsize):
257  ev = Event()
258  ev.decode(raw[i * EVsize:(i + 1) * EVsize])
259  self._eventq.push(ev)
260  return True
261  else:
262  return False
263 
264 
265 # base class for event devices. Subclass this for your specific device.
266 class EventDevice(object):
267  DEVNAME = None # must match name string of device
268 
269  def __init__(self, fname=None):
270  self._fd = None
271  self.name = ""
272  self._eventq = Queue()
273  self.idbus = self.idvendor = self.idproduct = self.idversion = None
274  if fname:
275  self.open(fname)
276  self.initialize()
277 
278  def __str__(self):
279  if self.idbus is None:
280  self.get_deviceid()
281  return "%s: bus=0x%x, vendor=0x%x, product=0x%x, version=0x%x\n %s" % \
282  (self.name, self.idbus, self.idvendor, self.idproduct, self.idversion, self.get_features())
283 
284  def _fill(self):
285  global EVsize
286  try:
287  raw = os.read(self._fd, EVsize * 32)
288  except EOFError:
289  self.close()
290  else:
291  if raw:
292  for i in range(len(raw) / EVsize):
293  ev = Event()
294  ev.decode(raw[i * EVsize:(i + 1) * EVsize])
295  self._eventq.push(ev)
296 
297  def find(self, start=0, name=None):
298  name = name or self.DEVNAME
299  assert name is not None, "EventDevice: no name to find"
300  for d in range(start, 16):
301  filename = "/dev/input/event%d" % (d,)
302  if os.path.exists(filename):
303  try:
304  self.open(filename)
305  except (OSError, IOError): # probably no permissions
306  pass
307  else:
308  if name in self.name:
309  return
310  self.close()
311  raise IOError("Input device %r not found." % (name,))
312 
313  def open(self, filename):
314  self._fd = os.open(filename, os.O_RDWR)
315  name = fcntl.ioctl(self._fd, EVIOCGNAME, chr(0) * 256)
316  self.name = name.replace(chr(0), '')
317 
318  def fileno(self):
319  return self._fd
320 
321  def close(self):
322  if self._fd is not None:
323  os.close(self._fd)
324  self._fd = None
325  self.name = ""
326 
327  def read(self):
328  if not self._eventq:
329  self._fill()
330  return self._eventq.pop()
331 
332  def readall(self):
333  ev = self.read()
334  while ev:
335  yield ev
336  ev = self.read()
337 
338  def write(self, evtype, code, value):
339  ev = Event(0.0, evtype, code, value)
340  return os.write(self._fd, ev.encode())
341 
342  def get_driverversion(self):
343  ver = fcntl.ioctl(self._fd, EVIOCGVERSION, '\x00\x00\x00\x00')
344  return struct.unpack(INT, ver)[0]
345 
346  def get_deviceid(self):
347  ver = fcntl.ioctl(self._fd, EVIOCGID, '\x00\x00\x00\x00\x00\x00\x00\x00')
348  self.idbus, self.idvendor, self.idproduct, self.idversion = struct.unpack(SHORT4, ver)
349  return self.idbus, self.idvendor, self.idproduct, self.idversion
350 
351  def get_features(self):
352  caps = fcntl.ioctl(self._fd, EVIOCGBIT(0), '\x00\x00\x00\x00')
353  caps = struct.unpack(INT, caps)[0]
354  return Features(caps)
355 
356  def readable(self):
357  return bool(self._fd)
358 
359  def writable(self):
360  return False
361 
362  def priority(self):
363  return False
364 
365  def read_handler(self):
366  self._fill()
367 
368  def write_handler(self):
369  pass
370 
371  def pri_handler(self):
372  pass
373 
374  def hangup_handler(self):
375  pass
376 
377  def initialize(self):
378  pass
379 
380 
381 ##
382 # Returns a list of tuples containing (index, devicename).
383 #
384 def get_device_names(start=0):
385  names = []
386  for d in range(start, 16):
387  filename = "/dev/input/event%d" % (d,)
388  if os.path.exists(filename):
389  try:
390  fd = os.open(filename, os.O_RDWR)
391  try:
392  name = fcntl.ioctl(fd, EVIOCGNAME, chr(0) * 256)
393  finally:
394  os.close(fd)
395  name = name.replace(chr(0), '')
396  except (OSError, IOError): # probably no permissions
397  continue
398  else:
399  names.append((d, name))
400  return names
401 
402 
403 def get_devices(start=0):
404  devs = []
405  for d in range(start, 16):
406  filename = "/dev/input/event%d" % (d,)
407  if os.path.exists(filename):
408  devs.append(EventDevice(filename))
409  return devs
410