Enigma2: add possibility to configure input device delay and repeat settings.
[vuplus_dvbapp] / lib / python / Components / InputDevice.py
1 # coding: utf-8
2 from config import config, configfile, ConfigSlider, ConfigSubsection, ConfigYesNo, ConfigText
3
4 import struct, sys, time, errno
5 from fcntl import ioctl
6 from os import path as os_path, listdir, open as os_open, close as os_close, write as os_write, read as os_read, O_RDWR, O_NONBLOCK
7
8 # asm-generic/ioctl.h
9 IOC_NRBITS = 8L
10 IOC_TYPEBITS = 8L
11 IOC_SIZEBITS = 13L
12 IOC_DIRBITS = 3L
13
14 IOC_NRSHIFT = 0L
15 IOC_TYPESHIFT = IOC_NRSHIFT+IOC_NRBITS
16 IOC_SIZESHIFT = IOC_TYPESHIFT+IOC_TYPEBITS
17 IOC_DIRSHIFT = IOC_SIZESHIFT+IOC_SIZEBITS
18
19 IOC_READ = 2L
20
21 def EVIOCGNAME(length):
22         return (IOC_READ<<IOC_DIRSHIFT)|(length<<IOC_SIZESHIFT)|(0x45<<IOC_TYPESHIFT)|(0x06<<IOC_NRSHIFT)
23
24
25 class inputDevices:
26
27         def __init__(self):
28                 self.Devices = {}
29                 self.currentDevice = ""
30                 self.getInputDevices()
31         
32         def getInputDevices(self):
33                 devices = listdir("/dev/input/")
34
35                 for evdev in devices:
36                         try:
37                                 buffer = "\0"*512
38                                 self.fd = os_open("/dev/input/" + evdev, O_RDWR | O_NONBLOCK)
39                                 self.name = ioctl(self.fd, EVIOCGNAME(256), buffer)
40                                 self.name = self.name[:self.name.find("\0")]
41                                 os_close(self.fd)
42                         except (IOError,OSError), err:
43                                 print '[iInputDevices] getInputDevices  <ERROR: ioctl(EVIOCGNAME): ' + str(err) + ' >'
44                                 self.name = None
45                         
46                         if self.name:
47                                 if self.name == 'dreambox front panel':
48                                         continue
49                                 if self.name == "dreambox advanced remote control (native)" and config.misc.rcused.value != 0:
50                                         continue
51                                 if self.name == "dreambox remote control (native)" and config.misc.rcused.value == 0:
52                                         continue
53                                 self.Devices[evdev] = {'name': self.name, 'type': self.getInputDeviceType(self.name),'enabled': False, 'configuredName': None }
54         
55
56         def getInputDeviceType(self,name):
57                 if name.find("remote control") != -1:
58                         return "remote"
59                 elif name.find("keyboard") != -1:
60                         return "keyboard"
61                 elif name.find("mouse") != -1:
62                         return "mouse"
63                 else:
64                         print "Unknown device type:",name
65                         return None
66                         
67         def getDeviceName(self, x):
68                 if x in self.Devices.keys():
69                         return self.Devices[x].get("name", x)
70                 else:
71                         return "Unknown device name"
72
73         def getDeviceList(self):
74                 return sorted(self.Devices.iterkeys())
75
76         def getDefaultRCdeviceName(self):
77                 if config.misc.rcused.value == 0:
78                         for device in self.Devices.iterkeys():
79                                 if self.Devices[device]["name"] == "dreambox advanced remote control (native)":
80                                         return device
81                 else:
82                         for device in self.Devices.iterkeys():
83                                 if self.Devices[device]["name"] == "dreambox remote control (native)":
84                                         return device
85
86         def setDeviceAttribute(self, device, attribute, value):
87                 #print "[iInputDevices] setting for device", device, "attribute", attribute, " to value", value
88                 if self.Devices.has_key(device):
89                         self.Devices[device][attribute] = value
90                         
91         def getDeviceAttribute(self, device, attribute):
92                 if self.Devices.has_key(device):
93                         if self.Devices[device].has_key(attribute):
94                                 return self.Devices[device][attribute]
95                 return None
96                         
97         def setEnabled(self, device, value):
98                 oldval = self.getDeviceAttribute(device, 'enabled')
99                 #print "[iInputDevices] setEnabled for device %s to %s from %s" % (device,value,oldval)
100                 self.setDeviceAttribute(device, 'enabled', value)
101                 if oldval is True and value is False:
102                         self.setDefaults(device)
103
104         def setName(self, device, value):
105                 #print "[iInputDevices] setName for device %s to %s" % (device,value)
106                 self.setDeviceAttribute(device, 'configuredName', value)
107                 
108         #struct input_event {
109         #       struct timeval time;    -> ignored
110         #       __u16 type;             -> EV_REP (0x14)
111         #       __u16 code;             -> REP_DELAY (0x00) or REP_PERIOD (0x01)
112         #       __s32 value;            -> DEFAULTS: 700(REP_DELAY) or 100(REP_PERIOD)
113         #}; -> size = 16
114
115         def setDefaults(self, device):
116                 print "[iInputDevices] setDefaults for device %s" % (device)
117                 self.setDeviceAttribute(device, 'configuredName', None)
118                 event_repeat = struct.pack('iihhi', 0, 0, 0x14, 0x01, 100)
119                 event_delay = struct.pack('iihhi', 0, 0, 0x14, 0x00, 700)
120                 fd = os_open("/dev/input/" + device, O_RDWR)
121                 os_write(fd, event_repeat)
122                 os_write(fd, event_delay)
123                 os_close(fd)
124
125         def setRepeat(self, device, value): #REP_PERIOD
126                 if self.getDeviceAttribute(device, 'enabled') == True:
127                         print "[iInputDevices] setRepeat for device %s to %d ms" % (device,value)
128                         event = struct.pack('iihhi', 0, 0, 0x14, 0x01, int(value))
129                         fd = os_open("/dev/input/" + device, O_RDWR)
130                         os_write(fd, event)
131                         os_close(fd)
132
133         def setDelay(self, device, value): #REP_DELAY
134                 if self.getDeviceAttribute(device, 'enabled') == True:
135                         print "[iInputDevices] setDelay for device %s to %d ms" % (device,value)
136                         event = struct.pack('iihhi', 0, 0, 0x14, 0x00, int(value))
137                         fd = os_open("/dev/input/" + device, O_RDWR)
138                         os_write(fd, event)
139                         os_close(fd)
140
141
142 class InitInputDevices:
143         
144         def __init__(self):
145                 self.currentDevice = ""
146                 self.createConfig()
147         
148         def createConfig(self, *args):
149                 config.inputDevices = ConfigSubsection()
150                 for device in sorted(iInputDevices.Devices.iterkeys()):
151                         self.currentDevice = device
152                         #print "[InitInputDevices] -> creating config entry for device: %s -> %s  " % (self.currentDevice, iInputDevices.Devices[device]["name"])
153                         self.setupConfigEntries(self.currentDevice)
154                         self.currentDevice = ""
155
156         def inputDevicesEnabledChanged(self,configElement):
157                 if self.currentDevice != "" and iInputDevices.currentDevice == "":
158                         iInputDevices.setEnabled(self.currentDevice, configElement.value)
159                 elif iInputDevices.currentDevice != "":
160                         iInputDevices.setEnabled(iInputDevices.currentDevice, configElement.value)
161
162         def inputDevicesNameChanged(self,configElement):
163                 if self.currentDevice != "" and iInputDevices.currentDevice == "":
164                         iInputDevices.setName(self.currentDevice, configElement.value)
165                         if configElement.value != "":
166                                 devname = iInputDevices.getDeviceAttribute(self.currentDevice, 'name')
167                                 if devname != configElement.value:
168                                         cmd = "config.inputDevices." + self.currentDevice + ".enabled.value = False"
169                                         exec (cmd)
170                                         cmd = "config.inputDevices." + self.currentDevice + ".enabled.save()"
171                                         exec (cmd)
172                 elif iInputDevices.currentDevice != "":
173                         iInputDevices.setName(iInputDevices.currentDevice, configElement.value)
174
175         def inputDevicesRepeatChanged(self,configElement):
176                 if self.currentDevice != "" and iInputDevices.currentDevice == "":
177                         iInputDevices.setRepeat(self.currentDevice, configElement.value)
178                 elif iInputDevices.currentDevice != "":
179                         iInputDevices.setRepeat(iInputDevices.currentDevice, configElement.value)
180                 
181         def inputDevicesDelayChanged(self,configElement):
182                 if self.currentDevice != "" and iInputDevices.currentDevice == "":
183                         iInputDevices.setDelay(self.currentDevice, configElement.value)
184                 elif iInputDevices.currentDevice != "":
185                         iInputDevices.setDelay(iInputDevices.currentDevice, configElement.value)
186
187         def setupConfigEntries(self,device):
188                 cmd = "config.inputDevices." + device + " = ConfigSubsection()"
189                 exec (cmd)
190                 cmd = "config.inputDevices." + device + ".enabled = ConfigYesNo(default = False)"
191                 exec (cmd)
192                 cmd = "config.inputDevices." + device + ".enabled.addNotifier(self.inputDevicesEnabledChanged,config.inputDevices." + device + ".enabled)"
193                 exec (cmd)
194                 cmd = "config.inputDevices." + device + '.name = ConfigText(default="")'
195                 exec (cmd)
196                 cmd = "config.inputDevices." + device + ".name.addNotifier(self.inputDevicesNameChanged,config.inputDevices." + device + ".name)"
197                 exec (cmd)
198                 cmd = "config.inputDevices." + device + ".repeat = ConfigSlider(default=100, increment = 10, limits=(0, 500))"
199                 exec (cmd)
200                 cmd = "config.inputDevices." + device + ".repeat.addNotifier(self.inputDevicesRepeatChanged,config.inputDevices." + device + ".repeat)"
201                 exec (cmd)
202                 cmd = "config.inputDevices." + device + ".delay = ConfigSlider(default=700, increment = 100, limits=(0, 5000))"
203                 exec (cmd)
204                 cmd = "config.inputDevices." + device + ".delay.addNotifier(self.inputDevicesDelayChanged,config.inputDevices." + device + ".delay)"
205                 exec (cmd)
206
207
208 iInputDevices = inputDevices()