|
|
|
@ -1,6 +1,16 @@
|
|
|
|
|
# Fenrir TTY screen reader
|
|
|
|
|
# By Chrys, Storm Dragon, and contributers.
|
|
|
|
|
|
|
|
|
|
from fenrirscreenreader.core.inputDriver import inputDriver
|
|
|
|
|
from fenrirscreenreader.core import debug
|
|
|
|
|
from fenrirscreenreader.core import inputData
|
|
|
|
|
from fenrirscreenreader.core.eventData import fenrirEventType
|
|
|
|
|
import threading
|
|
|
|
|
from ctypes import c_bool
|
|
|
|
|
from multiprocessing.sharedctypes import Value
|
|
|
|
|
import multiprocessing
|
|
|
|
|
from select import select
|
|
|
|
|
import time
|
|
|
|
|
_evdevAvailable = False
|
|
|
|
|
_udevAvailable = False
|
|
|
|
|
_evdevAvailableError = ''
|
|
|
|
@ -19,17 +29,6 @@ try:
|
|
|
|
|
except Exception as e:
|
|
|
|
|
_udevAvailableError = str(e)
|
|
|
|
|
|
|
|
|
|
import time
|
|
|
|
|
from select import select
|
|
|
|
|
import multiprocessing
|
|
|
|
|
from multiprocessing.sharedctypes import Value
|
|
|
|
|
from ctypes import c_bool
|
|
|
|
|
import threading
|
|
|
|
|
|
|
|
|
|
from fenrirscreenreader.core.eventData import fenrirEventType
|
|
|
|
|
from fenrirscreenreader.core import inputData
|
|
|
|
|
from fenrirscreenreader.core import debug
|
|
|
|
|
from fenrirscreenreader.core.inputDriver import inputDriver
|
|
|
|
|
|
|
|
|
|
class driver(inputDriver):
|
|
|
|
|
def __init__(self):
|
|
|
|
@ -43,6 +42,7 @@ class driver(inputDriver):
|
|
|
|
|
self.watchDog = Value(c_bool, True)
|
|
|
|
|
self.UInputinject = UInput()
|
|
|
|
|
self._deviceLock = threading.Lock()
|
|
|
|
|
|
|
|
|
|
def initialize(self, environment):
|
|
|
|
|
self.env = environment
|
|
|
|
|
self.env['runtime']['inputManager'].setShortcutType('KEY')
|
|
|
|
@ -51,14 +51,18 @@ class driver(inputDriver):
|
|
|
|
|
global _evdevAvailableError
|
|
|
|
|
global _udevAvailableError
|
|
|
|
|
if not _udevAvailable:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver:' + _udevAvailableError, debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver:' + _udevAvailableError, debug.debugLevel.ERROR)
|
|
|
|
|
if not _evdevAvailable:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver:' + _evdevAvailableError, debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver:' + _evdevAvailableError, debug.debugLevel.ERROR)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if _udevAvailable:
|
|
|
|
|
self.env['runtime']['processManager'].addCustomEventThread(self.plugInputDeviceWatchdogUdev)
|
|
|
|
|
self.env['runtime']['processManager'].addCustomEventThread(self.inputWatchdog)
|
|
|
|
|
self.env['runtime']['processManager'].addCustomEventThread(
|
|
|
|
|
self.plugInputDeviceWatchdogUdev)
|
|
|
|
|
self.env['runtime']['processManager'].addCustomEventThread(
|
|
|
|
|
self.inputWatchdog)
|
|
|
|
|
self._initialized = True
|
|
|
|
|
|
|
|
|
|
def plugInputDeviceWatchdogUdev(self, active, eventQueue):
|
|
|
|
@ -71,25 +75,41 @@ class driver(inputDriver):
|
|
|
|
|
validDevices = []
|
|
|
|
|
device = monitor.poll(1)
|
|
|
|
|
while device:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('plugInputDeviceWatchdogUdev:' + str(device), debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'plugInputDeviceWatchdogUdev:' + str(device), debug.debugLevel.INFO)
|
|
|
|
|
try:
|
|
|
|
|
try:
|
|
|
|
|
# FIX: Check if attributes exist before accessing them
|
|
|
|
|
if hasattr(device, 'name') and device.name and device.name.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
|
|
|
|
|
if hasattr(
|
|
|
|
|
device,
|
|
|
|
|
'name') and device.name and device.name.upper() in [
|
|
|
|
|
'',
|
|
|
|
|
'SPEAKUP',
|
|
|
|
|
'FENRIR-UINPUT']:
|
|
|
|
|
ignorePlug = True
|
|
|
|
|
if hasattr(device, 'phys') and device.phys and device.phys.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
|
|
|
|
|
if hasattr(
|
|
|
|
|
device,
|
|
|
|
|
'phys') and device.phys and device.phys.upper() in [
|
|
|
|
|
'',
|
|
|
|
|
'SPEAKUP',
|
|
|
|
|
'FENRIR-UINPUT']:
|
|
|
|
|
ignorePlug = True
|
|
|
|
|
if hasattr(device, 'name') and device.name and 'BRLTTY' in device.name.upper():
|
|
|
|
|
if hasattr(
|
|
|
|
|
device,
|
|
|
|
|
'name') and device.name and 'BRLTTY' in device.name.upper():
|
|
|
|
|
ignorePlug = True
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut("plugInputDeviceWatchdogUdev CHECK NAME CRASH: " + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
"plugInputDeviceWatchdogUdev CHECK NAME CRASH: " + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
if not ignorePlug:
|
|
|
|
|
virtual = '/sys/devices/virtual/input/' in device.sys_path
|
|
|
|
|
if device.device_node:
|
|
|
|
|
validDevices.append({'device': device.device_node, 'virtual': virtual})
|
|
|
|
|
validDevices.append(
|
|
|
|
|
{'device': device.device_node, 'virtual': virtual})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut("plugInputDeviceWatchdogUdev APPEND CRASH: " + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
"plugInputDeviceWatchdogUdev APPEND CRASH: " + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
pollTimeout = 1
|
|
|
|
|
device = monitor.poll(pollTimeout)
|
|
|
|
@ -97,20 +117,22 @@ class driver(inputDriver):
|
|
|
|
|
device = None
|
|
|
|
|
ignorePlug = False
|
|
|
|
|
if validDevices:
|
|
|
|
|
eventQueue.put({"Type": fenrirEventType.PlugInputDevice, "Data": validDevices})
|
|
|
|
|
eventQueue.put(
|
|
|
|
|
{"Type": fenrirEventType.PlugInputDevice, "Data": validDevices})
|
|
|
|
|
return time.time()
|
|
|
|
|
|
|
|
|
|
def inputWatchdog(self, active, eventQueue):
|
|
|
|
|
try:
|
|
|
|
|
while active.value:
|
|
|
|
|
# Get a snapshot of devices for select() to avoid lock contention
|
|
|
|
|
# Get a snapshot of devices for select() to avoid lock
|
|
|
|
|
# contention
|
|
|
|
|
with self._deviceLock:
|
|
|
|
|
devices_snapshot = self.iDevices.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not devices_snapshot:
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r, w, x = select(devices_snapshot, [], [], 0.8)
|
|
|
|
|
event = None
|
|
|
|
|
foundKeyInSequence = False
|
|
|
|
@ -123,16 +145,20 @@ class driver(inputDriver):
|
|
|
|
|
continue
|
|
|
|
|
device = self.iDevices[fd]
|
|
|
|
|
udevice = self.uDevices.get(fd)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
event = device.read_one()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver handleInputEvent: Error reading event: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver handleInputEvent: Error reading event: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
self.removeDevice(fd)
|
|
|
|
|
continue
|
|
|
|
|
while(event):
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('inputWatchdog: EVENT:' + str(event), debug.debugLevel.INFO)
|
|
|
|
|
self.env['input']['eventBuffer'].append([device, udevice, event])
|
|
|
|
|
while (event):
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'inputWatchdog: EVENT:' + str(event), debug.debugLevel.INFO)
|
|
|
|
|
self.env['input']['eventBuffer'].append(
|
|
|
|
|
[device, udevice, event])
|
|
|
|
|
if event.type == evdev.events.EV_KEY:
|
|
|
|
|
if not foundKeyInSequence:
|
|
|
|
|
foundKeyInSequence = True
|
|
|
|
@ -141,11 +167,13 @@ class driver(inputDriver):
|
|
|
|
|
if not currMapEvent:
|
|
|
|
|
event = device.read_one()
|
|
|
|
|
continue
|
|
|
|
|
if not isinstance(currMapEvent['EventName'], str):
|
|
|
|
|
if not isinstance(
|
|
|
|
|
currMapEvent['EventName'], str):
|
|
|
|
|
event = device.read_one()
|
|
|
|
|
continue
|
|
|
|
|
if currMapEvent['EventState'] in [0, 1, 2]:
|
|
|
|
|
eventQueue.put({"Type": fenrirEventType.KeyboardInput, "Data": currMapEvent.copy()})
|
|
|
|
|
eventQueue.put(
|
|
|
|
|
{"Type": fenrirEventType.KeyboardInput, "Data": currMapEvent.copy()})
|
|
|
|
|
eventFired = True
|
|
|
|
|
else:
|
|
|
|
|
if event.type in [2, 3]:
|
|
|
|
@ -155,20 +183,23 @@ class driver(inputDriver):
|
|
|
|
|
if not foundKeyInSequence:
|
|
|
|
|
if foreward and not eventFired:
|
|
|
|
|
self.writeEventBuffer()
|
|
|
|
|
self.clearEventBuffer()
|
|
|
|
|
self.clearEventBuffer()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut("INPUT WATCHDOG CRASH: " + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
"INPUT WATCHDOG CRASH: " + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
def writeEventBuffer(self):
|
|
|
|
|
if not self._initialized:
|
|
|
|
|
return
|
|
|
|
|
return
|
|
|
|
|
for iDevice, uDevice, event in self.env['input']['eventBuffer']:
|
|
|
|
|
try:
|
|
|
|
|
if uDevice:
|
|
|
|
|
if self.gDevices[iDevice.fd]:
|
|
|
|
|
self.writeUInput(uDevice, event)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver writeEventBuffer: Error writing event: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver writeEventBuffer: Error writing event: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
def writeUInput(self, uDevice, event):
|
|
|
|
|
if not self._initialized:
|
|
|
|
@ -190,12 +221,13 @@ class driver(inputDriver):
|
|
|
|
|
else:
|
|
|
|
|
deviceFileList = evdev.list_devices()
|
|
|
|
|
if len(deviceFileList) == self.iDeviceNo:
|
|
|
|
|
return
|
|
|
|
|
return
|
|
|
|
|
if not deviceFileList:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
mode = self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper()
|
|
|
|
|
|
|
|
|
|
mode = self.env['runtime']['settingsManager'].getSetting(
|
|
|
|
|
'keyboard', 'device').upper()
|
|
|
|
|
|
|
|
|
|
iDevicesFiles = []
|
|
|
|
|
for device in self.iDevices:
|
|
|
|
|
iDevicesFiles.append(self.iDevices[device].fn)
|
|
|
|
@ -213,7 +245,9 @@ class driver(inputDriver):
|
|
|
|
|
with open(deviceFile) as f:
|
|
|
|
|
pass
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver updateInputDevices: Error opening device file: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver updateInputDevices: Error opening device file: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
continue
|
|
|
|
|
# 3 pos absolute
|
|
|
|
|
# 2 pos relative
|
|
|
|
@ -221,61 +255,100 @@ class driver(inputDriver):
|
|
|
|
|
try:
|
|
|
|
|
currDevice = evdev.InputDevice(deviceFile)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver createDeviceType: Error creating device: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver createDeviceType: Error creating device: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
continue
|
|
|
|
|
try:
|
|
|
|
|
# FIX: Check if attributes exist before accessing them
|
|
|
|
|
if hasattr(currDevice, 'name') and currDevice.name and currDevice.name.upper() in ['', 'SPEAKUP', 'FENRIR-UINPUT']:
|
|
|
|
|
if hasattr(
|
|
|
|
|
currDevice,
|
|
|
|
|
'name') and currDevice.name and currDevice.name.upper() in [
|
|
|
|
|
'',
|
|
|
|
|
'SPEAKUP',
|
|
|
|
|
'FENRIR-UINPUT']:
|
|
|
|
|
continue
|
|
|
|
|
if hasattr(currDevice, 'phys') and currDevice.phys and currDevice.phys.upper() in ['', 'SPEAKUP', 'FENRIR-UINPUT']:
|
|
|
|
|
if hasattr(
|
|
|
|
|
currDevice,
|
|
|
|
|
'phys') and currDevice.phys and currDevice.phys.upper() in [
|
|
|
|
|
'',
|
|
|
|
|
'SPEAKUP',
|
|
|
|
|
'FENRIR-UINPUT']:
|
|
|
|
|
continue
|
|
|
|
|
if hasattr(currDevice, 'name') and currDevice.name and 'BRLTTY' in currDevice.name.upper():
|
|
|
|
|
if hasattr(
|
|
|
|
|
currDevice,
|
|
|
|
|
'name') and currDevice.name and 'BRLTTY' in currDevice.name.upper():
|
|
|
|
|
continue
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver: Error checking device capabilities: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver: Error checking device capabilities: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
cap = currDevice.capabilities()
|
|
|
|
|
if mode in ['ALL', 'NOMICE']:
|
|
|
|
|
if eventType.EV_KEY in cap:
|
|
|
|
|
if 116 in cap[eventType.EV_KEY] and len(cap[eventType.EV_KEY]) < 10:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Device Skipped (has 116):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
if 116 in cap[eventType.EV_KEY] and len(
|
|
|
|
|
cap[eventType.EV_KEY]) < 10:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Device Skipped (has 116):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
continue
|
|
|
|
|
if len(cap[eventType.EV_KEY]) < 60:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Device Skipped (< 60 keys):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Device Skipped (< 60 keys):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
continue
|
|
|
|
|
if mode == 'ALL':
|
|
|
|
|
self.addDevice(currDevice)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Device added (ALL):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Device added (ALL):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO)
|
|
|
|
|
elif mode == 'NOMICE':
|
|
|
|
|
if not ((eventType.EV_REL in cap) or (eventType.EV_ABS in cap)):
|
|
|
|
|
if not (
|
|
|
|
|
(eventType.EV_REL in cap) or (
|
|
|
|
|
eventType.EV_ABS in cap)):
|
|
|
|
|
self.addDevice(currDevice)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Device added (NOMICE):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Device added (NOMICE):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO)
|
|
|
|
|
else:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Device Skipped (NOMICE):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Device Skipped (NOMICE):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
else:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Device Skipped (no EV_KEY):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Device Skipped (no EV_KEY):' + currDevice.name, debug.debugLevel.INFO)
|
|
|
|
|
elif currDevice.name.upper() in mode.split(','):
|
|
|
|
|
self.addDevice(currDevice)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Device added (Name):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Device added (Name):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
try:
|
|
|
|
|
device_name = currDevice.name if hasattr(currDevice, 'name') else "unknown"
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile + ' ' + device_name + ' ' + str(e), debug.debugLevel.INFO)
|
|
|
|
|
device_name = currDevice.name if hasattr(
|
|
|
|
|
currDevice, 'name') else "unknown"
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
"Device Skipped (Exception): " +
|
|
|
|
|
deviceFile +
|
|
|
|
|
' ' +
|
|
|
|
|
device_name +
|
|
|
|
|
' ' +
|
|
|
|
|
str(e),
|
|
|
|
|
debug.debugLevel.INFO)
|
|
|
|
|
except Exception as ex:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile + ' ' + str(ex), debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
"Device Skipped (Exception): " + deviceFile + ' ' + str(ex),
|
|
|
|
|
debug.debugLevel.INFO)
|
|
|
|
|
self.iDeviceNo = len(evdev.list_devices())
|
|
|
|
|
self.updateMPiDevicesFD()
|
|
|
|
|
|
|
|
|
|
def updateMPiDevicesFD(self):
|
|
|
|
|
try:
|
|
|
|
|
for fd in self.iDevices:
|
|
|
|
|
if not fd in self.iDevicesFD:
|
|
|
|
|
if fd not in self.iDevicesFD:
|
|
|
|
|
self.iDevicesFD.append(fd)
|
|
|
|
|
for fd in self.iDevicesFD:
|
|
|
|
|
if not fd in self.iDevices:
|
|
|
|
|
if fd not in self.iDevices:
|
|
|
|
|
self.iDevicesFD.remove(fd)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver updateMPiDevicesFD: Error updating device file descriptors: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver updateMPiDevicesFD: Error updating device file descriptors: ' +
|
|
|
|
|
str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
def mapEvent(self, event):
|
|
|
|
|
if not self._initialized:
|
|
|
|
|
return None
|
|
|
|
@ -310,7 +383,7 @@ class driver(inputDriver):
|
|
|
|
|
if led in dev.leds():
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def toggleLedState(self, led=0):
|
|
|
|
|
if not self.hasIDevices():
|
|
|
|
|
return False
|
|
|
|
@ -323,7 +396,7 @@ class driver(inputDriver):
|
|
|
|
|
self.iDevices[i].set_led(led, 0)
|
|
|
|
|
else:
|
|
|
|
|
self.iDevices[i].set_led(led, 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def grabAllDevices(self):
|
|
|
|
|
if not self._initialized:
|
|
|
|
|
return True
|
|
|
|
@ -332,7 +405,7 @@ class driver(inputDriver):
|
|
|
|
|
if not self.gDevices[fd]:
|
|
|
|
|
ok = ok and self.grabDevice(fd)
|
|
|
|
|
return ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ungrabAllDevices(self):
|
|
|
|
|
if not self._initialized:
|
|
|
|
|
return True
|
|
|
|
@ -341,9 +414,10 @@ class driver(inputDriver):
|
|
|
|
|
if self.gDevices[fd]:
|
|
|
|
|
ok = ok and self.ungrabDevice(fd)
|
|
|
|
|
return ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def createUInputDev(self, fd):
|
|
|
|
|
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
|
|
|
|
if not self.env['runtime']['settingsManager'].getSettingAsBool(
|
|
|
|
|
'keyboard', 'grabDevices'):
|
|
|
|
|
self.uDevices[fd] = None
|
|
|
|
|
return
|
|
|
|
|
try:
|
|
|
|
@ -351,132 +425,182 @@ class driver(inputDriver):
|
|
|
|
|
return
|
|
|
|
|
except KeyError:
|
|
|
|
|
self.uDevices[fd] = None
|
|
|
|
|
if self.uDevices[fd] != None:
|
|
|
|
|
if self.uDevices[fd] is not None:
|
|
|
|
|
return
|
|
|
|
|
try:
|
|
|
|
|
self.uDevices[fd] = UInput.from_device(self.iDevices[fd], name='fenrir-uinput', phys='fenrir-uinput')
|
|
|
|
|
self.uDevices[fd] = UInput.from_device(
|
|
|
|
|
self.iDevices[fd], name='fenrir-uinput', phys='fenrir-uinput')
|
|
|
|
|
except Exception as e:
|
|
|
|
|
try:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: compat fallback: ' + str(e), debug.debugLevel.WARNING)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: compat fallback: ' + str(e), debug.debugLevel.WARNING)
|
|
|
|
|
dev = self.iDevices[fd]
|
|
|
|
|
cap = dev.capabilities()
|
|
|
|
|
del cap[0]
|
|
|
|
|
self.uDevices[fd] = UInput(
|
|
|
|
|
cap,
|
|
|
|
|
name='fenrir-uinput',
|
|
|
|
|
phys='fenrir-uinput'
|
|
|
|
|
cap,
|
|
|
|
|
name='fenrir-uinput',
|
|
|
|
|
phys='fenrir-uinput'
|
|
|
|
|
)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: init Uinput not possible: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: init Uinput not possible: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def addDevice(self, newDevice):
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device added: ' + str(newDevice.fd) + ' ' + str(newDevice), debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: device added: ' + str(
|
|
|
|
|
newDevice.fd) + ' ' + str(newDevice),
|
|
|
|
|
debug.debugLevel.INFO)
|
|
|
|
|
with self._deviceLock:
|
|
|
|
|
try:
|
|
|
|
|
self.iDevices[newDevice.fd] = newDevice
|
|
|
|
|
self.iDevices[newDevice.fd] = newDevice
|
|
|
|
|
self.createUInputDev(newDevice.fd)
|
|
|
|
|
self.gDevices[newDevice.fd] = False
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: error adding device: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: error adding device: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
# if it doesnt work clean up
|
|
|
|
|
try:
|
|
|
|
|
del(self.iDevices[newDevice.fd])
|
|
|
|
|
del (self.iDevices[newDevice.fd])
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error removing iDevice: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error removing iDevice: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
del(self.uDevices[newDevice.fd])
|
|
|
|
|
del (self.uDevices[newDevice.fd])
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error removing uDevice: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error removing uDevice: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
del(self.gDevices[newDevice.fd])
|
|
|
|
|
del (self.gDevices[newDevice.fd])
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver addDevice: Error cleaning up gDevice: ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver addDevice: Error cleaning up gDevice: ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
def grabDevice(self, fd):
|
|
|
|
|
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
|
|
|
|
if not self.env['runtime']['settingsManager'].getSettingAsBool(
|
|
|
|
|
'keyboard', 'grabDevices'):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# FIX: Handle exception variable scope correctly
|
|
|
|
|
grab_error = None
|
|
|
|
|
try:
|
|
|
|
|
self.iDevices[fd].grab()
|
|
|
|
|
self.gDevices[fd] = True
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grab device (' + str(self.iDevices[fd].name) + ')', debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: grab device (' + str(self.iDevices[fd].name) + ')', debug.debugLevel.INFO)
|
|
|
|
|
# Reset modifier keys on successful grab
|
|
|
|
|
if self.uDevices[fd]:
|
|
|
|
|
modifierKeys = [e.KEY_LEFTCTRL, e.KEY_RIGHTCTRL, e.KEY_LEFTALT, e.KEY_RIGHTALT, e.KEY_LEFTSHIFT, e.KEY_RIGHTSHIFT]
|
|
|
|
|
modifierKeys = [
|
|
|
|
|
e.KEY_LEFTCTRL,
|
|
|
|
|
e.KEY_RIGHTCTRL,
|
|
|
|
|
e.KEY_LEFTALT,
|
|
|
|
|
e.KEY_RIGHTALT,
|
|
|
|
|
e.KEY_LEFTSHIFT,
|
|
|
|
|
e.KEY_RIGHTSHIFT]
|
|
|
|
|
for key in modifierKeys:
|
|
|
|
|
try:
|
|
|
|
|
self.uDevices[fd].write(e.EV_KEY, key, 0) # 0 = key up
|
|
|
|
|
self.uDevices[fd].syn()
|
|
|
|
|
except Exception as mod_error:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('Failed to reset modifier key: ' + str(mod_error), debug.debugLevel.WARNING)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'Failed to reset modifier key: ' + str(mod_error), debug.debugLevel.WARNING)
|
|
|
|
|
except IOError:
|
|
|
|
|
if not self.gDevices[fd]:
|
|
|
|
|
return False
|
|
|
|
|
except Exception as ex:
|
|
|
|
|
grab_error = ex
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if grab_error:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(grab_error), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: grabing not possible: ' +
|
|
|
|
|
str(grab_error),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def ungrabDevice(self, fd):
|
|
|
|
|
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
|
|
|
|
if not self.env['runtime']['settingsManager'].getSettingAsBool(
|
|
|
|
|
'keyboard', 'grabDevices'):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# FIX: Handle exception variable scope correctly
|
|
|
|
|
ungrab_error = None
|
|
|
|
|
try:
|
|
|
|
|
self.iDevices[fd].ungrab()
|
|
|
|
|
self.gDevices[fd] = False
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: ungrab device (' + str(self.iDevices[fd].name) + ')', debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: ungrab device (' + str(self.iDevices[fd].name) + ')', debug.debugLevel.INFO)
|
|
|
|
|
except IOError:
|
|
|
|
|
if self.gDevices[fd]:
|
|
|
|
|
return False
|
|
|
|
|
except Exception as ex:
|
|
|
|
|
ungrab_error = ex
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ungrab_error:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: ungrabing not possible: ' + str(ungrab_error), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: ungrabing not possible: ' +
|
|
|
|
|
str(ungrab_error),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def removeDevice(self, fd):
|
|
|
|
|
with self._deviceLock:
|
|
|
|
|
try:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device removed: ' + str(fd) + ' ' + str(self.iDevices[fd]), debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: device removed: ' + str(fd) + ' ' + str(
|
|
|
|
|
self.iDevices[fd]), debug.debugLevel.INFO)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device removed: ' + str(fd) + ' Error: ' + str(e), debug.debugLevel.INFO)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'InputDriver evdev: device removed: ' +
|
|
|
|
|
str(fd) +
|
|
|
|
|
' Error: ' +
|
|
|
|
|
str(e),
|
|
|
|
|
debug.debugLevel.INFO)
|
|
|
|
|
self.clearEventBuffer()
|
|
|
|
|
try:
|
|
|
|
|
self.ungrabDevice(fd)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error ungrabbing device ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error ungrabbing device ' + str(fd) + ': ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
self.iDevices[fd].close()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error closing iDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error closing iDevice ' + str(fd) + ': ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
self.uDevices[fd].close()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error closing uDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error closing uDevice ' + str(fd) + ': ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
del(self.iDevices[fd])
|
|
|
|
|
del (self.iDevices[fd])
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error deleting iDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error deleting iDevice ' + str(fd) + ': ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
del(self.uDevices[fd])
|
|
|
|
|
del (self.uDevices[fd])
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error deleting uDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error deleting uDevice ' + str(fd) + ': ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
try:
|
|
|
|
|
del(self.gDevices[fd])
|
|
|
|
|
del (self.gDevices[fd])
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error deleting gDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver removeDevice: Error deleting gDevice ' + str(fd) + ': ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
self.updateMPiDevicesFD()
|
|
|
|
|
|
|
|
|
|
def hasIDevices(self):
|
|
|
|
@ -495,7 +619,9 @@ class driver(inputDriver):
|
|
|
|
|
self.UInputinject.write(e.EV_KEY, e.ecodes[key], state)
|
|
|
|
|
self.UInputinject.syn()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut('evdevDriver sendKey: Error sending key ' + str(key) + ': ' + str(e), debug.debugLevel.ERROR)
|
|
|
|
|
self.env['runtime']['debug'].writeDebugOut(
|
|
|
|
|
'evdevDriver sendKey: Error sending key ' + str(key) + ': ' + str(e),
|
|
|
|
|
debug.debugLevel.ERROR)
|
|
|
|
|
|
|
|
|
|
def removeAllDevices(self):
|
|
|
|
|
if not self.hasIDevices():
|
|
|
|
|