From f53e9f16af6c5af1748903edfdeb3647b7c39cb2 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 22 Apr 2012 08:33:45 +1000 Subject: [PATCH] Add utils/lock.py Also add associated icons in new 'icons' directory. 'lock' handles locking the display when idle and allowing suspend when completely idle. This has lots of dependencies on things that aren't packaged yet. - susman (suspend manager) - sound (plays sound files when they appear in a directory) Signed-off-by: NeilBrown --- icons/lock-no.png | Bin 0 -> 2353 bytes icons/lock-nosusp.png | Bin 0 -> 1981 bytes icons/lock-un-nosusp.png | Bin 0 -> 2155 bytes icons/lock-un-pressed.png | Bin 0 -> 2122 bytes icons/lock-un.png | Bin 0 -> 1423 bytes icons/lock.png | Bin 0 -> 1242 bytes icons/lock.xcf | Bin 0 -> 10360 bytes {utils => icons}/tapinput.png | Bin utils/lock.py | 557 ++++++++++++++++++++++++++++++++++ 9 files changed, 557 insertions(+) create mode 100644 icons/lock-no.png create mode 100644 icons/lock-nosusp.png create mode 100644 icons/lock-un-nosusp.png create mode 100644 icons/lock-un-pressed.png create mode 100644 icons/lock-un.png create mode 100644 icons/lock.png create mode 100644 icons/lock.xcf rename {utils => icons}/tapinput.png (100%) create mode 100755 utils/lock.py diff --git a/icons/lock-no.png b/icons/lock-no.png new file mode 100644 index 0000000000000000000000000000000000000000..fe367d3a285a79f4f4127912612125ed0fd87c9b GIT binary patch literal 2353 zcmV-13C{M3P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXA& z6)!uge)%K-000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000P#NklsiGX)Or@S7C;O~Jq&6h7Go^jw>68H9pb1zQ!o_b~{b z+1}H0ySk}&5`W(WY@DL6JG09LvNKBnsL9AyZdWof1QhJf7Z>7^9ybBs1?Ej50F#-d z=Xgc=&`S?JurBQPFV}+l0CQ$MesbwY*MI-@(`U~I#^Q?{8LV~+$k0SoZ1!y?y#ga`#nF_J3GtgcV9el2DhQ9^40_+fxKLZ0@ z`wom`{%GZ6ZAD(MryA%`O8pf0-Vc_2w&sN+M}M?161||~ttC6%jK1xZg^k$0-A-Z)hj7*@FlpEE5GB87kl7>!$| z%CLMePb>tmlTN^JaFe_=A+!1&sF`>9)rEE86SK+y5;>~-9N=5P3IzqOgwe9fbcK%3 z@cW&EBo{m(msqGZ@+|+H0I~*H^3|1>PFGf(eyM5kfGNDFE3V1_Q3pH^Y;d#0o_z<7 z3WP;u=5K!Y`sh^VcUU1H$}S$;^Tfa|V29HJBC_1)^BpWNub}$AYU<0&Sv?TpD<|Hk zI2KE*j0#W-77*UHjmwQq^bHLX4u|RQ57XBdCLB(-e){_Q=pP8vAMR&(c%&^JAA4H^ z-=T|JuGoCW(7OluG!)6f0LMiHuh)aeFc|g~@b1C|9By95NJ&YSFUgrR1a|JE?9Kgn zV=)_)0;QDw-u5Fz><rXkf+}j@9w;@LHA1pTxF9P1d7`p{=u=N&ZrhdvtwA7wwRtm%mKKy`FTG2nQ64*XjHD44K#t$;UaeXtu~i@Y*)f`q#?0g|!8?9$d`zXP@PIM+c_Qmlc3by}kS} z_)oqxFu+XH%ygdy7mgMZZ2^*7B9l?q2{lQ|3?h<5qMgW@+7zn5N1~>N-Yr|W($|9yjVxHmU2u;X-aHRwTVsyrP2hPi!C& zi&1mr2p-EyXMf}4d@~xw=ka(dE%RZZ#l?M6RNI>@*=m9|*XCKqg_Of&6M~|HS5m1} ziE@apQh9##-dP0KtbzW1YEPa_D?$QPS{7R@%j2;(7w&iQ{a}*f7#aI6-7dUiHL!ZA zQpL$SU?d}2GWd_h1G^vg)OjS?mboP!tGdEU-20~O``b@_4*HZ*X(s3?m$81@1upY{(q_l1lc z=-hS$8k=G5lcves#JDZIk~D6Y4CEvTr8MUeN#%IU>m__|Id3*C;n$6g^c5CP^+ab+ zrk5BQxjCd4)A=$IGok+5i3A%XQR-qbwDNUR8bEr4TS^dz8)@3iNMQkeMMeC3#*D0G zU7o=0%G{;)=IPkUL?OxM7fSK?&=B<(FIw+=z1E=NvAltR5{wj(^tezs!@6*In5wH+ zWx=^~#-cN4jJlyA!#la~ow*e2&A~Av$~IM!NaajrC6>kK`}>X0L?R!Je(=HBk&=>g z!*l1JO)RMIRc&AHm8$BPvwv~0r+8L(chv*u&sW`Z`EtEK8m;q>j@J83vuX<4>z%oF zrd<#D{tFH`oWk$Ese`|};fU#f`;hN$IA*=;54!)q{%VltK=AJSvxf^9CxDOT?>7Gd XFwNM(?d>A+00000NkvXXu0mjf(9d3j literal 0 HcmV?d00001 diff --git a/icons/lock-nosusp.png b/icons/lock-nosusp.png new file mode 100644 index 0000000000000000000000000000000000000000..3174bb529207aaf2f27d8defc45bbe3003c9bec6 GIT binary patch literal 1981 zcmV;u2SWIXP)Px#24YJ`L;&*u!~m9g9hn~h000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXA) z2r(S$pd4=i000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000LVNkl>3+m?1kXVx-@nqJJ2SP9n`cGwG>(>ph7Un1SC)diiA|D5-n1m z@&av?w@P`bn#VS3)aIe3n3@<9LXDKP3aT1A6)8!KvLSIzYwvp3c5Jh|GhZL(%zF0b zD{L#3BOlFWXU_Tmzsvu8XAJk-{dT|IZ};2(bCbJ0VCU1j8gTRlh220iPzKn*`y%pk zAP_ivw)>4Q{-+3Z?ccLHl}ddBI0+mux9NVg9 zFeV~TclY$YyO{U3v_B?a-q`pxRlR0zoj!lz(oaiDpmXo8EvkAESPz^yf8o+Emodg+ zRec?}B_i9pd-{f#I)=4e0;+lts0FSs2Rwjn+vkC^z=NvVwVW}mWvWgH*kmqWU#<~) zdN0qIoJj%uo;~u6RT2WWZHIsd0W6W;6$;rkU<}ymIH^^o3ZbCUbr6ZJ1id9PVLY(L zNjXvy0;(GD79~}kTG>)6%H z%aUlNOs*(|&h_-YD-actwXgm5_p|qW9T1V7Wo2boHf*S+@k@;~hQl<}HxLeosc)!v zkM-`cu`x_CnIamC5*>}Y$7qyTEXvrJd+zoaV`F2)#-qfdF{YZ zFhIbv5CjoW&m8_JR`KF&?$o_RRo!zpju7*%qBA0Trvy1*5LpW1lE9D=k*r75pjH>T zdrb!Y91)j+=n_&nsBjE8V`}%@_7ib`D-cSWXM;8IIFI!9^3dhW1g72EY!y%iGy#(> zE&Q#ki$q7p}LqlwR zrbX_fplP9rH zohnG8e0G-ay>*3$MnZC?S~Es6b2rUHAifZR=3D}bYav100CI!V{Bz^CJqrByKK}n^^=RrWYg7?hm7krNuk9<}OsS7njCH z?mYiIv)i`ikr1F|c$mY3gVfJV=Y*(w;nO}3fd~+>#AOmG;)M{eLzlC`zmJaUxu)D%tcyhFfovcjn$mEs491Z9Chpw6+M z0JhH)J|13|fIwVbMv)>f?EoU`bJ-kFO!7)bT2<5sT{AjA`@nhz4;+A4jOOdtv&sMg z>Kum?juQyLac{#^B=!eQ=x2@5Z#qSCVLz~ct7?_E4p?4BOEwVk-BT6cA_ZU6*7E1Q zd%3ZBGq#n#j&1;{alacC)Bh}-mT%$+aCHGiI(8bqU6au{F@IJjY}8*1`RW2!=Us&v zuie0#J9l!Wt&P#jN;H3U4a{TxtK!3G6<~L6o^_#p8$9!@ZL=|*a=~kM;pQc>M?%%q zJR%v5cY;Bp4{YG#<6HQ3dpl$0i`o;#4YvNG)u>_CJ&z)>7FvIpPID}tpk-%q z5XjDOM+NbPktv&*DPP4{WhMVyy_)pG1O|X^$%&9)kq2L8ZXwC9FI4H8oTT;EE$8pS zpfh0woM0%Vf|VhXofnEft;?sU3E#dg4-XAln?L%W&s!@JiI$4l+14`K4liK&hyj023WRo1HCGq-aoqhv^CDx^D@#5tkVhe3ao9YM z$`k_sD=986^L#OYW`!RsyrFb#Y!=G>IJw zFDra<55a$8=Gd`V@Uqm9GG)bg%(0of(;`OSuLAu`iFaA1M?4~JzN&Gl?vDG4vcaVS zzbpTt@ohTVa@3{JUN-LQo>~p!R=M#Ne%!e`d6Gk*Cg+iapTJ5$``dp2yU<{dyBfX_ P00000NkvXXu0mjfL&Tv+ literal 0 HcmV?d00001 diff --git a/icons/lock-un-nosusp.png b/icons/lock-un-nosusp.png new file mode 100644 index 0000000000000000000000000000000000000000..965b4e77df607547cace72100b200afff499ac0a GIT binary patch literal 2155 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 literal 0 HcmV?d00001 diff --git a/icons/lock.png b/icons/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..bb7b06458cfe09f42c8ccb6a4606a91409e6b5f4 GIT binary patch literal 1242 zcmV<01SR{4P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXA& z6*4M6qP5BZ000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000CvNklxDmH* ziguyV#7W!4kFB)0&_WTxjY2`_yb1V`X=a>vT-^KSeGFnc<2(iD48wi*@!rk(pYuQe zb0#pciA`)`6Z=1#{^2P}o=m0U`faw4R;C<)xju~ICHa5EdDuA=6PtJ5YoeRKg;k>VaZ-8%s+rS?Z zd(4;xjsQ;sj{$AqUEspn`sP;Y03JR3h`#&&2U}V^{uwY2+ydT^bQ#!MZEUoQ?<}5} zpQ%%@QYrA>x=#j_u(1Z0S%#)=U#B70O<94`+-9MPP#Ip zkX;9wz*BMD-BT8YszKL5ibnC?Nxy^)+!J?Wl>)%bDoIl^v)@K*rP>QrfIFSIXQdT! z2F%`(-jCz^LNGe}rl-p(;^!8Q{ame9e{@dKjD8)7LZ37?t_dPZ_g?(qqdQ~o1CowS zO-+4y;J`uZ57epGYRt{fQLELMotyRRtY7Q(8l6s;s1*_2j{F)$v|16(roZ;z7R_dp z)>cF-YO%fDp6_&az8F^qx{|0?D^#3A2nj3+N0!B=glFlc-(qI|+Vcp7cMWSxwo^h4 z1dp77JO~09Nx4TXcx~Quzo+kg3dAFjSqVif*}xG2g9j13x16_@dC(GvGZ`zaWn@4E zhh5^i0*azqsn4-uh%KR6*qLm60Fpl=DMJ-kPz2@tw}dKzK5-$)S%1xhOydKf0qqj9 z{Cy>937q%NXC1aado20%i`x1@8dC;*gcQgwEQHWU-6h!wbh0ABEzKfvu?7q!n8%)h zgywST#x&Sma`XuNHu>UKU!n>Wwec3QloqegNr=BoAGAzEt8d?GZts~?nB^vghF=44M2Z4gd_^3f>bI!z$|UcnFgRTD3o`UP`v6( ztI2Y%r#c_HG3IHeEGQf3Yh&)j!u4BkF*(YN5y~{F!OvL331yJ-8gCi;TRKi;ma?YNOi{}MfP96=CX}U- zrFx%re3)UbI>K++9p8@=*2_~V0Lj;dVSg!GNplO&7_kYrTM)wlxB)!tpbh@N2u@!9 z%nS(}t}xE|A1&V5!5~|f2qK2~CKH?3#3nYeiS5Gv1Obfx@l?vuPXGV_07*qoM6N<$ Ef+%P~JOBUy literal 0 HcmV?d00001 diff --git a/icons/lock.xcf b/icons/lock.xcf new file mode 100644 index 0000000000000000000000000000000000000000..92462fc9da64b0b7c32d1602be308956f497468c GIT binary patch literal 10360 zcmeHNX>e3k7QWp{I-PEkys!izNIHN5qiC~aAS_d1>rUv->+S?3fDDNtgs>zThzsM8 z1YBmA(MiA!$8AQ@nHo!jY$`evtE>{jV#XRv9Yq^lP?;$MxRBo7o$uWDUMGQm{?aO~ z@>M zJA3(17ukyWrPtggY_9pk6R(W=>>%~$WXJoaIl~&4&(>`E^)JIZ+Z&hDI&*sa=05!) zfPBEyYw$cKRMoFvUtLG%5r-T&cSCh$WA#eM&9#lI9q!^1KOvGZtzBPPQ$3+(L#_Bf z;=g3Fj@#I{Xy!^Y~W#@hP2jpJ?OR@GG1udCnS7$=$u8)|N-bU3eZiYq~9 zq6UqJ>kSE9b=+axA=g_rHdI#C*3~#BPtq5(joXxHQk$D_V_j_{4qvspnofO7{i;

CiOksh?Sa#QsN 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 +# +# 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. +# +# +# 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. +# +# While display is lit we prevent suspend. As soon as display +# is dark, suspend is allowed to progress. +# +# Also handle alerts. Alerts are signaled by files appearing in +# /var/run/alert. We respond by: +# - disabling suspend +# - triggering a vibrator rumble +# - playing a suitable sound by linking a sound from /etc/alert/$name +# to /var/run/sound. A separate program plays the sound. +# - restoring the display to "dim" if it is "off". +# +# +# contains lots of old/dead code +# - vibrator control for GTA02 +# - watches GTA04 accelerometer and locks display when upside-down +# - look for external network connections. The idea was to disable +# suspend if there were any, but it is too easy for them to remain +# after network is disconnected. +# Needs lots of cleaning up. + +import gobject +import gtk +import fcntl +import os +import time +import suspend +import dnotify + +from subprocess import Popen, PIPE +from vibra import Vibra +from evdev import EvDev + +FBIOBLANK = 0x4611 +FB_BLANK_UNBLANK = 0 +FB_BLANK_POWERDOWN = 4 + +def sysfs_write(file, val): + try: + f = open(file, "w") + f.write(val) + f.close() + except: + pass + +vib_timer = None +def gta02_set_vibrate(on, off, total): + global vib_timer + if vib_timer: + return + vib = "/sys/class/leds/neo1973:vibrator" + sysfs_write(vib+"/trigger", "none") + sysfs_write(vib+"/trigger", "timer") + sysfs_write(vib+"/delay_on", "%d"%on) + sysfs_write(vib+"/delay_off", "%d"%off) + vib_timer = gobject.timeout_add(total, clear_vibrator) +def clear_vibrator(): + return + global vib_timer + if vib_timer: + gobject.source_remove(vib_timer) + vib_timer = None + vib = "/sys/class/leds/neo1973:vibrator" + sysfs_write(vib+"/trigger", "none") + +vib_han = None +def set_vibrate(on, off, total): + global vib_han + if vib_han: + return + vib_han = Vibra() + vib_han.play(vib_han.multi_vibe(on, total/(on+off), off)) + gobject.timeout_add(total, clear_vibe) +def clear_vibe(): + global vib_han + if vib_han: + vib_han.close() + vib_han = None + +class SetAlerts: + def __init__(self, alertdir, actiondir): + # arrange to respond to alerts. + # If a name appears in 'alertdir', respond based + # on the content of the same name in 'actiondir'. + # Currently that must be a WAV file to be played + # If the file disappears, the action must stop instantly + # If the file is newer when the action completes, it is + # restarted + self.alertdir = alertdir + self.actiondir = actiondir + self.watch = dnotify.dir(alertdir) + self.active = {} + self.watch.watchall(self.runalert) + self.pref = "normal" + self.blocker = suspend.blocker(False) + + def setpref(self, str): + self.pref = str + + def runalert(self): + self.blocker.block() + gobject.idle_add(self.alert) + return True + + def alert(self): + # Only look for new entries here. + for n in os.listdir(self.alertdir): + if n in self.active: + continue + if n[0] == '.': + continue + self.add_alert(n) + self.blocker.unblock() + return False + + def add_alert(self, name): + #print "adding", name + self.active[name] = (None, None, None) + w = self.watch.watch(name, lambda x : self.runcheck(x, name)) + if w.ino == 0: + del self.active[name] + # already disappeared + return + a = self.action(name) + self.active[name] = (w, a, w.mtime) + + def runcheck(self, w, name): + gobject.idle_add(lambda : self.check(w, name)) + return True + def check(self, w, name): + if name not in self.active: + #print "check", name, "not found" + return False + #print "check", name + (w2, a, mtime) = self.active[name] + if w.ino == 0: + if a: + self.stop(a) + del self.active[name] + return False + #if a and not os.path.exists(a): + # a = None + #if a == None and w.mtime > mtime + 1: + # # play back had stopped - start it again + # print "restart play" + a = self.action(name) + self.active[name] = (w, a, w.mtime) + return False + + def action(self, name): + n = '/var/run/sound/10-alert' + try: + os.symlink(os.path.join(self.actiondir, self.pref, name), n) + except: + pass + set_vibrate(200,400,1800) + + if display.state != 'on': + set_dim() + suspend.abort_cycle() + return n + def stop(self, name): + try: + os.unlink(name) + except OSError: + pass + + def stopall(self): + for n in self.active: + w, a, w_time = self.active[n] + if a: + self.stop(a) + self.active[n] = (w, None, 0) + +class Screen: + def __init__(self): + self.state = "unknown" + f = open("/sys/class/backlight/pwm-backlight/max_brightness") + self.max = int(f.read()) + f.close() + def bright(self, pcent): + b = int(pcent * self.max / 100) + f = open("/sys/class/backlight/pwm-backlight/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, accel + screen.grab() + power.grab() + aux.grab() + #accel.grab() + +def release_all(): + global screen, power, aux, accel + screen.ungrab() + power.ungrab() + aux.ungrab() + #accel.ungrab() + +# wall-clock might get reset when we wake from suspend, so +# use a monotonic clock to guard against early blanking. +import ctypes + +CLOCK_MONOTONIC = 1 # not sure about this one, check the headers + +class timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + +librt = ctypes.CDLL('librt.so.1') +clock_gettime = librt.clock_gettime +clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)] + +def get_ticks(): + t = timespec() + clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) + return t.tv_sec + t.tv_nsec / 1e9 + + + +timeout = None +state = "full" +dimtime = 15 +enable_suspend = True +last_set = 0 +def set_timeout(): + global timeout + global state + global dimtime, last_set + + last_set = get_ticks() + 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) + + + set_ico_file() + global susblock, enable_suspend + if state == "off" and enable_suspend: + susblock.unblock() + else: + susblock.block() + +def set_dim(): + global state, last_set + global aux, power, screen + global one_down + if aux.down_count() + power.down_count() + screen.down_count() > 0: + # button still down + one_down = True + set_timeout() + return + one_down = False + if state != "off" and get_ticks() - last_set < dimtime - 1: + # if delay was too quick, try again + set_timeout() + return + display.dim() + grab_all() + state = "dim" + set_timeout() + +def set_off(): + global state, dimtime + global last_set + if get_ticks() - last_set < 9.5: + set_timeout() + return + grab_all() + 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 wake_all(down_cnt, moment, typ, code, value): + global state, dimtime, alert, suspended + if typ == 0: + # ignore sync events + return + if suspended: + return + alert.stopall() + 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, moment, typ, code, value): + global state, suspended + if suspended: + return + if typ == 0: + return + #print "wake_dim" + if state == "dim" or state == "full": + wake_all(down_cnt, moment, typ, code, value) + +def wake_toggle(down_cnt, moment, typ, code, value): + global state, last_set, enable_suspend, suspended + if suspended: + return + # ignore down, just get up + if typ != 1 or value: + return + if ( state == "full" or state == "disable" ) and get_ticks() - last_set > 0.5: + enable_suspend = True + last_set = 0 + set_off() + else: + wake_all(down_cnt, moment, typ, code, value) + +EV_SYN = 0 +EV_KEY = 1 +EV_ABS = 3 +ABS_X = 0 +ABS_Y = 1 +ABS_Z = 2 +BTN_X = 307 +BTN_Y = 308 +BTN_Z = 309 + +shake_cnt = 0 +shake_time = 0 +shake_seen = 0 +invert_timer = 0 +def check_attitude(down_cnt, moment, typ, code, value): + global state + global shake_cnt, shake_time, shake_seen + if moment - shake_time > 0.4: + shake_cnt = 0 + if typ == EV_ABS and abs(value) > 1500: + shake_time = moment + shake_seen = 1 + if typ == EV_SYN and shake_seen: + shake_cnt += 1 + shake_seen = 0 + if typ == EV_ABS and code == ABS_Y and value > 100: + shake_cnt = 0 + if shake_cnt >= 3: + shake_cnt = 0 + #no wake_all(0) + #no return + + if typ == EV_KEY and code <= BTN_Z and code >= BTN_X and value == 1: + wake_dim(0) + + global invert_timer + if typ == EV_ABS and code == ABS_Y and value > 500: + # upside down - need this for 0.6 seconds + #print "down", moment + if invert_timer == 0: + invert_timer = gobject.timeout_add(400, attitude_confirm) + elif typ == EV_ABS and code == ABS_Y: + #print "up", moment + if invert_timer: + gobject.source_remove(invert_timer) + invert_timer = 0 + +def attitude_confirm(): + global invert_timer, state + # seem to have been inverted for a while + invert_timer = 0 + if state != "off": + display.off() + grab_all() + state = "off" + set_timeout() + return False + +ico_file = None +def set_ico_file(): + global state, ico_file, ico + global aux, power, screen + down = aux.down_count() + power.down_count() + screen.down_count() + if state == "disable": + file = "lock-no.png" + elif state == "full": + if enable_suspend: + if down: + file = "lock-un-pressed.png" + else: + 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 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 setfile(name, val): + f = open(name, 'w') + f.write(val) + f.close() + +def do_release(): + #print "Releasing" + global suspender + suspender.release() + +def suspending(): + # make sure all buttons have been checked + # everything happens in events. When we go idle, + # we have processed everything and can release the suspend. + global suspender, suspended + #print "suspending" + gobject.idle_add(do_release) + #suspended = True + return False + +def resumed(): + global suspended + #print "resumed" + suspended = False + +def main(): + global display, ico + global screen, power, aux, accel + global alert, suspender, susblock + aux = EvDev("/dev/input/aux", wake_all) + power = EvDev("/dev/input/power", wake_toggle) + screen = EvDev("/dev/input/touchscreen", wake_dim) + + try: + os.mkdir("/var/run/alert") + except: + pass + alert = SetAlerts("/var/run/alert", "/etc/alert") + #setfile('/sys/bus/spi/devices/spi3.1/threshold', '500') + #setfile('/sys/bus/spi/devices/spi3.1/sample_rate','0') + #setfile('/sys/bus/spi/devices/spi3.1/taps', '7000 5') + #accel = EvDev("/dev/input/accel", check_attitude) + state = "full" + display = Screen() + display.on() + susblock = suspend.blocker() + ico = gtk.StatusIcon() + set_timeout() + ico.connect("activate", ping) + + suspender.immediate(True) + gtk.main() + +suspended = False +one_down = False +suspender = suspend.monitor(suspending, resumed) +main() -- 2.39.5