]> git.neil.brown.name Git - freerunner.git/commitdiff
Initial commit for "lock" - screen lock for neo Freerunner
authorNeil Brown <neilb@suse.de>
Wed, 28 Jan 2009 02:44:14 +0000 (13:44 +1100)
committerNeil Brown <neilb@suse.de>
Wed, 28 Jan 2009 02:44:14 +0000 (13:44 +1100)
lock/lock-no.png [new file with mode: 0644]
lock/lock-nosusp.png [new file with mode: 0644]
lock/lock-un-nosusp.png [new file with mode: 0644]
lock/lock-un.png [new file with mode: 0644]
lock/lock.png [new file with mode: 0644]
lock/lock.py [new file with mode: 0644]
lock/lock.xcf [new file with mode: 0644]

diff --git a/lock/lock-no.png b/lock/lock-no.png
new file mode 100644 (file)
index 0000000..fe367d3
Binary files /dev/null and b/lock/lock-no.png differ
diff --git a/lock/lock-nosusp.png b/lock/lock-nosusp.png
new file mode 100644 (file)
index 0000000..3174bb5
Binary files /dev/null and b/lock/lock-nosusp.png differ
diff --git a/lock/lock-un-nosusp.png b/lock/lock-un-nosusp.png
new file mode 100644 (file)
index 0000000..965b4e7
Binary files /dev/null and b/lock/lock-un-nosusp.png differ
diff --git a/lock/lock-un.png b/lock/lock-un.png
new file mode 100644 (file)
index 0000000..990d127
Binary files /dev/null and b/lock/lock-un.png differ
diff --git a/lock/lock.png b/lock/lock.png
new file mode 100644 (file)
index 0000000..bb7b064
Binary files /dev/null and b/lock/lock.png differ
diff --git a/lock/lock.py b/lock/lock.py
new file mode 100644 (file)
index 0000000..27294af
--- /dev/null
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+
+# This software is copyright Neil Brown 2009.
+# It is licensed to you under the terms of the
+# GNU General Public License version 2.
+#
+#
+# blank and lock the screen when there is no activity.
+#
+# We detect activity by watching touch screen, power button,
+# aux button
+# After a period with no activity, we drop brightness to 20%
+# and Grab all devices.
+# Any activity at this stage returns us to 100% and no grab
+# Continued inactivity turns display off.  After that, require
+# a button (AUX or Power) to reactivate.
+#
+# If the device seems really idle, we suspend with "apm -s"
+# Other applications can disable this by getting a LOCK_SH
+# lock on /var/run/suspend_disabled
+#
+
+import gobject
+import gtk
+import fcntl
+import os
+import sys
+import struct
+import time
+from subprocess import Popen, PIPE
+
+class EvDev:
+    def __init__(self, path, on_event):
+        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.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:
+                    del self.downlist[self.downlist.index(code)]
+            else:
+                # 'down' - add to downlist
+                if code not in self.downlist:
+                    self.downlist.append(code)
+        self.on_event(self.down_count(), typ, code, value)
+        return True
+    def down_count(self):
+        return len(self.downlist)
+
+    def grab(self):
+        if self.grabbed:
+            return
+        #print "grab"
+        fcntl.ioctl(self.f, EVIOC_GRAB, 1)
+        self.grabbed = True
+    def ungrab(self):
+        if not self.grabbed:
+            return
+        #print "release"
+        fcntl.ioctl(self.f, EVIOC_GRAB, 0)
+        self.grabbed = False
+
+FBIOBLANK = 0x4611
+FB_BLANK_UNBLANK = 0
+FB_BLANK_POWERDOWN = 4
+
+EVIOC_GRAB = 0x40044590
+
+class Screen:
+    def __init__(self):
+        self.state = "unknown"
+        f = open("/sys/class/backlight/gta02-bl/max_brightness")
+        self.max = int(f.read())
+        f.close()
+    def bright(self, pcent):
+        b = int(pcent * self.max / 100)
+        f = open("/sys/class/backlight/gta02-bl/brightness","w")
+        f.write("%d\n" % b)
+        f.close()
+    def power(self, ioc):
+        f = open("/dev/fb0", "r+")
+        fcntl.ioctl(f, FBIOBLANK, ioc)
+        f.close()
+    def on(self):
+        if self.state != "on":
+            self.power(FB_BLANK_UNBLANK)
+            self.state = "on"
+        self.bright(100)
+    def dim(self):
+        if self.state != "on":
+            self.power(FB_BLANK_UNBLANK)
+            self.state = "on"
+        self.bright(20)
+    def off(self):
+        self.bright(0)
+        if self.state != "off":
+            self.power(FB_BLANK_POWERDOWN)
+            self.state = "off"
+
+def grab_all():
+    global screen, power, aux
+    screen.grab()
+    power.grab()
+    aux.grab()
+
+def release_all():
+    global screen, power, aux
+    screen.ungrab()
+    power.ungrab()
+    aux.ungrab()
+
+timeout = None
+state = "full"
+dimtime = 15
+enable_suspend = True
+def set_timeout():
+    global timeout
+    global state, enable_suspend
+    global dimtime
+    #print "set timeout for", state
+    if timeout != None:
+        gobject.source_remove(timeout)
+    if state == "full":
+        timeout = gobject.timeout_add(dimtime*1000, set_dim)
+    elif state == "dim":
+        timeout = gobject.timeout_add(10*1000, set_off)
+    elif state == "insta-lock":
+        timeout = gobject.timeout_add(1000, set_off)
+    elif state == "off" and enable_suspend:
+        timeout = gobject.timeout_add(30*1000, set_suspend)
+
+    set_ico_file()
+
+def set_dim():
+    global state
+    global aux, power, screen
+    if aux.down_count() + power.down_count() + screen.down_count() > 0:
+        # button still down
+        set_timeout()
+        return
+    display.dim()
+    grab_all()
+    state = "dim"
+    set_timeout()
+
+def set_off():
+    global state, dimtime
+    display.off()
+    state = "off"
+    set_timeout()
+    dimtime = 15
+
+def read_num(filename, default = 0, sep = None):
+    try:
+        f = open(filename)
+    except:
+        f = [ "%d" % default ]
+    num = default
+    for l in f:
+        l = l.split(sep)[0].strip()
+        try:
+            num = float(l)
+            break
+        except:
+            num = default
+    return num
+
+#Active Internet connections (w/o servers)
+#Proto Recv-Q Send-Q Local Address           Foreign Address         State
+#tcp        0     48 192.168.2.202:22        192.168.2.200:34244     ESTABLISHED
+#tcp        0      0 192.168.2.202:22        192.168.2.200:41473     ESTABLISHED
+def external_tcp():
+    # check for TCP connections to external computers.
+    netstat = Popen(['netstat','-nt'], stdout = PIPE, close_fds = True)
+    for l in netstat.stdout:
+        l = l.strip()
+        f = l.split()
+        if f[0] != "tcp" or f[5] != 'ESTABLISHED':
+            continue
+        a = f[4].split(':')
+        if a[0] != "127.0.0.1":
+            return True
+    return False
+
+def set_suspend():
+    global state, display
+    # Check for lock file
+    try:
+        f = open("/var/run/suspend_disabled", "r+")
+    except:
+        f = None
+    if f:
+        try:
+            fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
+        except:
+            set_timeout()
+            return
+
+    # Check for loadavg > 0.5
+    load = read_num("/proc/loadavg")
+    if load > 0.5:
+        set_timeout()
+        return
+
+    # Check for USB power, at least 500mA
+    current = read_num("/sys/class/i2c-adapter/i2c-0/0-0073/pcf50633-mbc/usb_curlim")
+    if current >= 500:
+        set_timeout()
+        return
+
+    #if external_tcp():
+    #    set_timeout()
+    #    return
+
+    os.system("apm -s")
+    if f:
+        f.close()
+    state = "full"
+    set_timeout()
+    display.on()
+
+def wake_all(down_cnt, *rest):
+    global state, dimtime
+    #print "wake all"
+    display.on()
+    if down_cnt == 0:
+        release_all()
+    if state == "dim" and dimtime < 120:
+        dimtime += 15
+    if state != "disable":
+        state = "full"
+    set_timeout()
+
+def wake_dim(down_cnt, *rest):
+    global state
+    #print "wake_dim"
+    if state == "dim" or state == "full":
+        wake_all(down_cnt)
+
+
+ico_file = None
+def set_ico_file():
+    global state, ico_file, ico
+    if state == "disable":
+        file = "lock-no.png"
+    elif state == "full":
+        if enable_suspend:
+            file = "lock-un.png"
+        else:
+            file = "lock-un-nosusp.png"
+    else:
+        if enable_suspend:
+            file = "lock.png"
+        else:
+            file = "lock-nosusp.png"
+    if file != ico_file:
+        ico.set_from_file("/usr/local/pixmaps/" + file)
+        ico_file = file
+
+last_ping = 0
+prev_ping = 0
+def ping(icon):
+    global state, enable_suspend, last_ping, prev_ping
+    if time.time() - prev_ping < 0.8:
+        grab_all()
+        state = "insta-lock"
+    elif state == "disable":
+        enable_suspend = False
+        state = "full"
+    elif not enable_suspend:
+        enable_suspend = True
+        state = "full"
+    else:
+        state = "disable"
+    prev_ping = last_ping
+    last_ping = time.time()
+    set_timeout()
+
+def main():
+    global display, ico
+    global screen, power, aux
+    aux = EvDev("/dev/input/event4", wake_all)
+    power = EvDev("/dev/input/event0", wake_all)
+    screen = EvDev("/dev/input/event1", wake_dim)
+    state = "full"
+    display = Screen()
+    display.on()
+    ico = gtk.StatusIcon()
+    set_timeout()
+    ico.connect("activate", ping)
+
+    gtk.main()
+
+main()
diff --git a/lock/lock.xcf b/lock/lock.xcf
new file mode 100644 (file)
index 0000000..92462fc
Binary files /dev/null and b/lock/lock.xcf differ