3 # This software is copyright Neil Brown 2009.
4 # It is licensed to you under the terms of the
5 # GNU General Public License version 2.
8 # blank and lock the screen when there is no activity.
10 # We detect activity by watching touch screen, power button,
12 # After a period with no activity, we drop brightness to 20%
13 # and Grab all devices.
14 # Any activity at this stage returns us to 100% and no grab
15 # Continued inactivity turns display off. After that, require
16 # a button (AUX or Power) to reactivate.
18 # If the device seems really idle, we suspend with "apm -s"
19 # Other applications can disable this by getting a LOCK_SH
20 # lock on /var/run/suspend_disabled
30 from subprocess import Popen, PIPE
33 def __init__(self, path, on_event):
34 self.f = os.open(path, os.O_RDWR|os.O_NONBLOCK);
35 self.ev = gobject.io_add_watch(self.f, gobject.IO_IN, self.read)
36 self.on_event = on_event
41 str = os.read(self.f, 16)
47 (sec,usec,typ,code,value) = struct.unpack_from("IIHHI", str)
51 # 'up' - remove from downlist
52 if code in self.downlist:
53 self.downlist.remove(code)
55 # 'down' - add to downlist
56 if code not in self.downlist:
57 self.downlist.append(code)
58 self.on_event(self.down_count(), typ, code, value)
61 if len(self.downlist) == 0:
63 # double check, we might have missed an 'up' event somehow.
65 rv = fcntl.ioctl(self.f, EVIOCGKEY(768/8), (768/8) * " " )
67 ra = struct.unpack('%dI' % l, rv)
69 for k in self.downlist:
72 if by < l and ((ra[by] >> bt) & 1) == 0:
75 self.downlist.remove(k)
78 return len(self.downlist)
84 fcntl.ioctl(self.f, EVIOCGRAB, 1)
90 fcntl.ioctl(self.f, EVIOCGRAB, 0)
95 FB_BLANK_POWERDOWN = 4
97 EVIOCGRAB = 0x40044590
99 return 0x80004518 + len * 65536
103 self.state = "unknown"
104 f = open("/sys/class/backlight/gta02-bl/max_brightness")
105 self.max = int(f.read())
107 def bright(self, pcent):
108 b = int(pcent * self.max / 100)
109 f = open("/sys/class/backlight/gta02-bl/brightness","w")
112 def power(self, ioc):
113 f = open("/dev/fb0", "r+")
114 fcntl.ioctl(f, FBIOBLANK, ioc)
117 if self.state != "on":
118 self.power(FB_BLANK_UNBLANK)
122 if self.state != "on":
123 self.power(FB_BLANK_UNBLANK)
128 if self.state != "off":
129 self.power(FB_BLANK_POWERDOWN)
133 global screen, power, aux
139 global screen, power, aux
147 enable_suspend = True
150 global state, enable_suspend
152 #print "set timeout for", state
154 gobject.source_remove(timeout)
156 timeout = gobject.timeout_add(dimtime*1000, set_dim)
158 timeout = gobject.timeout_add(10*1000, set_off)
159 elif state == "insta-lock":
160 timeout = gobject.timeout_add(1000, set_off)
161 elif state == "off" and enable_suspend:
162 timeout = gobject.timeout_add(30*1000, set_suspend)
168 global aux, power, screen
169 if aux.down_count() + power.down_count() + screen.down_count() > 0:
179 global state, dimtime
185 def read_num(filename, default = 0, sep = None):
189 f = [ "%d" % default ]
192 l = l.split(sep)[0].strip()
200 #Active Internet connections (w/o servers)
201 #Proto Recv-Q Send-Q Local Address Foreign Address State
202 #tcp 0 48 192.168.2.202:22 192.168.2.200:34244 ESTABLISHED
203 #tcp 0 0 192.168.2.202:22 192.168.2.200:41473 ESTABLISHED
205 # check for TCP connections to external computers.
206 netstat = Popen(['netstat','-nt'], stdout = PIPE, close_fds = True)
207 for l in netstat.stdout:
210 if f[0] != "tcp" or f[5] != 'ESTABLISHED':
213 if a[0] != "127.0.0.1":
218 global state, display
219 # Check for lock file
221 f = open("/var/run/suspend_disabled", "r+")
226 fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
231 # Check for loadavg > 0.5
232 load = read_num("/proc/loadavg")
237 # Check for USB power, at least 500mA
238 current = read_num("/sys/class/i2c-adapter/i2c-0/0-0073/pcf50633-mbc/usb_curlim")
254 def wake_all(down_cnt, *rest):
255 global state, dimtime
260 if state == "dim" and dimtime < 120:
262 if state != "disable":
266 def wake_dim(down_cnt, *rest):
269 if state == "dim" or state == "full":
275 global state, ico_file, ico
276 if state == "disable":
278 elif state == "full":
282 file = "lock-un-nosusp.png"
287 file = "lock-nosusp.png"
289 ico.set_from_file("/usr/local/pixmaps/" + file)
295 global state, enable_suspend, last_ping, prev_ping
296 if time.time() - prev_ping < 0.8:
299 elif state == "disable":
300 enable_suspend = False
302 elif not enable_suspend:
303 enable_suspend = True
307 prev_ping = last_ping
308 last_ping = time.time()
313 global screen, power, aux
314 aux = EvDev("/dev/input/event4", wake_all)
315 power = EvDev("/dev/input/event0", wake_all)
316 screen = EvDev("/dev/input/event1", wake_dim)
320 ico = gtk.StatusIcon()
322 ico.connect("activate", ping)