From 7c7abc7e597010d369de09c5d95a3bba22896d38 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 18 May 2013 18:32:44 +0200 Subject: [PATCH] Document most code. --- cinput.py | 38 ++++++++++++++++++++++++++++++++++---- input-create | 16 ++++++++++------ input-read | 19 +++++++++++-------- mapper.py | 26 +++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/cinput.py b/cinput.py index c67184c..46d7d3f 100644 --- a/cinput.py +++ b/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)[:]) diff --git a/input-create b/input-create index 93d9a28..3bae5b7 100755 --- a/input-create +++ b/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() diff --git a/input-read b/input-read index 1d01d4f..6c99129 100755 --- a/input-read +++ b/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() diff --git a/mapper.py b/mapper.py index 6e46eab..a5ae27e 100644 --- a/mapper.py +++ b/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']