linuxOS_AP06/buildroot/package/input-event-daemon/power-key.sh
2025-06-03 12:28:32 +08:00

110 lines
1.9 KiB
Bash
Executable File

#!/bin/sh
EVENT=${1:-short-press}
LONG_PRESS_TIMEOUT=3 # s
DEBOUNCE=2 # s
PIDFILE="/tmp/$(basename $0).pid"
LOCKFILE=/tmp/.power_key
log()
{
logger -t $(basename $0) "[$$]: $@"
}
parse_wake_time()
{
RK_SUSPEND_STATE=/sys/kernel/wakeup_reasons/last_suspend_time
if ! [ -f "$RK_SUSPEND_STATE" ]; then
return -1
fi
SLEEP_TIME=$(sed 's/ /+/' "$RK_SUSPEND_STATE" | bc)
if [ "$SLEEP_TIME" = "0" ]; then
log "We have not slept before..."
return -1
fi
LAST_SUSPEND="$(stat -c "%Y" /sys/power/state)"
LAST_RESUME="$(echo "$LAST_SUSPEND+$SLEEP_TIME" | bc | cut -d'.' -f1)"
NOW="$(date "+%s")"
WAKE_TIME="$(( "$NOW" - "$LAST_RESUME" ))"
if [ "$WAKE_TIME" -lt 0 ]; then
log "Something is wrong, time changed?"
return -1
fi
log "Last resume: $(date -d "@$LAST_RESUME" "+%D %T")..."
}
short_press()
{
log "Power key short press..."
if which systemctl >/dev/null; then
SUSPEND_CMD="systemctl suspend"
elif which pm-suspend >/dev/null; then
SUSPEND_CMD="pm-suspend"
else
SUSPEND_CMD="echo -n mem > /sys/power/state"
fi
# Debounce
if [ -f $LOCKFILE ]; then
log "Too close to the latest request..."
return 0
fi
if parse_wake_time; then
if [ "$WAKE_TIME" -le $DEBOUNCE ]; then
log "We are just resumed!"
return 0
fi
fi
log "Prepare to suspend..."
touch $LOCKFILE
sh -c "$SUSPEND_CMD"
{ sleep $DEBOUNCE && rm $LOCKFILE; }&
}
long_press()
{
log "Power key long press (${LONG_PRESS_TIMEOUT}s)..."
log "Prepare to power off..."
poweroff
}
log "Received power key event: $@..."
case "$EVENT" in
press)
# Lock it
exec 3<$0
flock -x 3
start-stop-daemon -K -q -p $PIDFILE || true
start-stop-daemon -S -q -b -m -p $PIDFILE -x /bin/sh -- \
-c "sleep $LONG_PRESS_TIMEOUT; $0 long-press"
# Unlock
flock -u 3
;;
release)
# Avoid race with press event
sleep .5
start-stop-daemon -K -q -p $PIDFILE && short_press
;;
short-press)
short_press
;;
long-press)
long_press
;;
esac