mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Noticeable latency between toggling the power switch and the device showing the screensaver has been tracked down to the two network manager calls. This change allows the screen to be updated first. Note that unloading the open source brcmfmac driver used on okreader is slower than unloading the proprietary driver shipped by Kobo, making this delay even more noticeable. self.suspend() is scheduled after the network manager calls to avoid race conditions.
207 lines
7.0 KiB
Lua
207 lines
7.0 KiB
Lua
local Event = require("ui/event")
|
|
local logger = require("logger")
|
|
local _ = require("gettext")
|
|
|
|
local function yes() return true end
|
|
local function no() return false end
|
|
|
|
local Device = {
|
|
screen_saver_mode = false,
|
|
charging_mode = false,
|
|
survive_screen_saver = false,
|
|
is_cover_closed = false,
|
|
model = nil,
|
|
powerd = nil,
|
|
screen = nil,
|
|
input = nil,
|
|
-- For Kobo, wait at least 15 seconds before calling suspend script. Otherwise, suspend might
|
|
-- fail and the battery will be drained while we are in screensaver mode
|
|
suspend_wait_timeout = 15,
|
|
|
|
-- hardware feature tests: (these are functions!)
|
|
hasKeyboard = no,
|
|
hasKeys = no,
|
|
hasDPad = no,
|
|
isTouchDevice = no,
|
|
hasFrontlight = no,
|
|
needsTouchScreenProbe = no,
|
|
|
|
-- use these only as a last resort. We should abstract the functionality
|
|
-- and have device dependent implementations in the corresponting
|
|
-- device/<devicetype>/device.lua file
|
|
-- (these are functions!)
|
|
isKindle = no,
|
|
isKobo = no,
|
|
isPocketBook = no,
|
|
isAndroid = no,
|
|
isSDL = no,
|
|
|
|
-- some devices have part of their screen covered by the bezel
|
|
viewport = nil,
|
|
-- enforce portrait orientation on display, no matter how configured at
|
|
-- startup
|
|
isAlwaysPortrait = no,
|
|
-- needs full screen refresh when resumed from screensaver?
|
|
needsScreenRefreshAfterResume = yes,
|
|
}
|
|
|
|
function Device:new(o)
|
|
o = o or {}
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
return o
|
|
end
|
|
|
|
function Device:init()
|
|
if not self.screen then
|
|
error("screen/framebuffer must be implemented")
|
|
end
|
|
|
|
local is_eink = G_reader_settings:readSetting("eink")
|
|
self.screen.eink = (is_eink == nil) or is_eink
|
|
|
|
logger.info("initializing for device", self.model)
|
|
logger.info("framebuffer resolution:", self.screen:getSize())
|
|
|
|
if not self.input then
|
|
self.input = require("device/input"):new{device = self}
|
|
end
|
|
if not self.powerd then
|
|
self.powerd = require("device/generic/powerd"):new{device = self}
|
|
end
|
|
|
|
if self.viewport then
|
|
logger.dbg("setting a viewport:", self.viewport)
|
|
self.screen:setViewport(self.viewport)
|
|
self.input:registerEventAdjustHook(
|
|
self.input.adjustTouchTranslate,
|
|
{x = 0 - self.viewport.x, y = 0 - self.viewport.y})
|
|
end
|
|
end
|
|
|
|
function Device:getPowerDevice()
|
|
return self.powerd
|
|
end
|
|
|
|
function Device:rescheduleSuspend()
|
|
local UIManager = require("ui/uimanager")
|
|
UIManager:unschedule(self.suspend)
|
|
UIManager:scheduleIn(self.suspend_wait_timeout, self.suspend)
|
|
end
|
|
|
|
-- ONLY used for Kobo and PocketBook devices
|
|
function Device:onPowerEvent(ev)
|
|
if self.screen_saver_mode then
|
|
if ev == "Power" or ev == "Resume" then
|
|
if self.is_cover_closed then
|
|
-- don't let power key press wake up device when the cover is in closed state
|
|
self:rescheduleSuspend()
|
|
else
|
|
logger.dbg("Resuming...")
|
|
local UIManager = require("ui/uimanager")
|
|
UIManager:unschedule(self.suspend)
|
|
local network_manager = require("ui/network/manager")
|
|
if network_manager.wifi_was_on and G_reader_settings:nilOrTrue("auto_restore_wifi") then
|
|
network_manager:restoreWifiAsync()
|
|
end
|
|
self:resume()
|
|
require("ui/screensaver"):close()
|
|
-- restore to previous rotation mode
|
|
self.screen:setRotationMode(self.orig_rotation_mode)
|
|
if self:needsScreenRefreshAfterResume() then
|
|
UIManager:scheduleIn(1, function() self.screen:refreshFull() end)
|
|
end
|
|
self.screen_saver_mode = false
|
|
self.powerd:afterResume()
|
|
end
|
|
elseif ev == "Suspend" then
|
|
-- Already in screen saver mode, no need to update UI/state before
|
|
-- suspending the hardware. This usually happens when sleep cover
|
|
-- is closed after the device was sent to suspend state.
|
|
logger.dbg("Already in screen saver mode, suspending...")
|
|
self:rescheduleSuspend()
|
|
end
|
|
-- else we we not in screensaver mode
|
|
elseif ev == "Power" or ev == "Suspend" then
|
|
self.powerd:beforeSuspend()
|
|
local UIManager = require("ui/uimanager")
|
|
-- flushing settings first in case the screensaver takes too long time
|
|
-- that flushing has no chance to run
|
|
UIManager:broadcastEvent(Event:new("FlushSettings"))
|
|
logger.dbg("Suspending...")
|
|
-- always suspend in portrait mode
|
|
self.orig_rotation_mode = self.screen:getRotationMode()
|
|
self.screen:setRotationMode(0)
|
|
require("ui/screensaver"):show("suspend", _("Sleeping"))
|
|
self.screen:refreshFull()
|
|
self.screen_saver_mode = true
|
|
UIManager:scheduleIn(0.1, function()
|
|
local network_manager = require("ui/network/manager")
|
|
if network_manager.wifi_was_on then
|
|
network_manager:releaseIP()
|
|
network_manager:turnOffWifi()
|
|
end
|
|
UIManager:scheduleIn(self.suspend_wait_timeout, self.suspend)
|
|
end)
|
|
end
|
|
end
|
|
|
|
-- Hardware specific method to handle usb plug in event
|
|
function Device:usbPlugIn() end
|
|
|
|
-- Hardware specific method to handle usb plug out event
|
|
function Device:usbPlugOut() end
|
|
|
|
-- Hardware specific method to suspend the device
|
|
function Device:suspend() end
|
|
|
|
-- Hardware specific method to resume the device
|
|
function Device:resume() end
|
|
|
|
-- Hardware specific method to power off the device
|
|
function Device:powerOff() end
|
|
|
|
-- Hardware specific method to initialize network manager module
|
|
function Device:initNetworkManager() end
|
|
|
|
--[[
|
|
prepare for application shutdown
|
|
--]]
|
|
function Device:exit()
|
|
require("ffi/input"):closeAll()
|
|
self.screen:close()
|
|
end
|
|
|
|
function Device:retrieveNetworkInfo()
|
|
local std_out = io.popen("ifconfig | " ..
|
|
"sed -n " ..
|
|
"-e 's/ \\+$//g' " ..
|
|
"-e 's/ \\+/ /g' " ..
|
|
"-e 's/ \\?inet6\\? addr: \\?\\([^ ]\\+\\) .*$/IP: \\1/p' " ..
|
|
"-e 's/Link encap:Ethernet\\(.*\\)/\\1/p'",
|
|
"r")
|
|
if std_out then
|
|
local result = std_out:read("*all")
|
|
std_out:close()
|
|
std_out = io.popen('iwconfig eth0 | grep ESSID | cut -d\\" -f2')
|
|
if std_out then
|
|
local ssid = std_out:read("*all")
|
|
result = result .. "SSID: " .. ssid:gsub("(.-)%s*$", "%1") .. "\n"
|
|
std_out:close()
|
|
end
|
|
if os.execute("ip r | grep -q default") == 0 then
|
|
local pingok = os.execute("ping -q -w 3 -c 2 `ip r | grep default | cut -d ' ' -f 3` > /dev/null")
|
|
if pingok == 0 then
|
|
result = result .. "Gateway ping successful"
|
|
else
|
|
result = result .. "Gateway ping FAILED"
|
|
end
|
|
else
|
|
result = result .. "No default gateway to ping"
|
|
end
|
|
return result
|
|
end
|
|
end
|
|
|
|
return Device
|