mirror of
https://github.com/koreader/koreader
synced 2024-11-16 06:12:56 +00:00
Kindle: enable WakeupMgr & RTC support
This is acomplished through listening for the wakeupFromSuspend & readyToSuspend powerd events to set the RTC via lipc at the correct time.
This commit is contained in:
parent
30e499d4a9
commit
926223c192
2
base
2
base
@ -1 +1 @@
|
||||
Subproject commit 9b8e1fc44dc4c4b08891d55e48fbf28db1f77799
|
||||
Subproject commit d5b2e3798043630906251b99f9b79e1a59ab6099
|
@ -243,6 +243,8 @@ function Input:init()
|
||||
self.event_map[10011] = "UsbPlugOut"
|
||||
self.event_map[10020] = "Charging"
|
||||
self.event_map[10021] = "NotCharging"
|
||||
self.event_map[10030] = "WakeupFromSuspend"
|
||||
self.event_map[10031] = "ReadyToSuspend"
|
||||
|
||||
-- user custom event map
|
||||
local custom_event_map_location = string.format(
|
||||
@ -496,7 +498,8 @@ function Input:handleKeyBoardEv(ev)
|
||||
-- fake events
|
||||
if keycode == "IntoSS" or keycode == "OutOfSS"
|
||||
or keycode == "UsbPlugIn" or keycode == "UsbPlugOut"
|
||||
or keycode == "Charging" or keycode == "NotCharging" then
|
||||
or keycode == "Charging" or keycode == "NotCharging"
|
||||
or keycode == "WakeupFromSuspend" or keycode == "ReadyToSuspend" then
|
||||
return keycode
|
||||
end
|
||||
|
||||
@ -611,7 +614,8 @@ function Input:handlePowerManagementOnlyEv(ev)
|
||||
-- Fake events
|
||||
if keycode == "IntoSS" or keycode == "OutOfSS"
|
||||
or keycode == "UsbPlugIn" or keycode == "UsbPlugOut"
|
||||
or keycode == "Charging" or keycode == "NotCharging" then
|
||||
or keycode == "Charging" or keycode == "NotCharging"
|
||||
or keycode == "WakeupFromSuspend" or keycode == "ReadyToSuspend" then
|
||||
return keycode
|
||||
end
|
||||
|
||||
|
@ -275,6 +275,14 @@ function Kindle:usbPlugOut()
|
||||
self.charging_mode = false
|
||||
end
|
||||
|
||||
function Kindle:wakeupFromSuspend()
|
||||
self.powerd:wakeupFromSuspend()
|
||||
end
|
||||
|
||||
function Kindle:readyToSuspend()
|
||||
self.powerd:readyToSuspend()
|
||||
end
|
||||
|
||||
function Kindle:ambientBrightnessLevel()
|
||||
local haslipc, lipc = pcall(require, "liblipclua")
|
||||
if not haslipc or lipc == nil then return 0 end
|
||||
|
62
frontend/device/kindle/mockrtc.lua
Normal file
62
frontend/device/kindle/mockrtc.lua
Normal file
@ -0,0 +1,62 @@
|
||||
-- Mock RTC implementation backed by kindle's system powerd via lipc
|
||||
local MockRTC = {
|
||||
_wakeup_scheduled = false,
|
||||
_wakeup_scheduled_epoch = nil,
|
||||
}
|
||||
|
||||
-- This call always succeeds, errors will only happen at suspend time in
|
||||
-- powerd:setRtcWakeup()
|
||||
function MockRTC:setWakeupAlarm(epoch, enabled)
|
||||
enabled = (enabled ~= nil) and enabled or true
|
||||
if enabled then
|
||||
self._wakeup_scheduled = true
|
||||
self._wakeup_scheduled_epoch = epoch
|
||||
else
|
||||
self:unsetWakeupAlarm()
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function MockRTC:unsetWakeupAlarm()
|
||||
self._wakeup_scheduled = false
|
||||
self._wakeup_scheduled_epoch = nil
|
||||
end
|
||||
|
||||
function MockRTC:getWakeupAlarmEpoch()
|
||||
return self._wakeup_scheduled_epoch
|
||||
end
|
||||
|
||||
--[[--
|
||||
Checks if the alarm we set matches the current time.
|
||||
--]]
|
||||
function MockRTC:validateWakeupAlarmByProximity(task_alarm, proximity)
|
||||
-- In principle alarm time and current time should match within a second,
|
||||
-- but let's be absurdly generous and assume anything within 30 is a match.
|
||||
-- In practice, suspend() schedules check_unexpected_wakeup 15s *after*
|
||||
-- the actual wakeup, so we need to account for at least that much ;).
|
||||
proximity = proximity or 30
|
||||
|
||||
-- We want everything in UTC time_t (i.e. a Posix epoch).
|
||||
local now = os.time()
|
||||
local alarm = self:getWakeupAlarmEpoch()
|
||||
if not (alarm and task_alarm) then return end
|
||||
|
||||
-- Everything's in UTC, ask Lua to convert that to a human-readable format in the local timezone
|
||||
print("validateWakeupAlarmByProximity:",
|
||||
"\ntask @ " .. task_alarm .. os.date(" (%F %T %z)", task_alarm),
|
||||
"\nlast set alarm @ " .. alarm .. os.date(" (%F %T %z)", alarm),
|
||||
"\ncurrent time is " .. now .. os.date(" (%F %T %z)", now))
|
||||
|
||||
-- If our stored alarm and the provided task alarm don't match,
|
||||
-- we're not talking about the same task.
|
||||
if task_alarm and alarm ~= task_alarm then return end
|
||||
|
||||
local diff = now - alarm
|
||||
if diff >= 0 and diff < proximity then return true end
|
||||
end
|
||||
|
||||
function MockRTC:isWakeupAlarmScheduled()
|
||||
return self._wakeup_scheduled
|
||||
end
|
||||
|
||||
return MockRTC
|
@ -1,4 +1,6 @@
|
||||
local BasePowerD = require("device/generic/powerd")
|
||||
local WakeupMgr = require("device/wakeupmgr")
|
||||
local logger = require("logger")
|
||||
-- liblipclua, see require below
|
||||
|
||||
local KindlePowerD = BasePowerD:new{
|
||||
@ -19,6 +21,8 @@ function KindlePowerD:init()
|
||||
if not self.device:canTurnFrontlightOff() then
|
||||
self.fl_max = self.fl_max + 1
|
||||
end
|
||||
|
||||
self:initWakeupMgr()
|
||||
end
|
||||
|
||||
-- If we start with the light off (fl_intensity is fl_min), ensure a toggle will set it to the lowest "on" step,
|
||||
@ -186,6 +190,71 @@ function KindlePowerD:toggleSuspend()
|
||||
end
|
||||
end
|
||||
|
||||
-- Kindle only allows setting the RTC via lipc during the ReadyToSuspend state
|
||||
function KindlePowerD:setRtcWakeup(seconds_from_now)
|
||||
if self.lipc_handle then
|
||||
self.lipc_handle:set_int_property("com.lab126.powerd", "rtcWakeup", seconds_from_now)
|
||||
end
|
||||
end
|
||||
|
||||
-- Check the powerd state: are we still in screensaver mode.
|
||||
function KindlePowerD:getPowerdState()
|
||||
if self.lipc_handle then
|
||||
return self.lipc_handle:get_string_property("com.lab126.powerd", "state")
|
||||
end
|
||||
end
|
||||
|
||||
function KindlePowerD:checkUnexpectedWakeup()
|
||||
local state = self:getPowerdState()
|
||||
logger.info("Powerd resume state:", state)
|
||||
-- If we moved on to the active state,
|
||||
-- then we were woken by user input not our alarm.
|
||||
if state ~= "screenSaver" and state ~= "suspended" then return end
|
||||
|
||||
if self.device.wakeup_mgr:isWakeupAlarmScheduled() and self.device.wakeup_mgr:wakeupAction() then
|
||||
logger.info("Kindle scheduled wakeup")
|
||||
else
|
||||
logger.info("Kindle unscheduled wakeup")
|
||||
end
|
||||
end
|
||||
|
||||
-- Dummy fuctions. They will be defined in initWakeupMgr
|
||||
function KindlePowerD:wakeupFromSuspend() end
|
||||
function KindlePowerD:readyToSuspend() end
|
||||
|
||||
-- Support WakeupMgr on Lipc & supportsScreensaver devices.
|
||||
function KindlePowerD:initWakeupMgr()
|
||||
if not self.device:supportsScreensaver() then return end
|
||||
if self.lipc_handle == nil then return end
|
||||
|
||||
function KindlePowerD:wakeupFromSuspend()
|
||||
logger.info("Kindle wakeupFromSuspend")
|
||||
-- Give the device a few seconds to settle.
|
||||
-- This filters out user input resumes -> device will resume to active
|
||||
-- Also the Kindle stays in Ready to suspend for 10 seconds
|
||||
-- so the alarm may fire 10 seconds early
|
||||
local UIManager = require("ui/uimanager")
|
||||
UIManager:scheduleIn(15, self.checkUnexpectedWakeup, self)
|
||||
end
|
||||
|
||||
function KindlePowerD:readyToSuspend()
|
||||
logger.info("Kindle readyToSuspend")
|
||||
if self.device.wakeup_mgr:isWakeupAlarmScheduled() then
|
||||
local now = os.time()
|
||||
local alarm = self.device.wakeup_mgr:getWakeupAlarmEpoch()
|
||||
if alarm > now then
|
||||
-- Powerd / Lipc need seconds_from_now not epoch
|
||||
self:setRtcWakeup(alarm - now)
|
||||
else
|
||||
-- wakeup time is in the past
|
||||
self.device.wakeup_mgr:removeTasks(alarm)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.device.wakeup_mgr = WakeupMgr:new{rtc = require("device/kindle/mockrtc")}
|
||||
end
|
||||
|
||||
--- @fixme: This won't ever fire, as KindlePowerD is already a metatable on a plain table.
|
||||
function KindlePowerD:__gc()
|
||||
if self.lipc_handle then
|
||||
|
@ -22,6 +22,7 @@ WakeupMgr base class.
|
||||
local WakeupMgr = {
|
||||
dev_rtc = "/dev/rtc0", -- RTC device
|
||||
_task_queue = {}, -- Table with epoch at which to schedule the task and the function to be scheduled.
|
||||
rtc = RTC, -- The RTC implementation to use, defaults to the RTC module.
|
||||
}
|
||||
|
||||
--[[--
|
||||
@ -169,7 +170,7 @@ Set wakeup alarm.
|
||||
Simple wrapper for @{ffi.rtc.setWakeupAlarm}.
|
||||
--]]
|
||||
function WakeupMgr:setWakeupAlarm(epoch, enabled)
|
||||
return RTC:setWakeupAlarm(epoch, enabled)
|
||||
return self.rtc:setWakeupAlarm(epoch, enabled)
|
||||
end
|
||||
|
||||
--[[--
|
||||
@ -178,7 +179,7 @@ Unset wakeup alarm.
|
||||
Simple wrapper for @{ffi.rtc.unsetWakeupAlarm}.
|
||||
--]]
|
||||
function WakeupMgr:unsetWakeupAlarm()
|
||||
return RTC:unsetWakeupAlarm()
|
||||
return self.rtc:unsetWakeupAlarm()
|
||||
end
|
||||
|
||||
--[[--
|
||||
@ -187,13 +188,22 @@ Get wakealarm as set by us.
|
||||
Simple wrapper for @{ffi.rtc.getWakeupAlarm}.
|
||||
--]]
|
||||
function WakeupMgr:getWakeupAlarm()
|
||||
return RTC:getWakeupAlarm()
|
||||
return self.rtc:getWakeupAlarm()
|
||||
end
|
||||
|
||||
--[[--
|
||||
Get wakealarm epoch as set by us.
|
||||
|
||||
Simple wrapper for @{ffi.rtc.getWakeupAlarmEpoch}.
|
||||
--]]
|
||||
function WakeupMgr:getWakeupAlarmEpoch()
|
||||
return self.rtc:getWakeupAlarmEpoch()
|
||||
end
|
||||
|
||||
--[[--
|
||||
Get RTC wakealarm from system.
|
||||
|
||||
Simple wrapper for @{ffi.rtc.getWakeupAlarm}.
|
||||
Simple wrapper for @{ffi.rtc.getWakeupAlarmSys}.
|
||||
--]]
|
||||
function WakeupMgr:getWakeupAlarmSys()
|
||||
return RTC:getWakeupAlarmSys()
|
||||
@ -207,7 +217,7 @@ Checks if we set the alarm.
|
||||
Simple wrapper for @{ffi.rtc.validateWakeupAlarmByProximity}.
|
||||
--]]
|
||||
function WakeupMgr:validateWakeupAlarmByProximity(task_alarm_epoch, proximity)
|
||||
return RTC:validateWakeupAlarmByProximity(task_alarm_epoch, proximity)
|
||||
return self.rtc:validateWakeupAlarmByProximity(task_alarm_epoch, proximity)
|
||||
end
|
||||
|
||||
--[[--
|
||||
@ -216,10 +226,10 @@ Check if a wakeup is scheduled.
|
||||
Simple wrapper for @{ffi.rtc.isWakeupAlarmScheduled}.
|
||||
--]]
|
||||
function WakeupMgr:isWakeupAlarmScheduled()
|
||||
local wakeup_scheduled = RTC:isWakeupAlarmScheduled()
|
||||
local wakeup_scheduled = self.rtc:isWakeupAlarmScheduled()
|
||||
if wakeup_scheduled then
|
||||
-- NOTE: This can't return nil given that we're behind an isWakeupAlarmScheduled check.
|
||||
local alarm = RTC:getWakeupAlarmEpoch()
|
||||
local alarm = self.rtc:getWakeupAlarmEpoch()
|
||||
logger.dbg("WakeupMgr:isWakeupAlarmScheduled: An alarm is scheduled for " .. alarm .. os.date(" (%F %T %z)", alarm))
|
||||
else
|
||||
logger.dbg("WakeupMgr:isWakeupAlarmScheduled: No alarm is currently scheduled.")
|
||||
|
@ -239,6 +239,12 @@ function UIManager:init()
|
||||
Device:usbPlugOut()
|
||||
self:_afterNotCharging()
|
||||
end
|
||||
self.event_handlers["WakeupFromSuspend"] = function()
|
||||
Device:wakeupFromSuspend()
|
||||
end
|
||||
self.event_handlers["ReadyToSuspend"] = function()
|
||||
Device:readyToSuspend()
|
||||
end
|
||||
elseif Device:isRemarkable() then
|
||||
self.event_handlers["Suspend"] = function()
|
||||
self:_beforeSuspend()
|
||||
|
Loading…
Reference in New Issue
Block a user