From bd17119d0704c44b860766038bc837b372896288 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Wed, 13 Apr 2022 01:11:32 +0200 Subject: [PATCH] Kobo: Disable key repeat during suspend (#8987) Might help avoiding evdev queue overflow on misbehaving covers (#8964). At the very least shaves a fair bit of stupid from debug logs ;o). --- base | 2 +- frontend/device/generic/device.lua | 8 +++++ frontend/device/input.lua | 12 ++++++- frontend/device/kobo/device.lua | 50 +++++++++++++++++++++++++++++- frontend/ui/uimanager.lua | 6 ++++ 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/base b/base index d1b9fdc02..b2b72946a 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit d1b9fdc02ad7f26c1878586575fcbe48269fcacc +Subproject commit b2b72946a75dd3e5352c37bb87aa81688b1b3668 diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index d325a48cb..65e8adc25 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -448,6 +448,14 @@ function Device:setupChargingLED() end -- (Should only be implemented on embedded platforms where we can afford to control that without screwing with the system). function Device:enableCPUCores(amount) end +-- NOTE: For this to work, all three must be implemented, and getKeyRepeat must be run on init (c.f., Kobo)! +-- Device specific method to get the current key repeat setup +function Device:getKeyRepeat() end +-- Device specific method to disable key repeat +function Device:disableKeyRepeat() end +-- Device specific method to restore key repeat +function Device:restoreKeyRepeat() end + --[[ prepare for application shutdown --]] diff --git a/frontend/device/input.lua b/frontend/device/input.lua index 93949bf7e..6a3c34881 100644 --- a/frontend/device/input.lua +++ b/frontend/device/input.lua @@ -119,6 +119,11 @@ local linux_evdev_abs_code_map = { local linux_evdev_msc_code_map = { [C.MSC_RAW] = "MSC_RAW", } + +local linux_evdev_rep_code_map = { + [C.REP_DELAY] = "REP_DELAY", + [C.REP_PERIOD] = "REP_PERIOD", +} -- luacheck: pop local _internal_clipboard_text = nil -- holds the last copied text @@ -263,7 +268,7 @@ Note that we adhere to the "." syntax here for compatibility. @todo Clean up separation FFI/this. --]] function Input.open(device, is_emu_events) - input.open(device, is_emu_events and 1 or 0) + return input.open(device, is_emu_events and 1 or 0) end --[[-- @@ -1158,6 +1163,11 @@ function Input:waitEvent(now, deadline) "input event => type: %d (%s), code: %d (%s), value: %s, time: %d.%06d", event.type, linux_evdev_type_map[event.type], event.code, linux_evdev_msc_code_map[event.code], event.value, event.time.sec, event.time.usec)) + elseif event.type == C.EV_REP then + logger.dbg(string.format( + "input event => type: %d (%s), code: %d (%s), value: %s, time: %d.%06d", + event.type, linux_evdev_type_map[event.type], event.code, linux_evdev_rep_code_map[event.code], event.value, + event.time.sec, event.time.usec)) else logger.dbg(string.format( "input event => type: %d (%s), code: %d, value: %s, time: %d.%06d", diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua index cc074dc62..a0063110c 100644 --- a/frontend/device/kobo/device.lua +++ b/frontend/device/kobo/device.lua @@ -10,6 +10,7 @@ local ffi = require("ffi") local C = ffi.C require("ffi/linux_fb_h") require("ffi/linux_input_h") +require("ffi/posix_h") local function yes() return true end local function no() return false end @@ -430,6 +431,50 @@ function Kobo:setupChargingLED() end end +function Kobo:getKeyRepeat() + -- Sanity check (mostly for the testsuite's benefit...) + if not self.ntx_fd then + self.hasKeyRepeat = false + return false + end + + self.key_repeat = ffi.new("unsigned int[?]", C.REP_CNT) + if C.ioctl(self.ntx_fd, C.EVIOCGREP, self.key_repeat) < 0 then + local err = ffi.errno() + logger.warn("Device:getKeyRepeat: EVIOCGREP ioctl failed:", ffi.string(C.strerror(err))) + self.hasKeyRepeat = false + else + self.hasKeyRepeat = true + logger.dbg("Key repeat is set up to repeat every", self.key_repeat[C.REP_PERIOD], "ms after a delay of", self.key_repeat[C.REP_DELAY], "ms") + end + + return self.hasKeyRepeat +end + +function Kobo:disableKeyRepeat() + if not self.hasKeyRepeat then + return + end + + -- NOTE: LuaJIT zero inits, and PERIOD == 0 with DELAY == 0 disables repeats ;). + local key_repeat = ffi.new("unsigned int[?]", C.REP_CNT) + if C.ioctl(self.ntx_fd, C.EVIOCSREP, key_repeat) < 0 then + local err = ffi.errno() + logger.warn("Device:disableKeyRepeat: EVIOCSREP ioctl failed:", ffi.string(C.strerror(err))) + end +end + +function Kobo:restoreKeyRepeat() + if not self.hasKeyRepeat then + return + end + + if C.ioctl(self.ntx_fd, C.EVIOCSREP, self.key_repeat) < 0 then + local err = ffi.errno() + logger.warn("Device:restoreKeyRepeat: EVIOCSREP ioctl failed:", ffi.string(C.strerror(err))) + end +end + function Kobo:init() -- Check if we need to disable MXCFB_WAIT_FOR_UPDATE_COMPLETE ioctls... local mxcfb_bypass_wait_for @@ -514,7 +559,7 @@ function Kobo:init() Generic.init(self) -- When present, event2 is the raw accelerometer data (3-Axis Orientation/Motion Detection) - self.input.open(self.ntx_dev) -- Various HW Buttons, Switches & Synthetic NTX events + self.ntx_fd = self.input.open(self.ntx_dev) -- Various HW Buttons, Switches & Synthetic NTX events self.input.open(self.touch_dev) -- fake_events is only used for usb plug event so far -- NOTE: usb hotplug event is also available in /tmp/nickel-hardware-status (... but only when Nickel is running ;p) @@ -542,6 +587,9 @@ function Kobo:init() end end + -- See if the device supports key repeat + self:getKeyRepeat() + -- We have no way of querying the current state of the charging LED, so, start from scratch. -- Much like Nickel, start by turning it off. self:toggleChargingLED(false) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index c7a544771..33e4d9d07 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -1771,12 +1771,18 @@ function UIManager:_beforeSuspend() self:flushSettings() self:broadcastEvent(Event:new("Suspend")) + -- Disable key repeat to avoid useless chatter (especially where Sleep Covers are concerned...) + Device:disableKeyRepeat() + -- Reset gesture detection state to a blank slate (anything power-management related emits KEY events, which don't need gesture detection). Input:resetState() end -- The common operations that should be performed after resuming the device. function UIManager:_afterResume() + -- Restore key repeat + Device:restoreKeyRepeat() + self:broadcastEvent(Event:new("Resume")) end