--- /dev/null
+# 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