mirror of
https://github.com/moparisthebest/uinput-mapper
synced 2024-11-21 16:05:00 -05:00
Document most code.
This commit is contained in:
parent
72dde4af77
commit
7c7abc7e59
38
cinput.py
38
cinput.py
@ -29,6 +29,9 @@ _ll = _nbits(KEY_MAX)
|
|||||||
test_bit = lambda j, v: (v[j / _bpl] >> (j % _bpl)) & 1
|
test_bit = lambda j, v: (v[j / _bpl] >> (j % _bpl)) & 1
|
||||||
|
|
||||||
def get_keys(f, ev):
|
def get_keys(f, ev):
|
||||||
|
"""
|
||||||
|
Get keys of type *f* from a specific input device *f*.
|
||||||
|
"""
|
||||||
buf = array.array('L', [0L] * _ll)
|
buf = array.array('L', [0L] * _ll)
|
||||||
try:
|
try:
|
||||||
fcntl.ioctl(f, EVIOCGBIT(ev, KEY_MAX), buf)
|
fcntl.ioctl(f, EVIOCGBIT(ev, KEY_MAX), buf)
|
||||||
@ -58,19 +61,28 @@ def copy_event(estr):
|
|||||||
return input_event(ev.time, ev.type, ev.code, ev.value)
|
return input_event(ev.time, ev.type, ev.code, ev.value)
|
||||||
|
|
||||||
class InputDevice(object):
|
class InputDevice(object):
|
||||||
|
"""
|
||||||
|
Class for reading input devices in /dev/input/
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self._f = os.open(path, os.O_RDONLY)
|
self._f = os.open(path, os.O_RDONLY)
|
||||||
|
|
||||||
def get_version(self):
|
def get_version(self):
|
||||||
|
"""
|
||||||
|
Returns the version of the input device.
|
||||||
|
"""
|
||||||
return get_input_version(self._f)
|
return get_input_version(self._f)
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Returns the name of the input device.
|
||||||
|
"""
|
||||||
return get_input_name(self._f)
|
return get_input_name(self._f)
|
||||||
|
|
||||||
# TODO: Maybe do not export keys?
|
|
||||||
def get_exposed_events(self):
|
def get_exposed_events(self):
|
||||||
"""
|
"""
|
||||||
|
Returns all the keys exposed by this input device.
|
||||||
"""
|
"""
|
||||||
d = dict()
|
d = dict()
|
||||||
for k, v in events.iteritems():
|
for k, v in events.iteritems():
|
||||||
@ -86,10 +98,16 @@ class InputDevice(object):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
def next_event(self):
|
def next_event(self):
|
||||||
|
"""
|
||||||
|
Read the next event from the input device
|
||||||
|
"""
|
||||||
estr = os.read(self._f, ctypes.sizeof(input_event))
|
estr = os.read(self._f, ctypes.sizeof(input_event))
|
||||||
return copy_event(estr)
|
return copy_event(estr)
|
||||||
|
|
||||||
def get_fd(self):
|
def get_fd(self):
|
||||||
|
"""
|
||||||
|
Returns the underlying fd.
|
||||||
|
"""
|
||||||
return self._f
|
return self._f
|
||||||
|
|
||||||
|
|
||||||
@ -97,9 +115,6 @@ class InputDevice(object):
|
|||||||
if hasattr(self, '_f'):
|
if hasattr(self, '_f'):
|
||||||
os.close(self._f)
|
os.close(self._f)
|
||||||
|
|
||||||
class InputDeviceStream(object):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def open_uinput():
|
def open_uinput():
|
||||||
try:
|
try:
|
||||||
@ -144,6 +159,11 @@ def free_uinput_device(f):
|
|||||||
|
|
||||||
class UInputDevice(object):
|
class UInputDevice(object):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Class to create input devices using /dev/(input/)?uinput
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._f = open_uinput()
|
self._f = open_uinput()
|
||||||
if not self._f:
|
if not self._f:
|
||||||
@ -151,17 +171,27 @@ class UInputDevice(object):
|
|||||||
raise OSError
|
raise OSError
|
||||||
|
|
||||||
def setup(self, name):
|
def setup(self, name):
|
||||||
|
"""
|
||||||
|
Writes initial data and transforms the fd into the input device
|
||||||
|
"""
|
||||||
write_uinput_device_info(self._f, name)
|
write_uinput_device_info(self._f, name)
|
||||||
|
|
||||||
def expose_event_type(self, evt):
|
def expose_event_type(self, evt):
|
||||||
|
"""
|
||||||
|
Exposes a specific event type.
|
||||||
|
"""
|
||||||
fcntl.ioctl(self._f, UI_SET_EVBIT, evt)
|
fcntl.ioctl(self._f, UI_SET_EVBIT, evt)
|
||||||
|
|
||||||
def expose_event(self, evt, evk):
|
def expose_event(self, evt, evk):
|
||||||
|
"""
|
||||||
|
Exposes an event; make sure the event type is exposed as well.
|
||||||
|
"""
|
||||||
evbit = evbits[evt]
|
evbit = evbits[evt]
|
||||||
fcntl.ioctl(self._f, evbit, evk)
|
fcntl.ioctl(self._f, evbit, evk)
|
||||||
|
|
||||||
def fire_event(self, ev):
|
def fire_event(self, ev):
|
||||||
"""
|
"""
|
||||||
|
Fire a new input event.
|
||||||
"""
|
"""
|
||||||
os.write(self._f, buffer(ev)[:])
|
os.write(self._f, buffer(ev)[:])
|
||||||
|
|
||||||
|
16
input-create
16
input-create
@ -20,31 +20,34 @@ parser = optparse.OptionParser(description='Create input devices.',
|
|||||||
)
|
)
|
||||||
parser.add_option('-C', '--compat', action='store_true',
|
parser.add_option('-C', '--compat', action='store_true',
|
||||||
help='Enable compatibility mode; for Python < 2.7')
|
help='Enable compatibility mode; for Python < 2.7')
|
||||||
|
parser.add_option('-v', '--verbose', action='store_true',
|
||||||
|
help='Enable verbose mode')
|
||||||
|
|
||||||
args, cfg = parser.parse_args()
|
args, cfg = parser.parse_args()
|
||||||
|
|
||||||
# Unpickle from stdin ; currently this is the default and only way
|
# Unpickle from stdin ; currently this is the default and only way
|
||||||
in_f = pickle.Unpickler(sys.stdin)
|
in_f = pickle.Unpickler(sys.stdin)
|
||||||
|
|
||||||
|
# Read input device count
|
||||||
nifd = in_f.load()
|
nifd = in_f.load()
|
||||||
|
|
||||||
print 'Got', nifd, 'inputs'
|
# Read configuration
|
||||||
|
|
||||||
conf = in_f.load()
|
conf = in_f.load()
|
||||||
|
|
||||||
|
# Allow configurations to change our current configuration
|
||||||
for path in cfg:
|
for path in cfg:
|
||||||
config_merge = imp.load_source('', path).config_merge
|
config_merge = imp.load_source('', path).config_merge
|
||||||
config_merge(conf)
|
config_merge(conf)
|
||||||
|
|
||||||
pretty_conf_print(conf)
|
if args.verbose:
|
||||||
|
pretty_conf_print(conf)
|
||||||
|
|
||||||
m = KeyMapper(conf)
|
m = KeyMapper(conf)
|
||||||
|
|
||||||
# TODO: Get amount of uinput devices to export
|
# Get number of output devices (determined from conf)
|
||||||
|
|
||||||
nofd = get_exported_device_count(conf)
|
nofd = get_exported_device_count(conf)
|
||||||
|
|
||||||
|
# Create and expose uinput devices
|
||||||
ofs = []
|
ofs = []
|
||||||
for f in xrange(nofd):
|
for f in xrange(nofd):
|
||||||
d = UInputDevice()
|
d = UInputDevice()
|
||||||
@ -52,6 +55,7 @@ for f in xrange(nofd):
|
|||||||
d.setup('Example input device')
|
d.setup('Example input device')
|
||||||
ofs.append(d)
|
ofs.append(d)
|
||||||
|
|
||||||
|
# Map events
|
||||||
while True:
|
while True:
|
||||||
if not args.compat:
|
if not args.compat:
|
||||||
fd, ev = in_f.load()
|
fd, ev = in_f.load()
|
||||||
|
19
input-read
19
input-read
@ -24,23 +24,27 @@ parser.add_option('-C', '--compat', action='store_true',
|
|||||||
|
|
||||||
args, input_file = parser.parse_args()
|
args, input_file = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
if len(input_file) == 0:
|
if len(input_file) == 0:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
# Open input devices
|
||||||
fs = map(InputDevice, input_file)
|
fs = map(InputDevice, input_file)
|
||||||
|
|
||||||
|
# Create configuration
|
||||||
config = {}
|
config = {}
|
||||||
for idx, f in enumerate(fs):
|
for idx, f in enumerate(fs):
|
||||||
c = parse_conf(f, idx)
|
c = parse_conf(f, idx)
|
||||||
|
|
||||||
config.update(c)
|
config.update(c)
|
||||||
|
|
||||||
|
# Add all devices to epoll
|
||||||
pp = select.epoll()
|
pp = select.epoll()
|
||||||
for f in fs:
|
for f in fs:
|
||||||
pp.register(f.get_fd(), select.EPOLLIN)
|
pp.register(f.get_fd(), select.EPOLLIN)
|
||||||
|
|
||||||
|
|
||||||
|
# Human readable info
|
||||||
if args.dump:
|
if args.dump:
|
||||||
for f in fs:
|
for f in fs:
|
||||||
print 'Version:', f.get_version()
|
print 'Version:', f.get_version()
|
||||||
@ -51,6 +55,7 @@ if args.dump:
|
|||||||
print k + ':', ', '.join(v)
|
print k + ':', ', '.join(v)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
# Dump initial information over pickle to stdout
|
||||||
p = pickle.Pickler(sys.stdout)
|
p = pickle.Pickler(sys.stdout)
|
||||||
|
|
||||||
p.dump(len(fs))
|
p.dump(len(fs))
|
||||||
@ -59,7 +64,6 @@ else:
|
|||||||
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
i = 0
|
|
||||||
while True:
|
while True:
|
||||||
events = pp.poll()
|
events = pp.poll()
|
||||||
|
|
||||||
@ -69,7 +73,7 @@ while True:
|
|||||||
if not ev_mask & select.EPOLLIN:
|
if not ev_mask & select.EPOLLIN:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Lets undo that epoll speedup ;-)
|
# Lets undo that epoll speedup ;-) FIXME XXX
|
||||||
for idx, _ in enumerate(fs):
|
for idx, _ in enumerate(fs):
|
||||||
if _.get_fd() == fd:
|
if _.get_fd() == fd:
|
||||||
f = _
|
f = _
|
||||||
@ -80,7 +84,8 @@ while True:
|
|||||||
if args.dump:
|
if args.dump:
|
||||||
try:
|
try:
|
||||||
print i, ev.time.tv_sec, ev.time.tv_usec
|
print i, ev.time.tv_sec, ev.time.tv_usec
|
||||||
s = '%s %s %d' % (rev_events[ev.type], rev_event_keys[ev.type][ev.code], ev.value)
|
s = '%s %s %d' % (rev_events[ev.type],
|
||||||
|
rev_event_keys[ev.type][ev.code], ev.value)
|
||||||
print 'Event type:', s
|
print 'Event type:', s
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
@ -89,9 +94,7 @@ while True:
|
|||||||
if not args.compat:
|
if not args.compat:
|
||||||
p.dump((i, ev))
|
p.dump((i, ev))
|
||||||
else:
|
else:
|
||||||
# Use this rather than the line above if you use an old python version (also
|
p.dump((i, (ev.time.tv_sec, ev.time.tv_usec,
|
||||||
# edit create.py)
|
ev.type, ev.code, ev.value)))
|
||||||
p.dump((i, (ev.time.tv_sec, ev.time.tv_usec, ev.type, ev.code,
|
|
||||||
ev.value)))
|
|
||||||
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
26
mapper.py
26
mapper.py
@ -1,8 +1,17 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
import cinput
|
import cinput
|
||||||
|
|
||||||
# XXX: Also parse name, etc
|
"""
|
||||||
|
Module to help out with config parsing and input mapping
|
||||||
|
"""
|
||||||
|
|
||||||
def parse_conf(f, devname):
|
def parse_conf(f, devname):
|
||||||
|
"""
|
||||||
|
Reads in input devices and returns a config that contains all the events
|
||||||
|
exported by the device.
|
||||||
|
|
||||||
|
devname specificies the idx of this input device
|
||||||
|
"""
|
||||||
conf = {}
|
conf = {}
|
||||||
e = f.get_exposed_events()
|
e = f.get_exposed_events()
|
||||||
for k, v in e.iteritems():
|
for k, v in e.iteritems():
|
||||||
@ -25,6 +34,9 @@ def parse_conf(f, devname):
|
|||||||
|
|
||||||
|
|
||||||
def pretty_conf_print(c):
|
def pretty_conf_print(c):
|
||||||
|
"""
|
||||||
|
Function to print an entire configuration
|
||||||
|
"""
|
||||||
for k, v in c.iteritems():
|
for k, v in c.iteritems():
|
||||||
print 'Input:', k[0], 'Type:', cinput.rev_events[k[1]]
|
print 'Input:', k[0], 'Type:', cinput.rev_events[k[1]]
|
||||||
for kk, vv in v.iteritems():
|
for kk, vv in v.iteritems():
|
||||||
@ -36,6 +48,10 @@ def pretty_conf_print(c):
|
|||||||
cinput.rev_event_keys[n_ev_t][vv['code']])
|
cinput.rev_event_keys[n_ev_t][vv['code']])
|
||||||
|
|
||||||
def get_exported_device_count(c):
|
def get_exported_device_count(c):
|
||||||
|
"""
|
||||||
|
Iterate dictionary to find out how many devices are exported.
|
||||||
|
(Rather simple at the moment)
|
||||||
|
"""
|
||||||
m = 0
|
m = 0
|
||||||
for _, v in c.iteritems():
|
for _, v in c.iteritems():
|
||||||
for _, o in v.iteritems():
|
for _, o in v.iteritems():
|
||||||
@ -49,6 +65,10 @@ class KeyMapper(object):
|
|||||||
self._config = config
|
self._config = config
|
||||||
|
|
||||||
def map_event(self, ev, fd):
|
def map_event(self, ev, fd):
|
||||||
|
"""
|
||||||
|
Maps an event *ev* from fd *fd* to a possibly different event and output
|
||||||
|
fd *ofd*.
|
||||||
|
"""
|
||||||
_type = ev.type
|
_type = ev.type
|
||||||
|
|
||||||
if _type in self._config:
|
if _type in self._config:
|
||||||
@ -67,6 +87,10 @@ class KeyMapper(object):
|
|||||||
return ofd, ev
|
return ofd, ev
|
||||||
|
|
||||||
def expose(self, d, fd):
|
def expose(self, d, fd):
|
||||||
|
"""
|
||||||
|
Expose exposes events to a uinput-device *d* with index *fd* from the
|
||||||
|
config passed to __init__.
|
||||||
|
"""
|
||||||
for (n, evt), v in self._config.iteritems():
|
for (n, evt), v in self._config.iteritems():
|
||||||
for code, dat in v.iteritems():
|
for code, dat in v.iteritems():
|
||||||
ofd, t = dat['type']
|
ofd, t = dat['type']
|
||||||
|
Loading…
Reference in New Issue
Block a user