Package sparked :: Package hardware :: Module inputevent
[hide private]
[frames] | no frames]

Source Code for Module sparked.hardware.inputevent

  1  # Copyright (c) 2010 Arjan Scherpenisse 
  2  # See LICENSE for details. 
  3   
  4  """ 
  5  Classes dealing with /dev/input/* devices for twisted. 
  6   
  7  InputEvent class taken from http://github.com/rmt/pyinputevent/ 
  8  """ 
  9   
 10  import os 
 11  import struct 
 12  import time 
 13  import ctypes 
 14   
 15  from twisted.internet import abstract, fdesc, protocol 
 16   
 17  EV_SYN = 0x00 
 18  EV_KEY = 0x01 
 19  EV_REL = 0x02 
 20  EV_ABS = 0x03 
 21  EV_MSC = 0x04 
 22  EV_SW = 0x05 
 23  EV_LED = 0x11 
 24  EV_SND = 0x12 
 25  EV_REP = 0x14 
 26  EV_FF = 0x15 
 27  EV_PWR = 0x16 
 28  EV_FF_STATUS = 0x17 
 29   
 30   
 31  __all__ = ['InputEvent', 'InputEventDevice', 'InputEventProtocol'] 
 32   
 33  __voidptrsize = ctypes.sizeof(ctypes.c_voidp) 
 34  _64bit = (__voidptrsize == 8) 
 35  _32bit = (__voidptrsize == 4) 
 36  if _64bit: 
 37      INPUTEVENT_STRUCT = "=LLLLHHl" 
 38      INPUTEVENT_STRUCT_SIZE = 24 
 39  elif _32bit: # 32bit 
 40      INPUTEVENT_STRUCT = "=iiHHi" 
 41      INPUTEVENT_STRUCT_SIZE = 16 
 42  else: 
 43      raise RuntimeError("Couldn't determine architecture, modify " + __file__ + 
 44                         " to support your system.") 
45 46 47 -class InputEvent(object):
48 """ 49 A `struct input_event`. You can instantiate it with a buffer, in 50 which case the method `unpack(buf)` will be called. Or you can create 51 an instance with `InputEvent.new(type, code, value, timestamp=None)`, 52 which can then be packed into the structure with the `pack` method. 53 """ 54 55 __slots__ = ('etype', 'ecode', 'evalue', 'time', 'nanotime') 56
57 - def __init__(self, buf=None):
58 """By default, unpack from a buffer""" 59 if buf: 60 self.unpack(buf)
61
62 - def set(self, etype, ecode, evalue, timestamp=None):
63 """Set the parameters of this InputEvent""" 64 if timestamp is None: 65 timestamp = time.time() 66 self.time, self.nanotime = int(timestamp), int(timestamp%1*1000000.0) 67 self.etype = etype 68 self.ecode = ecode 69 self.evalue = evalue 70 return self
71 72 @classmethod
73 - def new(cls, etype, ecode, evalue, time=None):
74 """Construct a new InputEvent object""" 75 e = cls() 76 e.set(etype, ecode, evalue, time) 77 return e
78 79 @property
80 - def timestamp(self):
81 return self.time + (self.nanotime / 1000000.0)
82
83 - def unpack(self, buf):
84 if _64bit: 85 self.time, t1, self.nanotime, t3, \ 86 self.etype, self.ecode, self.evalue \ 87 = struct.unpack_from(INPUTEVENT_STRUCT, buf) 88 elif _32bit: 89 self.time, self.nanotime, self.etype, \ 90 self.ecode, self.evalue \ 91 = struct.unpack_from(INPUTEVENT_STRUCT, buf) 92 return self
93 - def pack(self):
94 if _64bit: 95 return struct.pack(INPUTEVENT_STRUCT, 96 self.time, 0, self.nanotime, 0, 97 self.etype, self.ecode, self.evalue) 98 elif _32bit: 99 return struct.pack(INPUTEVENT_STRUCT, 100 self.time, self.nanotime, 101 self.etype, self.ecode, self.evalue)
102 - def __repr__(self):
103 return "<InputEvent type=%r, code=%r, value=%r>" % \ 104 (self.etype, self.ecode, self.evalue)
105 - def __str__(self):
106 return "type=%r, code=%r, value=%r" % \ 107 (self.etype, self.ecode, self.evalue)
108 - def __hash__(self):
109 return hash( (self.etype, self.ecode, self.evalue,) )
110
111 - def __eq__(self, other):
112 return self.etype == other.etype \ 113 and self.ecode == other.ecode \ 114 and self.evalue == other.evalue
115
116 117 118 119 -class InputEventDevice(abstract.FileDescriptor):
120 """ 121 A select()able, read-only input device from /dev/input/* 122 """ 123 124 connected = 1 125
126 - def __init__(self, protocol, deviceName, reactor=None):
127 if reactor is None: 128 from twisted.internet import reactor 129 abstract.FileDescriptor.__init__(self, reactor) 130 self._fileno = os.open(deviceName, os.O_RDONLY | os.O_NONBLOCK) 131 self.reactor = reactor 132 self.protocol = protocol 133 self.protocol.makeConnection(self) 134 self.startReading()
135
136 - def fileno(self):
137 return self._fileno
138
139 - def writeSomeData(self, data):
140 """ 141 Write some data to the device. 142 """ 143 raise IOError("Input device is read-only!")
144
145 - def doRead(self):
146 """ 147 Some data's readable from serial device. 148 """ 149 return fdesc.readFromFD(self.fileno(), self.protocol.dataReceived)
150
151 - def connectionLost(self, reason):
152 abstract.FileDescriptor.connectionLost(self, reason) 153 os.close(self._fileno)
154
155 156 -class InputEventProtocol(protocol.Protocol):
157 """ 158 Receives events from an input device. 159 """ 160
161 - def connectionMade(self):
162 self.buf = ""
163
164 - def dataReceived(self, data):
165 self.buf += data 166 while len(self.buf) >= INPUTEVENT_STRUCT_SIZE: 167 self.eventReceived(InputEvent(self.buf[:INPUTEVENT_STRUCT_SIZE])) 168 self.buf = self.buf[INPUTEVENT_STRUCT_SIZE:]
169
170 - def eventReceived(self, event):
171 """ 172 Input event has been received. Override this function to do 173 something useful. 174 """ 175 print repr(event)
176