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
reviewable/pr10389/r1
yparitcher 1 year ago committed by GitHub
parent 4f23a6fafa
commit 1102c030fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -726,6 +726,7 @@ function KindlePaperWhite2:init()
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness", fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity", batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", 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) Kindle.init(self)
@ -740,6 +741,7 @@ function KindleBasic:init()
device = self, device = self,
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity", batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", 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) Kindle.init(self)
@ -755,6 +757,7 @@ function KindleVoyage:init()
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness", fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity", batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", 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{ self.input = require("device/input"):new{
device = self, device = self,
@ -814,6 +817,7 @@ function KindlePaperWhite3:init()
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness", fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity", batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", 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) Kindle.init(self)
@ -870,6 +874,7 @@ function KindleOasis:init()
-- NOTE: Points to the embedded battery. The one in the cover is codenamed "soda". -- 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", batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", 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{ self.input = require("device/input"):new{
@ -1130,6 +1135,7 @@ function KindleBasic2:init()
batt_capacity_file = "/sys/class/power_supply/bd7181x_bat/capacity", batt_capacity_file = "/sys/class/power_supply/bd7181x_bat/capacity",
is_charging_file = "/sys/class/power_supply/bd7181x_bat/charging", is_charging_file = "/sys/class/power_supply/bd7181x_bat/charging",
batt_status_file = "/sys/class/power_supply/bd7181x_bat/status", batt_status_file = "/sys/class/power_supply/bd7181x_bat/status",
hall_file = "/sys/devices/system/heisenberg_hall/heisenberg_hall0/hall_enable",
} }
Kindle.init(self) Kindle.init(self)
@ -1146,6 +1152,7 @@ function KindlePaperWhite4:init()
batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity", batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity",
is_charging_file = "/sys/class/power_supply/bd71827_bat/charging", is_charging_file = "/sys/class/power_supply/bd71827_bat/charging",
batt_status_file = "/sys/class/power_supply/bd71827_bat/status", 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) Kindle.init(self)
@ -1172,6 +1179,7 @@ function KindleBasic3:init()
batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity", batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity",
is_charging_file = "/sys/class/power_supply/bd71827_bat/charging", is_charging_file = "/sys/class/power_supply/bd71827_bat/charging",
batt_status_file = "/sys/class/power_supply/bd71827_bat/status", 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) Kindle.init(self)
@ -1193,6 +1201,7 @@ function KindlePaperWhite5:init()
batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity", batt_capacity_file = "/sys/class/power_supply/bd71827_bat/capacity",
is_charging_file = "/sys/class/power_supply/bd71827_bat/charging", is_charging_file = "/sys/class/power_supply/bd71827_bat/charging",
batt_status_file = "/sys/class/power_supply/bd71827_bat/status", 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. -- 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 BasePowerD = require("device/generic/powerd")
local WakeupMgr = require("device/wakeupmgr") local WakeupMgr = require("device/wakeupmgr")
local logger = require("logger") local logger = require("logger")
local util = require("util")
-- liblipclua, see require below -- liblipclua, see require below
local KindlePowerD = BasePowerD:new{ 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 -- 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). -- (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. -- 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... -- 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 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 end
end end
@ -161,6 +163,20 @@ function KindlePowerD:isChargedHW()
return false return false
end 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() function KindlePowerD:_readFLIntensity()
return self:read_int_file(self.fl_intensity_file) return self:read_int_file(self.fl_intensity_file)
end end

@ -47,25 +47,6 @@ local function checkStandby()
return no return no
end 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 -- Return the highest core number
local function getCPUCount() local function getCPUCount()
local fd = io.open("/sys/devices/system/cpu/possible", "re") 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 . . .") logger.dbg("Kobo standby: asking to enter standby . . .")
local standby_time = time.boottime_or_realtime_coarse() 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.last_standby_time = time.boottime_or_realtime_coarse() - standby_time
self.total_standby_time = self.total_standby_time + self.last_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 -- NOTE: Sets gSleep_Mode_Suspend to 1. Used as a flag throughout the
-- kernel to suspend/resume various subsystems -- kernel to suspend/resume various subsystems
-- c.f., state_extended_store @ kernel/power/main.c -- 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 if ret then
logger.dbg("Kobo suspend: successfully asked the kernel to put subsystems to sleep") logger.dbg("Kobo suspend: successfully asked the kernel to put subsystems to sleep")
else else
@ -1174,7 +1155,7 @@ function Kobo:suspend()
logger.dbg("Kobo suspend: asking for a suspend to RAM . . .") logger.dbg("Kobo suspend: asking for a suspend to RAM . . .")
local suspend_time = time.boottime_or_realtime_coarse() 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, -- NOTE: At this point, we *should* be in suspend to RAM, as such,
-- execution should only resume on wakeup... -- execution should only resume on wakeup...
@ -1189,7 +1170,7 @@ function Kobo:suspend()
else else
logger.warn("Kobo suspend: the kernel refused to enter suspend!") logger.warn("Kobo suspend: the kernel refused to enter suspend!")
-- Reset state-extended back to 0 since we are giving up. -- 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 if G_reader_settings:isTrue("pm_debug_entry_failure") then
self:toggleChargingLED(true) self:toggleChargingLED(true)
end end
@ -1238,7 +1219,7 @@ function Kobo:resume()
-- kernel to suspend/resume various subsystems -- kernel to suspend/resume various subsystems
-- cf. kernel/power/main.c @ L#207 -- cf. kernel/power/main.c @ L#207
-- Among other things, this sets up the wakeup pins (e.g., resume on input). -- 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 if ret then
logger.dbg("Kobo resume: successfully asked the kernel to resume subsystems") logger.dbg("Kobo resume: successfully asked the kernel to resume subsystems")
else else
@ -1254,7 +1235,7 @@ function Kobo:resume()
-- c.f., neo_ctl @ drivers/input/touchscreen/zforce_i2c.c, -- 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), -- 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). -- and l (led signal level, actually a NOP on NTX kernels).
writeToSys("a", self.hasIRGridSysfsKnob) util.writeToSysfs("a", self.hasIRGridSysfsKnob)
end end
-- A full suspend may have toggled the LED off. -- A full suspend may have toggled the LED off.
@ -1367,16 +1348,16 @@ function Kobo:enableCPUCores(amount)
up = "1" up = "1"
end end
writeToSys(up, path) util.writeToSysfs(up, path)
end end
end end
function Kobo:performanceCPUGovernor() function Kobo:performanceCPUGovernor()
writeToSys("performance", self.cpu_governor_knob) util.writeToSysfs("performance", self.cpu_governor_knob)
end end
function Kobo:defaultCPUGovernor() function Kobo:defaultCPUGovernor()
writeToSys(self.default_cpu_governor, self.cpu_governor_knob) util.writeToSysfs(self.default_cpu_governor, self.cpu_governor_knob)
end end
function Kobo:isStartupScriptUpToDate() function Kobo:isStartupScriptUpToDate()

@ -2,12 +2,8 @@
-- This also supports the natural light, which consists of additional -- This also supports the natural light, which consists of additional
-- red and green light LEDs. -- red and green light LEDs.
local logger = require("logger")
local dbg = require("dbg") local dbg = require("dbg")
local util = require("util")
local ffi = require("ffi")
local C = ffi.C
require("ffi/posix_h")
local SysfsLight = { local SysfsLight = {
frontlight_white = nil, frontlight_white = nil,
@ -77,15 +73,15 @@ function SysfsLight:setNaturalBrightness(brightness, warmth)
if self.frontlight_ioctl then if self.frontlight_ioctl then
self.frontlight_ioctl:setBrightness(brightness) self.frontlight_ioctl:setBrightness(brightness)
else else
self:_write_value(self.frontlight_white, brightness) util.writeToSysfs(brightness, self.frontlight_white)
end end
end end
-- The mixer might be using inverted values... (cold is nl_max, warm is nl_min) -- The mixer might be using inverted values... (cold is nl_max, warm is nl_min)
if set_warmth then if set_warmth then
if self.nl_inverted 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 else
self:_write_value(self.frontlight_mixer, warmth) util.writeToSysfs(warmth, self.frontlight_mixer)
end end
end end
else else
@ -128,30 +124,11 @@ function SysfsLight:_set_light_value(sysfs_directory, value)
if not sysfs_directory then return end if not sysfs_directory then return end
-- bl_power is '31' when the light is turned on, '0' otherwise. -- bl_power is '31' when the light is turned on, '0' otherwise.
if (value > 0) then if (value > 0) then
self:_write_value(sysfs_directory .. "/bl_power", 31) util.writeToSysfs(31, sysfs_directory .. "/bl_power")
else 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 end
C.close(fd) util.writeToSysfs(value, sysfs_directory .. "/brightness")
-- NOTE: Allows the caller to possibly handle short writes (not that these should ever happen here).
return nw == bytes
end end
return SysfsLight return SysfsLight

@ -4,6 +4,7 @@ local Event = require("ui/event")
local InfoMessage = require("ui/widget/infomessage") local InfoMessage = require("ui/widget/infomessage")
local Language = require("ui/language") local Language = require("ui/language")
local NetworkMgr = require("ui/network/manager") local NetworkMgr = require("ui/network/manager")
local PowerD = Device:getPowerDevice()
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local _ = require("gettext") local _ = require("gettext")
local N_ = _.ngettext local N_ = _.ngettext
@ -236,6 +237,17 @@ if Device:isKobo() then
} }
end 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 = { common_settings.night_mode = {
text = _("Night mode"), text = _("Night mode"),
checked_func = function() return G_reader_settings:isTrue("night_mode") end, checked_func = function() return G_reader_settings:isTrue("night_mode") end,

@ -58,6 +58,7 @@ local order = {
"autoshutdown", "autoshutdown",
"ignore_sleepcover", "ignore_sleepcover",
"ignore_open_sleepcover", "ignore_open_sleepcover",
"cover_events",
"ignore_battery_optimizations", "ignore_battery_optimizations",
"mass_storage_settings", -- if Device:canToggleMassStorage() "mass_storage_settings", -- if Device:canToggleMassStorage()
"file_ext_assoc", "file_ext_assoc",

@ -102,6 +102,7 @@ local order = {
"autoshutdown", "autoshutdown",
"ignore_sleepcover", "ignore_sleepcover",
"ignore_open_sleepcover", "ignore_open_sleepcover",
"cover_events",
"ignore_battery_optimizations", "ignore_battery_optimizations",
"mass_storage_settings", -- if Device:canToggleMassStorage() "mass_storage_settings", -- if Device:canToggleMassStorage()
"file_ext_assoc", "file_ext_assoc",

@ -5,9 +5,13 @@ This module contains miscellaneous helper functions for the KOReader frontend.
local BaseUtil = require("ffi/util") local BaseUtil = require("ffi/util")
local Utf8Proc = require("ffi/utf8proc") local Utf8Proc = require("ffi/utf8proc")
local lfs = require("libs/libkoreader-lfs") local lfs = require("libs/libkoreader-lfs")
local logger = require("logger")
local _ = require("gettext") local _ = require("gettext")
local C_ = _.pgettext local C_ = _.pgettext
local T = BaseUtil.template local T = BaseUtil.template
local ffi = require("ffi")
local C = ffi.C
require("ffi/posix_h")
local lshift = bit.lshift local lshift = bit.lshift
local rshift = bit.rshift local rshift = bit.rshift
@ -829,6 +833,26 @@ function util.removeFile(file)
end end
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. -- Gets total, used and available bytes for the mountpoint that holds a given directory.
-- @string path of the directory -- @string path of the directory
-- @treturn table with total, used and available bytes -- @treturn table with total, used and available bytes

@ -40,7 +40,6 @@ describe("device module", function()
after_each(function() after_each(function()
mock_input.open:revert() mock_input.open:revert()
os.getenv:revert() os.getenv:revert()
os.execute:revert()
os.getenv = osgetenv os.getenv = osgetenv
io.open = iopen io.open = iopen
@ -278,8 +277,6 @@ describe("device module", function()
assert.is.same(kindle_dev.powerd.fl_intensity, 5) assert.is.same(kindle_dev.powerd.fl_intensity, 5)
kindle_dev.powerd:toggleFrontlight() 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, -- 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 ;) -- so that we can properly turn it back on at the previous intensity ;)
assert.is.same(kindle_dev.powerd.fl_intensity, 5) assert.is.same(kindle_dev.powerd.fl_intensity, 5)

Loading…
Cancel
Save