mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
Kindle: toggle cover events
Allow disabling the hall efect sensor via the sysfs knob, so the kindle system wont sleep & wake the device for those of use that stay in koreader, are caseless and have get spurious wakeups
This commit is contained in:
@@ -726,6 +726,7 @@ function KindlePaperWhite2:init()
|
||||
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",
|
||||
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
|
||||
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging",
|
||||
hall_file = "/sys/devices/system/wario_hall/wario_hall0/hall_enable",
|
||||
}
|
||||
|
||||
Kindle.init(self)
|
||||
@@ -740,6 +741,7 @@ function KindleBasic:init()
|
||||
device = self,
|
||||
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
|
||||
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging",
|
||||
hall_file = "/sys/devices/system/wario_hall/wario_hall0/hall_enable",
|
||||
}
|
||||
|
||||
Kindle.init(self)
|
||||
@@ -755,6 +757,7 @@ function KindleVoyage:init()
|
||||
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",
|
||||
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
|
||||
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging",
|
||||
hall_file = "/sys/devices/system/wario_hall/wario_hall0/hall_enable",
|
||||
}
|
||||
self.input = require("device/input"):new{
|
||||
device = self,
|
||||
@@ -814,6 +817,7 @@ function KindlePaperWhite3:init()
|
||||
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",
|
||||
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
|
||||
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging",
|
||||
hall_file = "/sys/devices/system/wario_hall/wario_hall0/hall_enable",
|
||||
}
|
||||
|
||||
Kindle.init(self)
|
||||
@@ -870,6 +874,7 @@ function KindleOasis:init()
|
||||
-- NOTE: Points to the embedded battery. The one in the cover is codenamed "soda".
|
||||
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
|
||||
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging",
|
||||
hall_file = "/sys/devices/system/wario_hall/wario_hall0/hall_enable",
|
||||
}
|
||||
|
||||
self.input = require("device/input"):new{
|
||||
@@ -1130,6 +1135,7 @@ function KindleBasic2:init()
|
||||
batt_capacity_file = "/sys/class/power_supply/bd7181x_bat/capacity",
|
||||
is_charging_file = "/sys/class/power_supply/bd7181x_bat/charging",
|
||||
batt_status_file = "/sys/class/power_supply/bd7181x_bat/status",
|
||||
hall_file = "/sys/devices/system/heisenberg_hall/heisenberg_hall0/hall_enable",
|
||||
}
|
||||
|
||||
Kindle.init(self)
|
||||
@@ -1146,6 +1152,7 @@ function KindlePaperWhite4:init()
|
||||
batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity",
|
||||
is_charging_file = "/sys/class/power_supply/bd71827_bat/charging",
|
||||
batt_status_file = "/sys/class/power_supply/bd71827_bat/status",
|
||||
hall_file = "/sys/bus/platform/drivers/hall_sensor/rex_hall/hall_enable",
|
||||
}
|
||||
|
||||
Kindle.init(self)
|
||||
@@ -1172,6 +1179,7 @@ function KindleBasic3:init()
|
||||
batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity",
|
||||
is_charging_file = "/sys/class/power_supply/bd71827_bat/charging",
|
||||
batt_status_file = "/sys/class/power_supply/bd71827_bat/status",
|
||||
hall_file = "/sys/bus/platform/drivers/hall_sensor/rex_hall/hall_enable",
|
||||
}
|
||||
|
||||
Kindle.init(self)
|
||||
@@ -1193,6 +1201,7 @@ function KindlePaperWhite5:init()
|
||||
batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity",
|
||||
is_charging_file = "/sys/class/power_supply/bd71827_bat/charging",
|
||||
batt_status_file = "/sys/class/power_supply/bd71827_bat/status",
|
||||
hall_file = "/sys/devices/platform/eink_hall/hall_enable",
|
||||
}
|
||||
|
||||
-- Enable the so-called "fast" mode, so as to prevent the driver from silently promoting refreshes to REAGL.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local BasePowerD = require("device/generic/powerd")
|
||||
local WakeupMgr = require("device/wakeupmgr")
|
||||
local logger = require("logger")
|
||||
local util = require("util")
|
||||
-- liblipclua, see require below
|
||||
|
||||
local KindlePowerD = BasePowerD:new{
|
||||
@@ -98,11 +99,12 @@ function KindlePowerD:setIntensityHW(intensity)
|
||||
-- NOTE: when intensity is 0, we want to *really* kill the light, so do it manually
|
||||
-- (asking lipc to set it to 0 would in fact set it to > 0 on ! canTurnFrontlightOff Kindles).
|
||||
-- We do *both* to make the fl restore on resume less jarring on devices where lipc 0 != off.
|
||||
os.execute("printf '%s' ".. intensity .." > " .. self.fl_intensity_file)
|
||||
util.writeToSysfs(intensity, self.fl_intensity_file)
|
||||
|
||||
-- And in case there are two LED groups...
|
||||
-- This should never happen as all warmth devices so far canTurnFrontlightOff
|
||||
if self.warmth_intensity_file then
|
||||
os.execute("printf '%s' ".. intensity .." > " .. self.warmth_intensity_file)
|
||||
util.writeToSysfs(intensity, self.warmth_intensity_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -161,6 +163,20 @@ function KindlePowerD:isChargedHW()
|
||||
return false
|
||||
end
|
||||
|
||||
function KindlePowerD:hasHallSensor()
|
||||
return self.hall_file ~= nil
|
||||
end
|
||||
|
||||
function KindlePowerD:isHallSensorEnabled()
|
||||
local int = self:read_int_file(self.hall_file)
|
||||
return int == 1
|
||||
end
|
||||
|
||||
function KindlePowerD:onToggleHallSensor()
|
||||
local stat = self:isHallSensorEnabled()
|
||||
util.writeToSysfs(stat and 0 or 1, self.hall_file)
|
||||
end
|
||||
|
||||
function KindlePowerD:_readFLIntensity()
|
||||
return self:read_int_file(self.fl_intensity_file)
|
||||
end
|
||||
|
||||
@@ -47,25 +47,6 @@ local function checkStandby()
|
||||
return no
|
||||
end
|
||||
|
||||
local function writeToSys(val, file)
|
||||
-- NOTE: We do things by hand via ffi, because io.write uses fwrite,
|
||||
-- which isn't a great fit for procfs/sysfs (e.g., we lose failure cases like EBUSY,
|
||||
-- as it only reports failures to write to the *stream*, not to the disk/file!).
|
||||
local fd = C.open(file, bit.bor(C.O_WRONLY, C.O_CLOEXEC)) -- procfs/sysfs, we shouldn't need O_TRUNC
|
||||
if fd == -1 then
|
||||
logger.err("Cannot open file `" .. file .. "`:", ffi.string(C.strerror(ffi.errno())))
|
||||
return
|
||||
end
|
||||
local bytes = #val
|
||||
local nw = C.write(fd, val, bytes)
|
||||
if nw == -1 then
|
||||
logger.err("Cannot write `" .. val .. "` to file `" .. file .. "`:", ffi.string(C.strerror(ffi.errno())))
|
||||
end
|
||||
C.close(fd)
|
||||
-- NOTE: Allows the caller to possibly handle short writes (not that these should ever happen here).
|
||||
return nw == bytes
|
||||
end
|
||||
|
||||
-- Return the highest core number
|
||||
local function getCPUCount()
|
||||
local fd = io.open("/sys/devices/system/cpu/possible", "re")
|
||||
@@ -1064,7 +1045,7 @@ function Kobo:standby(max_duration)
|
||||
logger.dbg("Kobo standby: asking to enter standby . . .")
|
||||
local standby_time = time.boottime_or_realtime_coarse()
|
||||
|
||||
local ret = writeToSys("standby", "/sys/power/state")
|
||||
local ret = util.writeToSysfs("standby", "/sys/power/state")
|
||||
|
||||
self.last_standby_time = time.boottime_or_realtime_coarse() - standby_time
|
||||
self.total_standby_time = self.total_standby_time + self.last_standby_time
|
||||
@@ -1140,7 +1121,7 @@ function Kobo:suspend()
|
||||
-- NOTE: Sets gSleep_Mode_Suspend to 1. Used as a flag throughout the
|
||||
-- kernel to suspend/resume various subsystems
|
||||
-- c.f., state_extended_store @ kernel/power/main.c
|
||||
local ret = writeToSys("1", "/sys/power/state-extended")
|
||||
local ret = util.writeToSysfs("1", "/sys/power/state-extended")
|
||||
if ret then
|
||||
logger.dbg("Kobo suspend: successfully asked the kernel to put subsystems to sleep")
|
||||
else
|
||||
@@ -1174,7 +1155,7 @@ function Kobo:suspend()
|
||||
logger.dbg("Kobo suspend: asking for a suspend to RAM . . .")
|
||||
local suspend_time = time.boottime_or_realtime_coarse()
|
||||
|
||||
ret = writeToSys("mem", "/sys/power/state")
|
||||
ret = util.writeToSysfs("mem", "/sys/power/state")
|
||||
|
||||
-- NOTE: At this point, we *should* be in suspend to RAM, as such,
|
||||
-- execution should only resume on wakeup...
|
||||
@@ -1189,7 +1170,7 @@ function Kobo:suspend()
|
||||
else
|
||||
logger.warn("Kobo suspend: the kernel refused to enter suspend!")
|
||||
-- Reset state-extended back to 0 since we are giving up.
|
||||
writeToSys("0", "/sys/power/state-extended")
|
||||
util.writeToSysfs("0", "/sys/power/state-extended")
|
||||
if G_reader_settings:isTrue("pm_debug_entry_failure") then
|
||||
self:toggleChargingLED(true)
|
||||
end
|
||||
@@ -1238,7 +1219,7 @@ function Kobo:resume()
|
||||
-- kernel to suspend/resume various subsystems
|
||||
-- cf. kernel/power/main.c @ L#207
|
||||
-- Among other things, this sets up the wakeup pins (e.g., resume on input).
|
||||
local ret = writeToSys("0", "/sys/power/state-extended")
|
||||
local ret = util.writeToSysfs("0", "/sys/power/state-extended")
|
||||
if ret then
|
||||
logger.dbg("Kobo resume: successfully asked the kernel to resume subsystems")
|
||||
else
|
||||
@@ -1254,7 +1235,7 @@ function Kobo:resume()
|
||||
-- c.f., neo_ctl @ drivers/input/touchscreen/zforce_i2c.c,
|
||||
-- basically, a is wakeup (for activate), d is sleep (for deactivate), and we don't care about s (set res),
|
||||
-- and l (led signal level, actually a NOP on NTX kernels).
|
||||
writeToSys("a", self.hasIRGridSysfsKnob)
|
||||
util.writeToSysfs("a", self.hasIRGridSysfsKnob)
|
||||
end
|
||||
|
||||
-- A full suspend may have toggled the LED off.
|
||||
@@ -1367,16 +1348,16 @@ function Kobo:enableCPUCores(amount)
|
||||
up = "1"
|
||||
end
|
||||
|
||||
writeToSys(up, path)
|
||||
util.writeToSysfs(up, path)
|
||||
end
|
||||
end
|
||||
|
||||
function Kobo:performanceCPUGovernor()
|
||||
writeToSys("performance", self.cpu_governor_knob)
|
||||
util.writeToSysfs("performance", self.cpu_governor_knob)
|
||||
end
|
||||
|
||||
function Kobo:defaultCPUGovernor()
|
||||
writeToSys(self.default_cpu_governor, self.cpu_governor_knob)
|
||||
util.writeToSysfs(self.default_cpu_governor, self.cpu_governor_knob)
|
||||
end
|
||||
|
||||
function Kobo:isStartupScriptUpToDate()
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
-- This also supports the natural light, which consists of additional
|
||||
-- red and green light LEDs.
|
||||
|
||||
local logger = require("logger")
|
||||
local dbg = require("dbg")
|
||||
|
||||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
require("ffi/posix_h")
|
||||
local util = require("util")
|
||||
|
||||
local SysfsLight = {
|
||||
frontlight_white = nil,
|
||||
@@ -77,15 +73,15 @@ function SysfsLight:setNaturalBrightness(brightness, warmth)
|
||||
if self.frontlight_ioctl then
|
||||
self.frontlight_ioctl:setBrightness(brightness)
|
||||
else
|
||||
self:_write_value(self.frontlight_white, brightness)
|
||||
util.writeToSysfs(brightness, self.frontlight_white)
|
||||
end
|
||||
end
|
||||
-- The mixer might be using inverted values... (cold is nl_max, warm is nl_min)
|
||||
if set_warmth then
|
||||
if self.nl_inverted then
|
||||
self:_write_value(self.frontlight_mixer, self.nl_max - warmth)
|
||||
util.writeToSysfs(self.nl_max - warmth, self.frontlight_mixer)
|
||||
else
|
||||
self:_write_value(self.frontlight_mixer, warmth)
|
||||
util.writeToSysfs(warmth, self.frontlight_mixer)
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -128,30 +124,11 @@ function SysfsLight:_set_light_value(sysfs_directory, value)
|
||||
if not sysfs_directory then return end
|
||||
-- bl_power is '31' when the light is turned on, '0' otherwise.
|
||||
if (value > 0) then
|
||||
self:_write_value(sysfs_directory .. "/bl_power", 31)
|
||||
util.writeToSysfs(31, sysfs_directory .. "/bl_power")
|
||||
else
|
||||
self:_write_value(sysfs_directory .. "/bl_power", 0)
|
||||
util.writeToSysfs(0, sysfs_directory .. "/bl_power")
|
||||
end
|
||||
self:_write_value(sysfs_directory .. "/brightness", value)
|
||||
end
|
||||
|
||||
function SysfsLight:_write_value(file, val)
|
||||
local fd = C.open(file, bit.bor(C.O_WRONLY, C.O_CLOEXEC)) -- procfs/sysfs, we shouldn't need O_TRUNC
|
||||
if fd == -1 then
|
||||
logger.err("Cannot open file `" .. file .. "`:", ffi.string(C.strerror(ffi.errno())))
|
||||
return false
|
||||
end
|
||||
val = tostring(val)
|
||||
local bytes = #val
|
||||
local nw = C.write(fd, val, bytes)
|
||||
if nw == -1 then
|
||||
logger.err("Cannot write `" .. val .. "` to file `" .. file .. "`:", ffi.string(C.strerror(ffi.errno())))
|
||||
C.close(fd)
|
||||
return false
|
||||
end
|
||||
C.close(fd)
|
||||
-- NOTE: Allows the caller to possibly handle short writes (not that these should ever happen here).
|
||||
return nw == bytes
|
||||
util.writeToSysfs(value, sysfs_directory .. "/brightness")
|
||||
end
|
||||
|
||||
return SysfsLight
|
||||
|
||||
@@ -4,6 +4,7 @@ local Event = require("ui/event")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local Language = require("ui/language")
|
||||
local NetworkMgr = require("ui/network/manager")
|
||||
local PowerD = Device:getPowerDevice()
|
||||
local UIManager = require("ui/uimanager")
|
||||
local _ = require("gettext")
|
||||
local N_ = _.ngettext
|
||||
@@ -236,6 +237,17 @@ if Device:isKobo() then
|
||||
}
|
||||
end
|
||||
|
||||
if Device:isKindle() and PowerD:hasHallSensor() then
|
||||
common_settings.cover_events = {
|
||||
text = _("Disable Kindle cover events"),
|
||||
help_text = _([[Toggle the Hall effect sensor.
|
||||
This is used to detect if the cover is closed, which will automatically sleep and wake the device. If there is no cover present the sensor may cause spurious wakeups when located next to a magnetic source.]]),
|
||||
keep_menu_open = true,
|
||||
checked_func = function() return not PowerD:isHallSensorEnabled() end,
|
||||
callback = function() PowerD:onToggleHallSensor() end,
|
||||
}
|
||||
end
|
||||
|
||||
common_settings.night_mode = {
|
||||
text = _("Night mode"),
|
||||
checked_func = function() return G_reader_settings:isTrue("night_mode") end,
|
||||
|
||||
@@ -58,6 +58,7 @@ local order = {
|
||||
"autoshutdown",
|
||||
"ignore_sleepcover",
|
||||
"ignore_open_sleepcover",
|
||||
"cover_events",
|
||||
"ignore_battery_optimizations",
|
||||
"mass_storage_settings", -- if Device:canToggleMassStorage()
|
||||
"file_ext_assoc",
|
||||
|
||||
@@ -102,6 +102,7 @@ local order = {
|
||||
"autoshutdown",
|
||||
"ignore_sleepcover",
|
||||
"ignore_open_sleepcover",
|
||||
"cover_events",
|
||||
"ignore_battery_optimizations",
|
||||
"mass_storage_settings", -- if Device:canToggleMassStorage()
|
||||
"file_ext_assoc",
|
||||
|
||||
@@ -5,9 +5,13 @@ This module contains miscellaneous helper functions for the KOReader frontend.
|
||||
local BaseUtil = require("ffi/util")
|
||||
local Utf8Proc = require("ffi/utf8proc")
|
||||
local lfs = require("libs/libkoreader-lfs")
|
||||
local logger = require("logger")
|
||||
local _ = require("gettext")
|
||||
local C_ = _.pgettext
|
||||
local T = BaseUtil.template
|
||||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
require("ffi/posix_h")
|
||||
|
||||
local lshift = bit.lshift
|
||||
local rshift = bit.rshift
|
||||
@@ -829,6 +833,26 @@ function util.removeFile(file)
|
||||
end
|
||||
end
|
||||
|
||||
function util.writeToSysfs(val, file)
|
||||
-- NOTE: We do things by hand via ffi, because io.write uses fwrite,
|
||||
-- which isn't a great fit for procfs/sysfs (e.g., we lose failure cases like EBUSY,
|
||||
-- as it only reports failures to write to the *stream*, not to the disk/file!).
|
||||
local fd = C.open(file, bit.bor(C.O_WRONLY, C.O_CLOEXEC)) -- procfs/sysfs, we shouldn't need O_TRUNC
|
||||
if fd == -1 then
|
||||
logger.err("Cannot open file `" .. file .. "`:", ffi.string(C.strerror(ffi.errno())))
|
||||
return
|
||||
end
|
||||
val = tostring(val)
|
||||
local bytes = #val
|
||||
local nw = C.write(fd, val, bytes)
|
||||
if nw == -1 then
|
||||
logger.err("Cannot write `" .. val .. "` to file `" .. file .. "`:", ffi.string(C.strerror(ffi.errno())))
|
||||
end
|
||||
C.close(fd)
|
||||
-- NOTE: Allows the caller to possibly handle short writes (not that these should ever happen here).
|
||||
return nw == bytes
|
||||
end
|
||||
|
||||
-- Gets total, used and available bytes for the mountpoint that holds a given directory.
|
||||
-- @string path of the directory
|
||||
-- @treturn table with total, used and available bytes
|
||||
|
||||
@@ -40,7 +40,6 @@ describe("device module", function()
|
||||
after_each(function()
|
||||
mock_input.open:revert()
|
||||
os.getenv:revert()
|
||||
os.execute:revert()
|
||||
|
||||
os.getenv = osgetenv
|
||||
io.open = iopen
|
||||
@@ -278,8 +277,6 @@ describe("device module", function()
|
||||
assert.is.same(kindle_dev.powerd.fl_intensity, 5)
|
||||
|
||||
kindle_dev.powerd:toggleFrontlight()
|
||||
assert.stub(os.execute).was_called_with(
|
||||
"printf '%s' 0 > /sys/class/backlight/max77696-bl/brightness")
|
||||
-- Here be shenanigans: we don't override powerd's fl_intensity when we turn the light off,
|
||||
-- so that we can properly turn it back on at the previous intensity ;)
|
||||
assert.is.same(kindle_dev.powerd.fl_intensity, 5)
|
||||
|
||||
Reference in New Issue
Block a user