parent
7fbc1d347a
commit
725d89d6d6
12 changed files with 352 additions and 604 deletions
@ -0,0 +1,39 @@ |
||||
#!/usr/bin/env sh |
||||
|
||||
. "$(which sxmo_common.sh)" |
||||
|
||||
REDLED_PATH="/sys/class/leds/red:indicator/brightness" |
||||
BLUELED_PATH="/sys/class/leds/blue:indicator/brightness" |
||||
|
||||
finish() { |
||||
kill $BLINKPID |
||||
|
||||
echo 0 > "$REDLED_PATH" |
||||
echo 0 > "$BLUELED_PATH" |
||||
|
||||
# Going back to crust |
||||
if [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; then |
||||
sxmo_screenlock.sh crust "$SXMO_RTCWAKEINTERVAL" |
||||
fi |
||||
|
||||
exit 0 |
||||
} |
||||
|
||||
trap 'finish' TERM INT EXIT |
||||
|
||||
blink() { |
||||
while [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; do |
||||
echo 1 > "$REDLED_PATH" |
||||
echo 0 > "$BLUELED_PATH" |
||||
sleep 0.25 |
||||
echo 0 > "$REDLED_PATH" |
||||
echo 1 > "$BLUELED_PATH" |
||||
sleep 0.25 |
||||
done |
||||
} |
||||
|
||||
blink & |
||||
BLINKPID=$! |
||||
|
||||
# Replace this by wathever you want to do |
||||
sleep 5 |
@ -0,0 +1,39 @@ |
||||
#!/usr/bin/env sh |
||||
|
||||
. "$(which sxmo_common.sh)" |
||||
|
||||
REDLED_PATH="/sys/class/leds/red:indicator/brightness" |
||||
BLUELED_PATH="/sys/class/leds/blue:indicator/brightness" |
||||
|
||||
finish() { |
||||
kill $BLINKPID |
||||
|
||||
echo 0 > "$REDLED_PATH" |
||||
echo 0 > "$BLUELED_PATH" |
||||
|
||||
# Going back to crust |
||||
if [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; then |
||||
sxmo_screenlock.sh rtc "$SXMO_RTCWAKEINTERVAL" |
||||
fi |
||||
|
||||
exit 0 |
||||
} |
||||
|
||||
trap 'finish' TERM INT EXIT |
||||
|
||||
blink() { |
||||
while [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; do |
||||
echo 1 > "$REDLED_PATH" |
||||
echo 0 > "$BLUELED_PATH" |
||||
sleep 0.5 |
||||
echo 0 > "$REDLED_PATH" |
||||
echo 1 > "$BLUELED_PATH" |
||||
sleep 0.5 |
||||
done |
||||
} |
||||
|
||||
blink & |
||||
BLINKPID=$! |
||||
|
||||
# Replace this by wathever you want to do |
||||
sleep 10 |
@ -1,553 +0,0 @@ |
||||
#include <dirent.h> |
||||
#include <fcntl.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
#include <signal.h> |
||||
#include <time.h> |
||||
#include <X11/keysym.h> |
||||
#include <X11/XF86keysym.h> |
||||
#include <X11/XKBlib.h> |
||||
#include <X11/Xlib.h> |
||||
#include <X11/Xutil.h> |
||||
#include <sys/ioctl.h> |
||||
#include <sys/time.h> |
||||
#include <sys/types.h> |
||||
#include <linux/rtc.h> |
||||
|
||||
// Types
|
||||
enum State { |
||||
StateNoInput, // Screen on / input lock
|
||||
StateNoInputNoScreen, // Screen off / input lock
|
||||
StateSuspend, // Deep sleep
|
||||
StateSuspendPending, // Suspend 'woken up', must leave state in <5s, or kicks to StateSuspend
|
||||
StateDead // Exit the appliation
|
||||
}; |
||||
enum Color { |
||||
Red, |
||||
Blue, |
||||
Purple, |
||||
Off |
||||
}; |
||||
|
||||
// Fn declarations
|
||||
int checkrtcwake(); |
||||
void configuresuspendsettingsandwakeupsources(); |
||||
time_t convert_rtc_time(struct rtc_time * rtc); |
||||
void die(const char *err, ...); |
||||
int getoldbrightness(); |
||||
void init_rtc(); |
||||
void lockscreen(Display *dpy, int screen, int blank); |
||||
void unblankscreen(); |
||||
void blankscreen(); |
||||
void readinputloop(Display *dpy, int screen); |
||||
int presuspend(); |
||||
void postwake(); |
||||
void setpineled(enum Color c); |
||||
int setup_rtc_wakeup(); |
||||
void sigterm(); |
||||
void syncstate(); |
||||
void usage(); |
||||
void writefile(char *filepath, char *str); |
||||
|
||||
// Variables
|
||||
Display *dpy; |
||||
Window root; |
||||
enum State state = StateNoInput; |
||||
int suspendtimeouts = 35; |
||||
int suspendpendingsceenon = 0; |
||||
int suspendpendingtimeouts = 0; |
||||
KeySym lastkeysym = XK_Cancel; |
||||
int lastkeyn = 0; |
||||
char oldbrightness[10] = "200"; |
||||
char * brightnessfile = "/sys/devices/platform/backlight/backlight/backlight/brightness"; |
||||
char * powerstatefile = "/sys/power/state"; |
||||
int rtc_fd = 0; //file descriptor
|
||||
time_t wakeinterval = 0; //wake every x seconds
|
||||
time_t waketime = 0; //next wakeup time according to the RTC clock
|
||||
int slept = 0; //indicates whether the process has slept (crust) or not
|
||||
int blanked = 0; //indicated whether the display blanked or not
|
||||
|
||||
#define RTC_DEVICE "/dev/rtc0" |
||||
|
||||
time_t |
||||
convert_rtc_time(struct rtc_time * rtc) { |
||||
struct tm tm; |
||||
memset(&tm, 0, sizeof tm); |
||||
tm.tm_sec = rtc->tm_sec; |
||||
tm.tm_min = rtc->tm_min; |
||||
tm.tm_hour = rtc->tm_hour; |
||||
tm.tm_mday = rtc->tm_mday; |
||||
tm.tm_mon = rtc->tm_mon; |
||||
tm.tm_year = rtc->tm_year; |
||||
tm.tm_isdst = -1; /* assume the system knows better than the RTC */ |
||||
return mktime(&tm); |
||||
} |
||||
|
||||
int setup_rtc_wakeup() { |
||||
//(code adapted from util-linux's rtcwake)
|
||||
struct tm *tm; |
||||
struct rtc_wkalrm wake; |
||||
struct rtc_time now_rtc; |
||||
|
||||
if (ioctl(rtc_fd, RTC_RD_TIME, &now_rtc) < 0) { |
||||
fprintf(stderr, "Error reading rtc time\n"); |
||||
} |
||||
const time_t now = convert_rtc_time(&now_rtc); |
||||
waketime = now + wakeinterval; |
||||
|
||||
tm = localtime(&waketime); |
||||
|
||||
wake.time.tm_sec = tm->tm_sec; |
||||
wake.time.tm_min = tm->tm_min; |
||||
wake.time.tm_hour = tm->tm_hour; |
||||
wake.time.tm_mday = tm->tm_mday; |
||||
wake.time.tm_mon = tm->tm_mon; |
||||
wake.time.tm_year = tm->tm_year; |
||||
/* wday, yday, and isdst fields are unused by Linux */ |
||||
wake.time.tm_wday = -1; |
||||
wake.time.tm_yday = -1; |
||||
wake.time.tm_isdst = -1; |
||||
|
||||
fprintf(stderr, "Setting RTC wakeup to %ld: (UTC) %s", waketime, asctime(tm)); |
||||
|
||||
if (ioctl(rtc_fd, RTC_ALM_SET, &wake.time) < 0) { |
||||
fprintf(stderr, "error setting rtc alarm\n"); |
||||
return -1; |
||||
} |
||||
if (ioctl(rtc_fd, RTC_AIE_ON, 0) < 0) { |
||||
fprintf(stderr, "error enabling rtc alarm\n"); |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
void |
||||
configuresuspendsettingsandwakeupsources() |
||||
{ |
||||
// Disable all wakeup sources
|
||||
struct dirent *wakeupsource; |
||||
char wakeuppath[100]; |
||||
DIR *wakeupsources = opendir("/sys/class/wakeup"); |
||||
if (wakeupsources == NULL) |
||||
die("Couldn't open directory /sys/class/wakeup\n"); |
||||
while ((wakeupsource = readdir(wakeupsources)) != NULL) { |
||||
sprintf( |
||||
wakeuppath, |
||||
"/sys/class/wakeup/%.50s/device/power/wakeup", |
||||
wakeupsource->d_name |
||||
); |
||||
fprintf(stderr, "Disabling wakeup source: %s", wakeupsource->d_name); |
||||
writefile(wakeuppath, "disabled"); |
||||
fprintf(stderr, ".. ok\n"); |
||||
} |
||||
closedir(wakeupsources); |
||||
|
||||
// Enable powerbutton wakeup source
|
||||
fprintf(stderr, "Enable powerbutton wakeup source\n"); |
||||
writefile( |
||||
"/sys/devices/platform/soc/1f03400.rsb/sunxi-rsb-3a3/axp221-pek/power/wakeup", |
||||
"enabled" |
||||
); |
||||
|
||||
// Enable IRQ wakeup source (incoming call) 5.10
|
||||
fprintf(stderr, "Enable 5.10 IRQ wakeup source\n"); |
||||
writefile( |
||||
"/sys/devices/platform/gpio-keys/power/wakeup", |
||||
"enabled" |
||||
); |
||||
|
||||
// Enable IRQ wakeup source (incoming call) 5.9 (no longer exists in 5.10)
|
||||
fprintf(stderr, "Enable 5.9 IRQ wakeup source\n"); |
||||
writefile( |
||||
"/sys/devices/platform/soc/1c28c00.serial/serial1/serial1-0/power/wakeup", |
||||
"enabled" |
||||
); |
||||
|
||||
// Enable rtc wakeup source
|
||||
fprintf(stderr, "Enable rtc wakeup source\n"); |
||||
writefile( |
||||
"/sys/devices/platform/soc/1f00000.rtc/power/wakeup", |
||||
"enabled" |
||||
); |
||||
|
||||
//set RTC wake
|
||||
if (wakeinterval > 0) setup_rtc_wakeup(); |
||||
|
||||
// E.g. make sure we're using CRUST
|
||||
fprintf(stderr, "Flip mem_sleep setting to use crust\n"); |
||||
writefile("/sys/power/mem_sleep", "deep"); |
||||
|
||||
} |
||||
|
||||
void |
||||
die(const char *err, ...) |
||||
{ |
||||
fprintf(stderr, "Screenlock error: %s\n", err); |
||||
state = StateDead; |
||||
syncstate(); |
||||
exit(1); |
||||
} |
||||
|
||||
void |
||||
sigterm() |
||||
{ |
||||
state = StateDead; |
||||
syncstate(); |
||||
if (wakeinterval) { |
||||
ioctl(rtc_fd, RTC_AIE_OFF, 0); |
||||
close(rtc_fd); |
||||
} |
||||
fprintf(stderr, "Screenlock terminating on signal\n"); |
||||
exit(0); |
||||
} |
||||
|
||||
int |
||||
getoldbrightness() { |
||||
char * buffer = 0; |
||||
long length; |
||||
FILE * f = fopen(brightnessfile, "r"); |
||||
if (f) { |
||||
fseek(f, 0, SEEK_END); |
||||
length = ftell(f); |
||||
fseek(f, 0, SEEK_SET); |
||||
buffer = malloc(length); |
||||
if (buffer) { |
||||
fread(buffer, 1, length, f); |
||||
} |
||||
fclose(f); |
||||
} |
||||
if (buffer) { |
||||
sprintf(oldbrightness, "%d", atoi(buffer)); |
||||
} |
||||
} |
||||
|
||||
|
||||
void |
||||
lockscreen(Display *dpy, int screen, int blank) |
||||
{ |
||||
// Loosely derived from suckless' slock's lockscreen binding logic but
|
||||
// alot more coarse, intentionally so can be triggered while grab_key
|
||||
// for dwm multikey path already holding..
|
||||
int i, ptgrab, kbgrab; |
||||
root = RootWindow(dpy, screen); |
||||
if (blank == 1) { |
||||
blankscreen(); |
||||
} |
||||
for (i = 0, ptgrab = kbgrab = -1; i < 9999999; i++) { |
||||
if (ptgrab != GrabSuccess) { |
||||
ptgrab = XGrabPointer(dpy, root, False, |
||||
ButtonPressMask | ButtonReleaseMask | |
||||
PointerMotionMask, GrabModeAsync, |
||||
GrabModeAsync, None, None, CurrentTime); |
||||
} |
||||
if (kbgrab != GrabSuccess) { |
||||
kbgrab = XGrabKeyboard(dpy, root, True, |
||||
GrabModeAsync, GrabModeAsync, CurrentTime); |
||||
} |
||||
if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { |
||||
XSelectInput(dpy, root, SubstructureNotifyMask); |
||||
return; |
||||
} |
||||
usleep(100000); |
||||
} |
||||
} |
||||
|
||||
void |
||||
blankscreen() |
||||
{ |
||||
if (!blanked) { |
||||
system("xset dpms force off"); |
||||
blanked = 1; |
||||
} |
||||
} |
||||
|
||||
void |
||||
unblankscreen() |
||||
{ |
||||
if (blanked) { |
||||
system("xset dpms force on"); |
||||
blanked = 0; |
||||
} |
||||
} |
||||
|
||||
void |
||||
readinputloop(Display *dpy, int screen) { |
||||
KeySym keysym; |
||||
XEvent ev; |
||||
char buf[32]; |
||||
fd_set fdset; |
||||
int xfd; |
||||
int selectresult; |
||||
struct timeval xeventtimeout = {1, 0}; |
||||
xfd = ConnectionNumber(dpy); |
||||
|
||||
for (;;) { |
||||
FD_ZERO(&fdset); |
||||
FD_SET(xfd, &fdset); |
||||
if (state == StateSuspendPending) |
||||
selectresult = select(FD_SETSIZE, &fdset, NULL, NULL, &xeventtimeout); |
||||
else |
||||
selectresult = select(FD_SETSIZE, &fdset, NULL, NULL, NULL); |
||||
|
||||
if (FD_ISSET(xfd, &fdset) && XPending(dpy)) { |
||||
XNextEvent(dpy, &ev); |
||||
if (ev.type == KeyRelease) { |
||||
XLookupString(&ev.xkey, buf, sizeof(buf), &keysym, 0); |
||||
if (lastkeysym == keysym) { |
||||
lastkeyn++; |
||||
} else { |
||||
lastkeysym = keysym; |
||||
lastkeyn = 1; |
||||
} |
||||
|
||||
if (lastkeyn < 3) |
||||
continue; |
||||
|
||||
lastkeyn = 0; |
||||
lastkeysym = XK_Cancel; |
||||
if (slept) postwake(); |
||||
switch (keysym) { |
||||
case XF86XK_AudioRaiseVolume: |
||||
suspendpendingsceenon = state == StateNoInput; |
||||
suspendpendingtimeouts = 0; |
||||
state = StateSuspend; |
||||
break; |
||||
case XF86XK_AudioLowerVolume: |
||||
if (state == StateNoInput) state = StateNoInputNoScreen; |
||||
else if (state == StateNoInputNoScreen) state = StateNoInput; |
||||
else if (state == StateSuspendPending && suspendpendingsceenon) state = StateNoInputNoScreen; |
||||
else state = StateNoInput; |
||||
break; |
||||
case XF86XK_PowerOff: |
||||
waketime = 0; |
||||
state = StateDead; |
||||
break; |
||||
} |
||||
syncstate(); |
||||
} |
||||
} else if (state == StateSuspendPending) { |
||||
suspendpendingtimeouts++; |
||||
// # E.g. after suspendtimeouts seconds kick back into suspend
|
||||
if (suspendpendingtimeouts > suspendtimeouts) state = StateSuspend; |
||||
syncstate(); |
||||
} |
||||
|
||||
|
||||
if (state == StateDead) break; |
||||
} |
||||
} |
||||
|
||||
void |
||||
setpineled(enum Color c) |
||||
{ |
||||
if (c == Red) { |
||||
writefile("/sys/class/leds/red:indicator/brightness", "1"); |
||||
writefile("/sys/class/leds/blue:indicator/brightness", "0"); |
||||
} else if (c == Blue) { |
||||
writefile("/sys/class/leds/red:indicator/brightness", "0"); |
||||
writefile("/sys/class/leds/blue:indicator/brightness", "1"); |
||||
} else if (c == Purple) { |
||||
writefile("/sys/class/leds/red:indicator/brightness", "1"); |
||||
writefile("/sys/class/leds/blue:indicator/brightness", "1"); |
||||
} else if (c == Off) { |
||||
writefile("/sys/class/leds/red:indicator/brightness", "0"); |
||||
writefile("/sys/class/leds/blue:indicator/brightness", "0"); |
||||
} |
||||
} |
||||
|
||||
int |
||||
presuspend() { |
||||
//called prior to suspension, a non-zero return value cancels suspension
|
||||
return system("sxmo_presuspend.sh"); |
||||
} |
||||
|
||||
void |
||||
postwake() { |
||||
//called after fully waking up (not used for temporary rtc wakeups)
|
||||
system("sxmo_postwake.sh"); |
||||
slept = 0; |
||||
} |
||||
|
||||
int |
||||
checkrtcwake() |
||||
{ |
||||
struct rtc_time now; |
||||
if (ioctl(rtc_fd, RTC_RD_TIME, &now) < 0) { |
||||
fprintf(stderr, "Error reading rtc time\n"); |
||||
return -1; |
||||
} |
||||
|
||||
const long int timediff = convert_rtc_time(&now) - waketime; |
||||
fprintf(stderr, "Checking rtc wake? timediff=%ld\n", timediff); |
||||
if (timediff >= 0 && timediff <= 3) { |
||||
fprintf(stderr, "Calling RTC wake script\n"); |
||||
setpineled(Blue); |
||||
return system("sxmo_rtcwake.sh"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
void |
||||
syncstate() |
||||
{ |
||||
int rtcresult; |
||||
if (state == StateSuspend) { |
||||
if (presuspend() != 0) { |
||||
state = StateDead; |
||||
} else { |
||||
fprintf(stderr, "Screenlock entering suspend state (pred mode)\n"); |
||||
writefile(brightnessfile, "0"); |
||||
blankscreen(); |
||||
slept = 1; |
||||
setpineled(Red); |
||||
configuresuspendsettingsandwakeupsources(); |
||||
writefile(powerstatefile, "mem"); |
||||
//---- program blocks here due to sleep ----- //
|
||||
// Just woke up again
|
||||
fprintf(stderr, "Screenlock woke up\n"); |
||||
fprintf(stderr, "Lower scan interval for quicker reconnection to wireless network\n"); |
||||
writefile("/sys/module/8723cs/parameters/rtw_scan_interval_thr", "1200"); //ms
|
||||
//^-- this will be undone again by a networkmanager hook after connection has been established
|
||||
// or by a delayed script if no connection can be established after a while (to conserve battery)
|
||||
fprintf(stderr, "Woke up\n"); |
||||
if (waketime > 0) { |
||||
rtcresult = checkrtcwake(); |
||||
} else { |
||||
rtcresult = 0; |
||||
} |
||||
if (rtcresult == 0) { |
||||
state = StateSuspendPending; |
||||
suspendpendingtimeouts = 0; |
||||
} else { |
||||
postwake(); |
||||
state = StateDead; |
||||
} |
||||
} |
||||
syncstate(); |
||||
} else if (state == StateNoInput) { |
||||
fprintf(stderr, "Screenlock in no Input state (blue mode)\n"); |
||||
setpineled(Blue); |
||||
unblankscreen(); |
||||
writefile(brightnessfile, oldbrightness); |
||||
} else if (state == StateNoInputNoScreen) { |
||||
fprintf(stderr, "Screenlock in no screen state (purple mode)\n"); |
||||
setpineled(Purple); |
||||
writefile(brightnessfile, "0"); |
||||
blankscreen(); |
||||
} else if (state == StateSuspendPending) { |
||||
fprintf(stderr, "Screenlock is pending suspension\n"); |
||||
if (suspendpendingsceenon) unblankscreen(); |
||||
writefile(brightnessfile, suspendpendingsceenon ? oldbrightness : "0"); |
||||
if (!suspendpendingsceenon) blankscreen(); |
||||
setpineled(Off); |
||||
usleep(1000 * 100); |
||||
setpineled(suspendpendingsceenon ? Blue : Purple); |
||||
} else if (state == StateDead) { |
||||
unblankscreen(); |
||||
writefile(brightnessfile, oldbrightness); |
||||
setpineled(Off); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
void |
||||
writefile(char *filepath, char *str) |
||||
{ |
||||
int f; |
||||
f = open(filepath, O_WRONLY); |
||||
if (f != -1) { |
||||
write(f, str, strlen(str)); |
||||
close(f); |
||||
} else { |
||||
fprintf(stderr, "Couldn't open filepath <%s>\n", filepath); |
||||
} |
||||
} |
||||
|
||||
void usage() { |
||||
fprintf(stderr, "Usage: sxmo_screenlock [--screen-off] [--suspend] [--wake-interval n] [--setuid]\n"); |
||||
} |
||||
|
||||
|
||||
void init_rtc() { |
||||
rtc_fd = open(RTC_DEVICE, O_RDONLY); |
||||
if (rtc_fd < 0) { |
||||
fprintf(stderr, "Error opening rtc device: %d\n", rtc_fd); |
||||
die("Unable to open rtc device"); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
} |
||||
|
||||
int |
||||
main(int argc, char **argv) { |
||||
int screen; |
||||
int i; |
||||
enum State target = StateNoInput; |
||||
|
||||
signal(SIGTERM, sigterm); |
||||
|
||||
const char* suspendtimeouts_str = getenv("SXMO_SUSPENDTIMEOUTS"); |
||||
if (suspendtimeouts_str != NULL) suspendtimeouts = atoi(suspendtimeouts_str); |
||||
|
||||
const char* rtcwakeinterval = getenv("SXMO_RTCWAKEINTERVAL"); |
||||
if (rtcwakeinterval != NULL) wakeinterval = atoi(rtcwakeinterval); |
||||
|
||||
const char* screen_off = getenv("SXMO_LOCK_SCREEN_OFF"); |
||||
if (screen_off != NULL && atoi(screen_off)) target = StateNoInputNoScreen; |
||||
|
||||
const char* suspend = getenv("SXMO_LOCK_SUSPEND"); |
||||
if (suspend != NULL && atoi(suspend)) target = StateSuspend; |
||||
|
||||
//parse command line arguments
|
||||
for (i = 1; i < argc; i++) { |
||||
if(!strcmp(argv[i], "-h")) { |
||||
usage(); |
||||
return 0; |
||||
} else if(!strcmp(argv[i], "--screen-off")) { |
||||
target = StateNoInputNoScreen; |
||||
} else if(!strcmp(argv[i], "--suspend")) { |
||||
target = StateSuspend; |
||||
} else if(!strcmp(argv[i], "--wake-interval")) { |
||||
wakeinterval = (time_t) atoi(argv[++i]); |
||||
} else if(!strcmp(argv[i], "--setuid")) { |
||||
if (setuid(0)) |
||||
die("setuid(0) failed"); |
||||
} else { |
||||
fprintf(stderr, "Invalid argument: %s\n", argv[i]); |
||||
return 2; |
||||
} |
||||
} |
||||
|
||||
if (!(dpy = XOpenDisplay(NULL))) |
||||
die("Cannot open display"); |
||||
|
||||
getoldbrightness(); |
||||
|
||||
if (wakeinterval) init_rtc(); |
||||
|
||||
fprintf(stderr, "Screenlock starting\n"); |
||||
|
||||
XkbSetDetectableAutoRepeat(dpy, True, NULL); |
||||
screen = XDefaultScreen(dpy); |
||||
XSync(dpy, 0); |
||||
syncstate(); |
||||
lockscreen(dpy, screen, target == StateNoInputNoScreen || target == StateSuspend); |
||||
if ((target == StateNoInputNoScreen) || (target == StateSuspend)) { |
||||
state = StateNoInputNoScreen; |
||||
syncstate(); |
||||
} |
||||
if (target == StateSuspend) { |
||||
state = StateSuspend; |
||||
syncstate(); |
||||
} |
||||
readinputloop(dpy, screen); |
||||
if (wakeinterval) { |
||||
ioctl(rtc_fd, RTC_AIE_OFF, 0); |
||||
close(rtc_fd); |
||||
} |
||||
fprintf(stderr, "Screenlock terminating normally\n"); |
||||
return 0; |
||||
} |
@ -1,11 +0,0 @@ |
||||
#!/bin/sh |
||||
|
||||
# this script resets the wireless scan interval (value is in ms) |
||||
# it is invoked with a delay after waking from sleep |
||||
# to prevent the scan interval from being too quick, and thus |
||||
# too battery consuming, whilst no networks are found |
||||
|
||||
# the kernel parameter must be writable for the user |
||||
# or this script must have the setsuid bit set! |
||||
|
||||
echo 16000 > /sys/module/8723cs/parameters/rtw_scan_interval_thr |
@ -0,0 +1,196 @@ |
||||
#!/usr/bin/env sh |
||||
|
||||
# include common definitions |
||||
# shellcheck source=scripts/core/sxmo_common.sh |
||||
. "$(dirname "$0")/sxmo_common.sh" |
||||
|
||||
# Run xinput and get touchscreen id |
||||
TOUCH_POINTER_ID="${TOUCH_POINTER_ID:-"8"}" |
||||
|
||||
REDLED_PATH="/sys/class/leds/red:indicator/brightness" |
||||
BLUELED_PATH="/sys/class/leds/blue:indicator/brightness" |
||||
|
||||
WAKEUPRTC="/sys/class/wakeup/wakeup1/active_count" |
||||
MODEMUPRTC="/sys/class/wakeup/wakeup10/active_count" |
||||
NETWORKRTCSCAN="/sys/module/8723cs/parameters/rtw_scan_interval_thr" |
||||
|
||||
OLD_RTC_WAKECOUNT="$XDG_RUNTIME_DIR/wakeup.rtc.count" |
||||
OLD_MODEM_WAKECOUNT="$XDG_RUNTIME_DIR/wakeup.modem.count" |
||||
|
||||
saveAllEventCounts() { |
||||
cat "$WAKEUPRTC" > "$OLD_RTC_WAKECOUNT" |
||||
cat "$MODEMUPRTC" > "$OLD_MODEM_WAKECOUNT" |
||||
# TODO: add logic for modem wakeup |
||||
} |
||||
|
||||
whichWake() { |
||||
if [ "$(cat $WAKEUPRTC)" -gt "$(cat $OLD_RTC_WAKECOUNT)" ] ; then |
||||
echo "rtc" |
||||
elif [ "$(cat $MODEMUPRTC)" -gt "$(cat $OLD_MODEM_WAKECOUNT)" ] ; then |
||||
echo "modem" |
||||
else |
||||
# button does not have a active count so if it's none of the above, it has to be the button |
||||
echo "button" |
||||
fi |
||||
} |
||||
|
||||
getCurState() { |
||||
if xinput list-props "$TOUCH_POINTER_ID" | grep "Device Enabled" | grep -q "0$"; then |
||||
if xset q | grep -q "Off: 3"; then |
||||
echo "off" |
||||
else |
||||
echo "lock" |
||||
fi |
||||
else |
||||
echo "unlock" |
||||
fi |
||||
} |
||||
|
||||
updateLed() { |
||||
case "$(getCurState)" in |
||||
"off") |
||||
echo 1 > "$REDLED_PATH" |
||||
echo 1 > "$BLUELED_PATH" |
||||
;; |
||||
"lock") |
||||
echo 0 > "$REDLED_PATH" |
||||
echo 1 > "$BLUELED_PATH" |
||||
;; |
||||
"unlock") |
||||
echo 0 > "$REDLED_PATH" |
||||
echo 0 > "$BLUELED_PATH" |
||||
;; |
||||
esac |
||||
} |
||||
|
||||
if [ "$1" = "lock" ] ; then |
||||
# always echo last state first so that user can use it in their hooks |
||||
# TODO: Document LASTSTATE |
||||
getCurState > "$LASTSTATE" |
||||
# Do we want this hook after disabling all the input devices so users can enable certain devices? |
||||
if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/lock" ]; then |
||||
"$XDG_CONFIG_HOME/sxmo/hooks/lock" |
||||
fi |
||||
|
||||
xset dpms 0 0 0 |
||||
xset dpms force on |
||||
|
||||
# TODO: Could be improved by running xinput and disabling ALL input devices automatically but would need |
||||
# to decide on the hook issues. Do we want a prelock and postlock? Or should users |
||||
# be expected to edit the source code for disabling certain input devices? |
||||
# this code allows us to not use the slock locking mechanism in the original sxmo_lock.sh |
||||
# when combined with a working slock (see ~iv's) implementation, this should be secure. |
||||
xinput disable "$TOUCH_POINTER_ID" |
||||
killall lisgd |
||||
|
||||
updateLed |
||||
exit 0 |
||||
elif [ "$1" = "unlock" ] ; then |
||||
getCurState > "$LASTSTATE" |
||||
if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/unlock" ]; then |
||||
"$XDG_CONFIG_HOME/sxmo/hooks/unlock" |
||||
fi |
||||
|
||||
xset dpms 0 0 0 |
||||
xset dpms force on |
||||
xinput enable "$TOUCH_POINTER_ID" |
||||
sxmo_lisgdstart.sh |
||||
|
||||
updateLed |
||||
exit 0 |
||||
elif [ "$1" = "off" ] ; then |
||||
getCurState > "$LASTSTATE" |
||||
# TODO: document this hook |
||||
if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/screenoff" ]; then |
||||
"$XDG_CONFIG_HOME/sxmo/hooks/screenoff" |
||||
fi |
||||
|
||||
xset dpms 0 0 3 |
||||
xset dpms force off |
||||
# stop responding to input |
||||
xinput disable "$TOUCH_POINTER_ID" |
||||
killall lisgd |
||||
|
||||
updateLed |
||||
exit 0 |
||||
elif [ "$1" = "crust" ] ; then |
||||
getCurState > "$LASTSTATE" |
||||
|
||||
if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/presuspend" ]; then |
||||
"$XDG_CONFIG_HOME/sxmo/hooks/presuspend" |
||||
fi |
||||
|
||||
echo 1 > "$REDLED_PATH" |
||||
echo 0 > "$BLUELED_PATH" |
||||
xset dpms force off |
||||
|
||||
# configure crust |
||||
# TODO: disable all wakeup sources other than button, rtc, and modem. |
||||
# TODO: make sure there is logic in whichWake and saveAllEventCounts functions |
||||
# Do I need to unbind? https://git.sr.ht/~mil/sxmo-utils/commit/bcf4f5c24968df0055d15a9fca649f67de9ced6a |
||||
echo "deep" > /sys/power/mem_sleep # deep sleep |
||||
|
||||
echo "mem" > /sys/power/state |
||||
|
||||
echo "crust" > "$LASTSTATE" |
||||
|
||||
updateLed |
||||
xset dpms force on |
||||
|
||||
# all we know is it's not the rtc. Maybe modem? |
||||
# TODO: Check mmcli or something or sxmo's notifs when |
||||
# https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/356 |
||||
# https://gitlab.com/postmarketOS/pmaports/-/merge_requests/2066 |
||||
# fixed |
||||
# TODO: Document UNSUSPENDREASONFILE |
||||
echo "nonrtc" > "$UNSUSPENDREASONFILE" |
||||
|
||||
if [ "$(whichWake)" = "button" ] && [ -x "$XDG_CONFIG_HOME/sxmo/hooks/postwake" ]; then |
||||
"$XDG_CONFIG_HOME/sxmo/hooks/postwake" |
||||
fi |
||||
|
||||
exit 0 |
||||
elif [ "$1" = "rtc" ] ; then |
||||
getCurState > "$LASTSTATE" |
||||
# USER MUST USE sxmo_screenlock.sh rtc rather than using rtcwake directly. |
||||
# With this new version of lock, we dont check the exit code of the user hook. User must execute "sxmo_screenlock.sh rtc $TIME" at the end of their hook (depending on whether they want to re-rtc) |
||||
echo 1 > "$REDLED_PATH" |
||||
echo 0 > "$BLUELED_PATH" |
||||
|
||||
saveAllEventCounts |
||||
|
||||
if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/presuspend" ]; then |
||||
"$XDG_CONFIG_HOME/sxmo/hooks/presuspend" |
||||
fi |
||||
|
||||
xset dpms force off |
||||
rtcwake -m mem -s "$2" |
||||
whichWake > "$UNSUSPENDREASONFILE" |
||||
|
||||
echo "crust" > "$LASTSTATE" |
||||
|
||||
updateLed |
||||
|
||||
if [ "$(whichWake)" = "rtc" ]; then |
||||
WAKEHOOK="$XDG_CONFIG_HOME/sxmo/hooks/rtcwake"; |
||||
elif [ "$(whichWake)" = "button" ]; then |
||||
WAKEHOOK="$XDG_CONFIG_HOME/sxmo/hooks/postwake"; |
||||
fi |
||||
|
||||
if [ "$(whichWake)" != "rtc" ]; then |
||||
xset dpms force on |
||||
fi |
||||
|
||||
if [ -x "$WAKEHOOK" ]; then |
||||
echo 1200 > "$NETWORKRTCSCAN" |
||||
"$WAKEHOOK" |
||||
echo 16000 > "$NETWORKRTCSCAN" |
||||
fi |
||||
exit 0 |
||||
elif [ "$1" = "getCurState" ] ; then |
||||
getCurState |
||||
exit 0 |
||||
fi |
||||
|
||||
|
||||
echo "usage: sxmo_screenlock.sh [lock|unlock|off|crust|rtc|getCurState]" |
Loading…
Reference in new issue