diff --git a/frontend/device/input.lua b/frontend/device/input.lua index 520ed1667..de8dab7b4 100644 --- a/frontend/device/input.lua +++ b/frontend/device/input.lua @@ -40,9 +40,10 @@ local ABS_MT_POSITION_Y = 54 local ABS_MT_TRACKING_ID = 57 local ABS_MT_PRESSURE = 58 --- For device orientation events (ABS.code) - -local ABS_PRESSURE = 24 +-- For Kindle Oasis orientation events (ABS.code) +-- the ABS code of orientation event will be adjusted to -24 from 24(ABS_PRESSURE) +-- as ABS_PRESSURE is also used to detect touch input in KOBO devices. +local ABS_OASIS_ORIENTATION = -24 local DEVICE_ORIENTATION_PORTRAIT_LEFT = 15 local DEVICE_ORIENTATION_PORTRAIT_RIGHT = 17 local DEVICE_ORIENTATION_PORTRAIT = 19 @@ -240,6 +241,12 @@ function Input:adjustTouchTranslate(ev, by) end end +function Input:adjustKindleOasisOrientation(ev) + if ev.type == EV_ABS and ev.code == ABS_PRESSURE then + ev.code = ABS_OASIS_ORIENTATION + end +end + function Input:setTimeout(cb, tv_out) local item = { callback = cb, @@ -463,37 +470,36 @@ function Input:handleTouchEvPhoenix(ev) end end -function Input:handleOrientationEv(ev) - if ev.type == EV_ABS then - if ev.code == ABS_PRESSURE then - - local rotation_mode, screen_mode - if ev.value == DEVICE_ORIENTATION_PORTRAIT or ev.value == DEVICE_ORIENTATION_PORTRAIT_LEFT or ev.value == DEVICE_ORIENTATION_PORTRAIT_RIGHT then - rotation_mode = framebuffer.ORIENTATION_PORTRAIT - screen_mode = 'portrait' - elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE then - rotation_mode = framebuffer.ORIENTATION_LANDSCAPE - screen_mode = 'landscape' - elseif ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_LEFT or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_RIGHT then - rotation_mode = framebuffer.ORIENTATION_PORTRAIT_ROTATED - screen_mode = 'portrait' - elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE_ROTATED then - rotation_mode = framebuffer.ORIENTATION_LANDSCAPE_ROTATED - screen_mode = 'landscape' - end +function Input:handleOasisOrientationEv(ev) + local rotation_mode, screen_mode + if ev.value == DEVICE_ORIENTATION_PORTRAIT + or ev.value == DEVICE_ORIENTATION_PORTRAIT_LEFT + or ev.value == DEVICE_ORIENTATION_PORTRAIT_RIGHT then + rotation_mode = framebuffer.ORIENTATION_PORTRAIT + screen_mode = 'portrait' + elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE then + rotation_mode = framebuffer.ORIENTATION_LANDSCAPE + screen_mode = 'landscape' + elseif ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED + or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_LEFT + or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_RIGHT then + rotation_mode = framebuffer.ORIENTATION_PORTRAIT_ROTATED + screen_mode = 'portrait' + elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE_ROTATED then + rotation_mode = framebuffer.ORIENTATION_LANDSCAPE_ROTATED + screen_mode = 'landscape' + end - local old_rotation_mode = self.device.screen:getRotationMode() - local old_screen_mode = self.device.screen:getScreenMode(); - DEBUG("old_rotation_mode: ", old_rotation_mode) - DEBUG("new_rotation_mode: ", rotation_mode) - DEBUG("old_screen_mode: ", old_screen_mode) - DEBUG("new_screen_mode: ", screen_mode) - if rotation_mode ~= old_rotation_mode and screen_mode == old_screen_mode then - self.device.screen:setRotationMode(rotation_mode) - local UIManager = require("ui/uimanager") - UIManager:onRotation() - end - end + local old_rotation_mode = self.device.screen:getRotationMode() + local old_screen_mode = self.device.screen:getScreenMode() + DEBUG:v("old_rotation_mode: ", old_rotation_mode) + DEBUG:v("new_rotation_mode: ", rotation_mode) + DEBUG:v("old_screen_mode: ", old_screen_mode) + DEBUG:v("new_screen_mode: ", screen_mode) + if rotation_mode ~= old_rotation_mode and screen_mode == old_screen_mode then + self.device.screen:setRotationMode(rotation_mode) + local UIManager = require("ui/uimanager") + UIManager:onRotation() end end @@ -593,13 +599,14 @@ function Input:waitEvent(timeout_us) if ok and ev then if DEBUG.is_on and ev then DEBUG:logEv(ev) + DEBUG:v("ev", ev) end self:eventAdjustHook(ev) if ev.type == EV_KEY then DEBUG("key ev", ev) return self:handleKeyBoardEv(ev) - elseif ev.type == EV_ABS and ev.code == ABS_PRESSURE then - return self:handleOrientationEv(ev) + elseif ev.type == EV_ABS and ev.code == ABS_OASIS_ORIENTATION then + return self:handleOasisOrientationEv(ev) elseif ev.type == EV_ABS or ev.type == EV_SYN then return self:handleTouchEv(ev) elseif ev.type == EV_MSC then diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 6b4c6e172..5da46de0c 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -349,11 +349,12 @@ function KindleOasis:init() } } - local lipc = require("liblipclua") - if lipc then + local haslipc, lipc = pcall(require, "liblipclua") + if haslipc and lipc then local lipc_handle = lipc.init("com.github.koreader.screen") if lipc_handle then - local orientation_code = lipc_handle:get_string_property("com.lab126.winmgr", "accelerometer") + local orientation_code = lipc_handle:get_string_property( + "com.lab126.winmgr", "accelerometer") local rotation_mode = 0 if orientation_code then if orientation_code == "V" then @@ -376,9 +377,10 @@ function KindleOasis:init() end end - Kindle.init(self) + self.input:registerEventAdjustHook(self.input.adjustKindleOasisOrientation) + self.input.open(self.touch_dev) self.input.open("/dev/input/by-path/platform-gpiokey.0-event") diff --git a/spec/unit/device_spec.lua b/spec/unit/device_spec.lua index 724bb7b93..424d1ed03 100644 --- a/spec/unit/device_spec.lua +++ b/spec/unit/device_spec.lua @@ -1,5 +1,8 @@ describe("device module", function() local mock_fb, mock_input + local iopen = io.open + local osgetenv = os.getenv + setup(function() mock_fb = { new = function() @@ -7,48 +10,51 @@ describe("device module", function() getSize = function() return {w = 600, h = 800} end, getWidth = function() return 600 end, getDPI = function() return 72 end, - setViewport = function() end + setViewport = function() end, + getRotationMode = function() return 0 end, + getScreenMode = function() return "portrait" end, + setRotationMode = function() end, } end } require("commonrequire") end) + before_each(function() + package.loaded['ffi/framebuffer_mxcfb'] = mock_fb + package.loaded['device/kindle/device'] = nil + package.loaded['device/kobo/device'] = nil + mock_input = require('device/input') + stub(mock_input, "open") + stub(os, "getenv") + stub(os, "execute") + end) + + after_each(function() + mock_input.open:revert() + os.getenv:revert() + os.execute:revert() + + os.getenv = osgetenv + io.open = iopen + end) + describe("kobo", function() local TimeVal setup(function() TimeVal = require("ui/timeval") - mock_fb = { - new = function() - return { - getSize = function() return {w = 600, h = 800} end, - getWidth = function() return 600 end, - getDPI = function() return 72 end, - setViewport = function() end - } - end - } end) it("should initialize properly on Kobo dahlia", function() - package.loaded['ffi/framebuffer_mxcfb'] = mock_fb - stub(os, "getenv") os.getenv.returns("dahlia") local kobo_dev = require("device/kobo/device") - mock_input = require('device/input') - stub(mock_input, "open") kobo_dev:init() assert.is.same("Kobo_dahlia", kobo_dev.model) - package.loaded['ffi/framebuffer_mxcfb'] = nil - os.getenv:revert() - mock_input.open:revert() end) it("should setup eventAdjustHooks properly for input in trilogy", function() - local saved_getenv = os.getenv - stub(os, "getenv") os.getenv.invokes(function(key) if key == "PRODUCT" then return "trilogy" @@ -56,11 +62,8 @@ describe("device module", function() return saved_getenv(key) end end) - package.loaded['device/kobo/device'] = nil - package.loaded['ffi/framebuffer_mxcfb'] = mock_fb - mock_input = require('device/input') - stub(mock_input, "open") + package.loaded['device/kobo/device'] = nil local kobo_dev = require("device/kobo/device") kobo_dev:init() local Screen = kobo_dev.screen @@ -93,17 +96,12 @@ describe("device module", function() assert.is.same(y, ev_x.value) assert.is.same(ABS_Y, ev_x.code) - package.loaded['ffi/framebuffer_mxcfb'] = nil - os.getenv:revert() - mock_input.open:revert() -- reset eventAdjustHook kobo_dev.input.eventAdjustHook = function() end kobo_dev.touch_probe_ev_epoch_time = true end) it("should setup eventAdjustHooks properly for trilogy with non-epoch ev time", function() - local saved_getenv = os.getenv - stub(os, "getenv") os.getenv.invokes(function(key) if key == "PRODUCT" then return "trilogy" @@ -111,11 +109,6 @@ describe("device module", function() return saved_getenv(key) end end) - package.loaded['device/kobo/device'] = nil - package.loaded['ffi/framebuffer_mxcfb'] = mock_fb - mock_input = require('device/input') - stub(mock_input, "open") - local kobo_dev = require("device/kobo/device") kobo_dev:init() local Screen = kobo_dev.screen @@ -149,9 +142,6 @@ describe("device module", function() assert.truthy(cur_sec - ev_x.time.sec < 10) assert.truthy(cur_sec - ev_y.time.sec < 10) - package.loaded['ffi/framebuffer_mxcfb'] = nil - os.getenv:revert() - mock_input.open:revert() kobo_dev.input.eventAdjustHook = function() end end) @@ -195,44 +185,44 @@ describe("device module", function() end) end) - describe("kindle #notest #nocov", function() + describe("kindle", function() it("should initialize voyage without error", function() - package.loaded['ffi/framebuffer_mxcfb'] = mock_fb - stub(io, "open") - io.open.returns({ - read = function() - return "XX13XX" - end, - close = function() end - }) - mock_input = require('device/input') - stub(mock_input, "open") + io.open = function(filename, mode) + if filename == "/proc/usid" then + return { + read = function() return "XX13XX" end, + close = function() end + } + else + return iopen(filename, mode) + end + end - local kindle_dev = require("device/kindle/device") + local kindle_dev = require('device/kindle/device') assert.is.same(kindle_dev.model, "KindleVoyage") kindle_dev:init() assert.is.same(kindle_dev.input.event_map[104], "LPgBack") assert.is.same(kindle_dev.input.event_map[109], "LPgFwd") assert.is.same(kindle_dev.powerd.fl_min, 0) assert.is.same(kindle_dev.powerd.fl_max, 24) - - io.open:revert() - package.loaded['ffi/framebuffer_mxcfb'] = nil - mock_input.open:revert() end) it("should toggle frontlight", function() - package.loaded['ffi/framebuffer_mxcfb'] = mock_fb - stub(io, "open") - io.open.returns({ - read = function() - return "12" - end, - close = function() end - }) - mock_input = require('device/input') - stub(mock_input, "open") - stub(os, "execute") + io.open = function(filename, mode) + if filename == "/proc/usid" then + return { + read = function() return "XX13XX" end, + close = function() end + } + elseif filename == "/sys/class/backlight/max77696-bl/brightness" then + return { + read = function() return "12" end, + close = function() end + } + else + return iopen(filename, mode) + end + end local kindle_dev = require("device/kindle/device") kindle_dev:init() @@ -251,11 +241,46 @@ describe("device module", function() kindle_dev.powerd:toggleFrontlight() assert.stub(os.execute).was_called_with( "echo -n 5 > /sys/class/backlight/max77696-bl/brightness") + end) + + it("oasis should interpret orientation event", function() + io.open = function(filename, mode) + if filename == "/proc/usid" then + return { + read = function() + return "XXX0GCXXX" + end, + close = function() end + } + else + return iopen(filename, mode) + end + end + + mock_ffi_input = require('ffi/input') + stub(mock_ffi_input, "waitForEvent") + mock_ffi_input.waitForEvent.returns({ + type = 3, + time = { + usec = 450565, + sec = 1471081881 + }, + code = 24, + value = 16 + }) + + local UIManager = require("ui/uimanager") + stub(UIManager, "onRotation") + + local kindle_dev = require('device/kindle/device') + assert.is.same("KindleOasis", kindle_dev.model) + kindle_dev:init() + + kindle_dev.input:waitEvent() + assert.stub(UIManager.onRotation).was_called() - io.open:revert() - package.loaded['ffi/framebuffer_mxcfb'] = nil - mock_input.open:revert() - os.execute:revert() + mock_ffi_input.waitForEvent:revert() + UIManager.onRotation:revert() end) end) end)