]> git.neil.brown.name Git - plato.git/commitdiff
Add evdev.py
authorNeilBrown <neilb@suse.de>
Sat, 21 Apr 2012 11:42:50 +0000 (21:42 +1000)
committerNeilBrown <neilb@suse.de>
Sat, 21 Apr 2012 11:45:56 +0000 (21:45 +1000)
evdev monitors /dev/input/event* (event devices) and calls
a callback on each event.
It allows 'grabbing' of devices too

Signed-off-by: NeilBrown <neilb@suse.de>
lib/evdev.py [new file with mode: 0644]

diff --git a/lib/evdev.py b/lib/evdev.py
new file mode 100644 (file)
index 0000000..fa7e302
--- /dev/null
@@ -0,0 +1,87 @@
+# Copyright (C) 2011-2012 Neil Brown <neilb@suse.de>
+#
+#    This program is free software; you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation; either version 2 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License along
+#    with this program; if not, write to the Free Software Foundation, Inc.,
+#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import gobject, os, struct, fcntl
+
+
+EVIOCGRAB = 0x40044590
+def EVIOCGKEY(len):
+    return 0x80004518 + len * 65536
+
+class EvDev:
+    def __init__(self, path, on_event, arg=None):
+        self.f = os.open(path, os.O_RDWR|os.O_NONBLOCK);
+        self.ev = gobject.io_add_watch(self.f, gobject.IO_IN, self.read)
+        self.on_event = on_event
+        self.grabbed = False
+        self.arg = arg
+        self.downlist = []
+    def read(self, x, y):
+        try:
+            str = os.read(self.f, 16)
+        except:
+            return True
+
+        if len(str) != 16:
+            return True
+        (sec,usec,typ,code,value) = struct.unpack_from("IIHHi", str)
+        if typ == 0x01:
+            # KEY event
+            if value == 0:
+                # 'up' - remove from downlist
+                if code in self.downlist:
+                    self.downlist.remove(code)
+            else:
+                # 'down' - add to downlist
+                if code not in self.downlist:
+                    # ignore the 'play' butten (headphone insert)
+                    if code != 207:
+                        self.downlist.append(code)
+        moment = sec + float(usec)/1000000
+        self.on_event(self.down_count(), moment, typ, code, value)
+        return True
+    def down_count(self):
+        if len(self.downlist) == 0:
+            return 0
+        # double check, we might have missed an 'up' event somehow.
+        try:
+            rv = fcntl.ioctl(self.f, EVIOCGKEY(768/8), (768/8) * " " )
+            l = len(rv)/4
+            ra = struct.unpack('%dI' % l, rv)
+            isup = []
+            for k in self.downlist:
+                by = int(k/8)
+                bt = k % 8
+                if by < l and ((ra[by] >> bt) & 1) == 0:
+                    isup.append[k]
+            for k in isup:
+                self.downlist.remove(k)
+        except:
+            pass
+        return len(self.downlist)
+
+    def grab(self):
+        if self.grabbed:
+            return
+        #print "grab"
+        fcntl.ioctl(self.f, EVIOCGRAB, 1)
+        self.grabbed = True
+    def ungrab(self):
+        if not self.grabbed:
+            return
+        #print "release"
+        fcntl.ioctl(self.f, EVIOCGRAB, 0)
+        self.grabbed = False