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