2019-09-29 15:42:05 +02:00
--[[--
Generic device abstraction .
This module defines stubs for common methods .
--]]
2016-12-29 00:10:38 -08:00
local logger = require ( " logger " )
2020-06-25 21:33:51 +02:00
local util = require ( " util " )
2016-11-16 11:49:34 +01:00
local _ = require ( " gettext " )
2014-10-30 19:42:18 +01:00
2015-09-27 09:25:47 +08:00
local function yes ( ) return true end
2014-10-30 19:42:18 +01:00
local function no ( ) return false end
local Device = {
screen_saver_mode = false ,
charging_mode = false ,
survive_screen_saver = false ,
2016-09-13 22:16:31 -07:00
is_cover_closed = false ,
2019-02-18 08:01:00 -08:00
should_restrict_JIT = false ,
2014-10-30 19:42:18 +01:00
model = nil ,
powerd = nil ,
screen = nil ,
2019-03-11 02:01:37 -07:00
screen_dpi_override = nil ,
2014-10-30 19:42:18 +01:00
input = nil ,
2020-06-19 09:41:50 +02:00
home_dir = nil ,
2016-09-19 01:16:41 -07:00
-- 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 ,
2014-10-30 19:42:18 +01:00
-- hardware feature tests: (these are functions!)
2020-07-21 00:52:50 +02:00
hasBattery = yes ,
2014-10-30 19:42:18 +01:00
hasKeyboard = no ,
hasKeys = no ,
2015-09-27 09:05:37 +08:00
hasDPad = no ,
2020-06-19 09:41:50 +02:00
hasExitOptions = yes ,
2020-05-26 17:43:44 +02:00
hasFewKeys = no ,
2019-02-06 15:51:50 +01:00
hasWifiToggle = yes ,
hasWifiManager = no ,
2019-09-29 15:42:05 +02:00
isHapticFeedbackEnabled = no ,
2014-10-30 19:42:18 +01:00
isTouchDevice = no ,
hasFrontlight = no ,
2019-04-15 20:06:24 +02:00
hasNaturalLight = no , -- FL warmth implementation specific to NTX boards (Kobo, Cervantes)
hasNaturalLightMixer = no , -- Same, but only found on newer boards
2020-08-19 22:41:10 +02:00
hasNaturalLightApi = no ,
2016-04-02 21:52:30 -07:00
needsTouchScreenProbe = no ,
2019-01-15 18:40:36 +01:00
hasClipboard = yes , -- generic internal clipboard on all devices
2019-02-01 09:18:27 +01:00
hasEinkScreen = yes ,
Enable HW dithering in a few key places (#4541)
* Enable HW dithering on supported devices (Clara HD, Forma; Oasis 2, PW4)
* FileManager and co. (where appropriate, i.e., when covers are shown)
* Book Status
* Reader, where appropriate:
* CRe: on pages whith image content (for over 7.5% of the screen area, should hopefully leave stuff like bullet points or small scene breaks alone).
* Other engines: on user-request (in the gear tab of the bottom menu), via the new "Dithering" knob (will only appear on supported devices).
* ScreenSaver
* ImageViewer
* Minimize repaints when flash_ui is enabled (by, almost everywhere, only repainting the flashing element, and not the toplevel window which hosts it).
(The first pass of this involved fixing a few Button instances whose show_parent was wrong, in particular, chevrons in the FM & TopMenu).
* Hunted down a few redundant repaints (unneeded setDirty("all") calls),
either by switching the widget to nil when only a refresh was needed, and not a repaint,
or by passing the appropritate widget to setDirty.
(Note to self: Enable *verbose* debugging to catch broken setDirty calls via its post guard).
There were also a few instances of 'em right behind a widget close.
* Don't repaint the underlying widget when initially showing TopMenu & ConfigDialog.
We unfortunately do need to do it when switching tabs, because of their variable heights.
* On Kobo, disabled the extra and completely useless full refresh before suspend/reboot/poweroff, as well as on resume. No more double refreshes!
* Fix another debug guard in Kobo sysfs_light
* Switch ImageWidget & ImageViewer mostly to "ui" updates, which will be better suited to image content pretty much everywhere, REAGL or not.
PS: (Almost :100: commits! :D)
2019-02-07 01:14:37 +01:00
canHWDither = no ,
2019-04-08 23:05:08 +02:00
canHWInvert = no ,
2019-05-02 04:27:48 +02:00
canUseCBB = yes , -- The C BB maintains a 1:1 feature parity with the Lua BB, except that is has NO support for BB4, and limited support for BBRGB24
2017-10-01 19:23:06 +02:00
hasColorScreen = no ,
2018-06-02 12:10:55 -04:00
hasBGRFrameBuffer = no ,
2019-12-21 15:59:23 +01:00
canImportFiles = no ,
2020-01-05 12:56:01 +01:00
canShareText = no ,
2020-07-09 19:11:44 +02:00
hasGSensor = no ,
2019-01-08 02:59:47 +01:00
canToggleGSensor = no ,
2020-07-09 19:11:44 +02:00
isGSensorLocked = no ,
2019-02-15 01:18:30 +01:00
canToggleMassStorage = no ,
2019-08-01 19:10:46 +02:00
canUseWAL = yes , -- requires mmap'ed I/O on the target FS
2019-08-20 18:38:02 +02:00
canRestart = yes ,
2020-06-19 09:41:50 +02:00
canSuspend = yes ,
2019-08-20 18:38:02 +02:00
canReboot = no ,
canPowerOff = no ,
2014-10-30 19:42:18 +01:00
-- 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!)
2018-10-31 23:48:36 +01:00
isAndroid = no ,
isCervantes = no ,
2014-10-30 19:42:18 +01:00
isKindle = no ,
isKobo = no ,
2015-01-25 00:51:57 +08:00
isPocketBook = no ,
2020-02-08 01:58:10 +01:00
isRemarkable = no ,
2018-09-07 20:37:04 -03:00
isSonyPRSTUX = no ,
2015-10-03 14:18:47 +08:00
isSDL = no ,
2019-01-03 18:21:35 +01:00
isEmulator = no ,
2019-08-20 18:38:02 +02:00
isDesktop = no ,
2014-10-30 19:42:18 +01:00
-- some devices have part of their screen covered by the bezel
viewport = nil ,
2016-02-26 17:46:23 +08:00
-- enforce portrait orientation on display, no matter how configured at
-- startup
2014-11-27 15:33:48 +00:00
isAlwaysPortrait = no ,
2015-09-27 09:25:47 +08:00
-- needs full screen refresh when resumed from screensaver?
needsScreenRefreshAfterResume = yes ,
2018-09-30 21:37:14 +02:00
-- set to yes on devices whose framebuffer reports 8bit per pixel,
-- but is actually a color eInk screen with 24bit per pixel.
-- The refresh is still based on bytes. (This solves issue #4193.)
has3BytesWideFrameBuffer = no ,
2018-10-06 07:55:35 +02:00
-- set to yes on devices that support over-the-air incremental updates.
hasOTAUpdates = no ,
2019-03-20 16:58:32 +01:00
2019-03-31 19:19:07 +02:00
canOpenLink = no ,
2019-03-20 16:58:32 +01:00
openLink = no ,
2019-07-08 14:19:36 +02:00
canExternalDictLookup = no ,
2014-10-30 19:42:18 +01:00
}
function Device : new ( o )
2016-02-15 23:10:07 -08:00
o = o or { }
2014-10-30 19:42:18 +01:00
setmetatable ( o , self )
self.__index = self
return o
end
2019-01-08 02:59:47 +01:00
-- Inverts PageTurn button mappings
-- NOTE: For ref. on Kobo, stored by Nickel in the [Reading] section as invertPageTurnButtons=true
function Device : invertButtons ( )
if self : hasKeys ( ) and self.input and self.input . event_map then
for key , value in pairs ( self.input . event_map ) do
if value == " LPgFwd " then
self.input . event_map [ key ] = " LPgBack "
elseif value == " LPgBack " then
self.input . event_map [ key ] = " LPgFwd "
elseif value == " RPgFwd " then
self.input . event_map [ key ] = " RPgBack "
elseif value == " RPgBack " then
self.input . event_map [ key ] = " RPgFwd "
end
end
-- NOTE: We currently leave self.input.rotation_map alone,
-- which will definitely yield fairly stupid mappings in Landscape...
end
end
2014-10-30 19:42:18 +01:00
function Device : init ( )
2017-06-14 10:32:16 -07:00
assert ( self ~= nil )
2014-10-30 19:42:18 +01:00
if not self.screen then
2014-11-20 20:24:02 +01:00
error ( " screen/framebuffer must be implemented " )
2014-10-30 19:42:18 +01:00
end
2014-11-22 21:55:53 +00:00
2019-03-19 20:18:38 +01:00
if self.hasMultitouch == nil then
-- default to assuming multitouch when dealing with a touch device
self.hasMultitouch = self.isTouchDevice
end
2017-10-01 19:23:06 +02:00
self.screen . isColorScreen = self.hasColorScreen
2019-02-17 23:20:42 -08:00
self.screen . isColorEnabled = function ( )
if G_reader_settings : has ( " color_rendering " ) then
return G_reader_settings : isTrue ( " color_rendering " )
else
return self.screen . isColorScreen ( )
end
end
2017-10-01 00:16:38 +02:00
2018-06-02 12:10:55 -04:00
self.screen . isBGRFrameBuffer = self.hasBGRFrameBuffer
2018-10-10 21:34:47 +02:00
local low_pan_rate = G_reader_settings : readSetting ( " low_pan_rate " )
2019-03-04 19:15:00 +01:00
if low_pan_rate ~= nil then
self.screen . low_pan_rate = low_pan_rate
else
self.screen . low_pan_rate = self.hasEinkScreen ( )
end
2016-02-29 15:08:57 +08:00
2016-12-29 00:10:38 -08:00
logger.info ( " initializing for device " , self.model )
logger.info ( " framebuffer resolution: " , self.screen : getSize ( ) )
2014-11-27 10:34:16 +00:00
2014-10-30 19:42:18 +01:00
if not self.input then
2014-11-03 10:08:55 +01:00
self.input = require ( " device/input " ) : new { device = self }
2014-10-30 19:42:18 +01:00
end
if not self.powerd then
self.powerd = require ( " device/generic/powerd " ) : new { device = self }
end
if self.viewport then
2016-12-29 00:10:38 -08:00
logger.dbg ( " setting a viewport: " , self.viewport )
2014-10-30 19:42:18 +01:00
self.screen : setViewport ( self.viewport )
self.input : registerEventAdjustHook (
self.input . adjustTouchTranslate ,
{ x = 0 - self.viewport . x , y = 0 - self.viewport . y } )
end
2019-01-08 02:59:47 +01:00
-- Handle button mappings shenanigans
if self : hasKeys ( ) then
if G_reader_settings : isTrue ( " input_invert_page_turn_keys " ) then
self : invertButtons ( )
end
end
2020-07-09 19:11:44 +02:00
-- Honor the gyro lock
if self : hasGSensor ( ) then
if G_reader_settings : isTrue ( " input_lock_gsensor " ) then
self : lockGSensor ( true )
end
end
2014-10-30 19:42:18 +01:00
end
2019-03-05 00:51:00 -08:00
function Device : setScreenDPI ( dpi_override )
self.screen : setDPI ( dpi_override )
self.input . gesture_detector : init ( )
2019-03-11 02:01:37 -07:00
self.screen_dpi_override = dpi_override
2019-03-05 00:51:00 -08:00
end
2014-10-30 19:42:18 +01:00
function Device : getPowerDevice ( )
return self.powerd
end
2016-09-19 01:16:41 -07:00
function Device : rescheduleSuspend ( )
2016-09-13 22:16:31 -07:00
local UIManager = require ( " ui/uimanager " )
2016-09-19 01:16:41 -07:00
UIManager : unschedule ( self.suspend )
UIManager : scheduleIn ( self.suspend_wait_timeout , self.suspend )
2016-09-13 22:16:31 -07:00
end
2015-02-01 12:49:46 +08:00
-- ONLY used for Kobo and PocketBook devices
2014-10-30 19:42:18 +01:00
function Device : onPowerEvent ( ev )
2016-09-10 17:33:21 -07:00
if self.screen_saver_mode then
if ev == " Power " or ev == " Resume " then
2016-09-13 22:16:31 -07:00
if self.is_cover_closed then
-- don't let power key press wake up device when the cover is in closed state
2016-09-19 01:16:41 -07:00
self : rescheduleSuspend ( )
2016-09-13 22:16:31 -07:00
else
2016-12-29 00:10:38 -08:00
logger.dbg ( " Resuming... " )
2016-09-27 00:18:47 -07:00
local UIManager = require ( " ui/uimanager " )
UIManager : unschedule ( self.suspend )
2016-09-13 22:16:31 -07:00
local network_manager = require ( " ui/network/manager " )
2019-02-08 22:29:11 +01:00
if network_manager.wifi_was_on and G_reader_settings : isTrue ( " auto_restore_wifi " ) then
2016-09-30 00:51:44 -07:00
network_manager : restoreWifiAsync ( )
2019-07-31 01:00:51 +02:00
network_manager : scheduleConnectivityCheck ( )
2016-09-13 22:16:31 -07:00
end
self : resume ( )
2020-01-23 20:08:51 +01:00
-- Restore to previous rotation mode, if need be.
2018-07-26 00:46:52 +02:00
if self.orig_rotation_mode then
self.screen : setRotationMode ( self.orig_rotation_mode )
end
2019-02-19 18:17:58 +01:00
require ( " ui/screensaver " ) : close ( )
2016-09-13 22:16:31 -07:00
if self : needsScreenRefreshAfterResume ( ) then
2016-09-27 00:18:47 -07:00
UIManager : scheduleIn ( 1 , function ( ) self.screen : refreshFull ( ) end )
2016-09-13 22:16:31 -07:00
end
self.screen_saver_mode = false
self.powerd : afterResume ( )
2016-09-10 17:33:21 -07:00
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.
2016-12-29 00:10:38 -08:00
logger.dbg ( " Already in screen saver mode, suspending... " )
2016-09-19 01:16:41 -07:00
self : rescheduleSuspend ( )
2016-09-10 17:33:21 -07:00
end
2019-02-14 20:23:28 +01:00
-- else we were not in screensaver mode
2016-09-10 17:33:21 -07:00
elseif ev == " Power " or ev == " Suspend " then
2016-02-26 17:46:23 +08:00
self.powerd : beforeSuspend ( )
2014-10-30 19:42:18 +01:00
local UIManager = require ( " ui/uimanager " )
2016-12-29 00:10:38 -08:00
logger.dbg ( " Suspending... " )
2020-01-23 20:08:51 +01:00
-- Mostly always suspend in Portrait/Inverted Portrait mode...
2020-03-08 03:46:46 -04:00
-- ... except when we just show an InfoMessage or when the screensaver
2020-06-21 16:27:43 +02:00
-- is disabled, as it plays badly with Landscape mode (c.f., #4098 and #5290).
-- We also exclude full-screen widgets that work fine in Landscape mode,
-- like ReadingProgress and BookStatus (c.f., #5724)
2020-03-08 03:46:46 -04:00
local screensaver_type = G_reader_settings : readSetting ( " screensaver_type " )
2020-06-21 16:27:43 +02:00
if screensaver_type ~= " message " and screensaver_type ~= " disable " and
screensaver_type ~= " readingprogress " and screensaver_type ~= " bookstatus " then
2018-07-26 00:46:52 +02:00
self.orig_rotation_mode = self.screen : getRotationMode ( )
2020-01-23 20:08:51 +01:00
-- Leave Portrait & Inverted Portrait alone, that works just fine.
if bit.band ( self.orig_rotation_mode , 1 ) == 1 then
-- i.e., only switch to Portrait if we're currently in *any* Landscape orientation (odd number)
2020-07-09 19:11:44 +02:00
self.screen : setRotationMode ( self.screen . ORIENTATION_PORTRAIT )
2020-01-23 20:08:51 +01:00
else
self.orig_rotation_mode = nil
end
2019-02-14 20:23:28 +01:00
-- On eInk, if we're using a screensaver mode that shows an image,
-- flash the screen to white first, to eliminate ghosting.
if self : hasEinkScreen ( ) and
2020-03-08 03:46:46 -04:00
screensaver_type == " cover " or screensaver_type == " random_image " or
screensaver_type == " image_file " then
2019-03-14 20:58:45 +01:00
if not G_reader_settings : isTrue ( " screensaver_no_background " ) then
2019-03-27 22:50:44 +01:00
self.screen : clear ( )
2019-03-14 20:58:45 +01:00
end
2019-02-14 20:23:28 +01:00
self.screen : refreshFull ( )
end
2018-07-26 00:46:52 +02:00
else
-- nil it, in case user switched ScreenSaver modes during our lifetime.
self.orig_rotation_mode = nil
end
2017-12-17 18:27:24 +01:00
require ( " ui/screensaver " ) : show ( )
Enable HW dithering in a few key places (#4541)
* Enable HW dithering on supported devices (Clara HD, Forma; Oasis 2, PW4)
* FileManager and co. (where appropriate, i.e., when covers are shown)
* Book Status
* Reader, where appropriate:
* CRe: on pages whith image content (for over 7.5% of the screen area, should hopefully leave stuff like bullet points or small scene breaks alone).
* Other engines: on user-request (in the gear tab of the bottom menu), via the new "Dithering" knob (will only appear on supported devices).
* ScreenSaver
* ImageViewer
* Minimize repaints when flash_ui is enabled (by, almost everywhere, only repainting the flashing element, and not the toplevel window which hosts it).
(The first pass of this involved fixing a few Button instances whose show_parent was wrong, in particular, chevrons in the FM & TopMenu).
* Hunted down a few redundant repaints (unneeded setDirty("all") calls),
either by switching the widget to nil when only a refresh was needed, and not a repaint,
or by passing the appropritate widget to setDirty.
(Note to self: Enable *verbose* debugging to catch broken setDirty calls via its post guard).
There were also a few instances of 'em right behind a widget close.
* Don't repaint the underlying widget when initially showing TopMenu & ConfigDialog.
We unfortunately do need to do it when switching tabs, because of their variable heights.
* On Kobo, disabled the extra and completely useless full refresh before suspend/reboot/poweroff, as well as on resume. No more double refreshes!
* Fix another debug guard in Kobo sysfs_light
* Switch ImageWidget & ImageViewer mostly to "ui" updates, which will be better suited to image content pretty much everywhere, REAGL or not.
PS: (Almost :100: commits! :D)
2019-02-07 01:14:37 +01:00
if self : needsScreenRefreshAfterResume ( ) then
self.screen : refreshFull ( )
end
2016-02-26 17:46:23 +08:00
self.screen_saver_mode = true
2017-04-01 20:24:15 +01:00
UIManager : scheduleIn ( 0.1 , function ( )
local network_manager = require ( " ui/network/manager " )
Various Wi-Fi QoL improvements (#6424)
* Revamped most actions that require an internet connection to a new/fixed backend that allows forwarding the initial action and running it automatically once connected. (i.e., it'll allow you to set "Action when Wi-Fi is off" to "turn_on", and whatch stuff connect and do what you wanted automatically without having to re-click anywhere instead of showing you a Wi-Fi prompt and then not doing anything without any other feedback).
* Speaking of, fixed the "turn_on" beforeWifi action to, well, actually work. It's no longer marked as experimental.
* Consistently use "Wi-Fi" everywhere.
* On Kobo/Cervantes/Sony, implemented a "Kill Wi-Fi connection when inactive" system that will automatically disconnect from Wi-Fi after sustained *network* inactivity (i.e., you can keep reading, it'll eventually turn off on its own). This should be smart and flexible enough not to murder Wi-Fi while you need it, while still not keeping it uselessly on and murdering your battery.
(i.e., enable that + turn Wi-Fi on when off and enjoy never having to bother about Wi-Fi ever again).
* Made sending `NetworkConnected` / `NetworkDisconnected` events consistent (they were only being sent... sometimes, which made relying on 'em somewhat problematic).
* restoreWifiAsync is now only run when really needed (i.e., we no longer stomp on an existing working connection just for the hell of it).
* We no longer attempt to kill a bogus non-existent Wi-Fi connection when going to suspend, we only do it when it's actually needed.
* Every method of enabling Wi-Fi will now properly tear down Wi-Fi on failure, instead of leaving it in an undefined state.
* Fixed an issue in the fancy crash screen on Kobo/reMarkable that could sometime lead to the log excerpt being missing.
* Worked-around a number of sneaky issues related to low-level Wi-Fi/DHCP/DNS handling on Kobo (see the lengthy comments [below](https://github.com/koreader/koreader/pull/6424#issuecomment-663881059) for details). Fix #6421
Incidentally, this should also fix the inconsistencies experienced re: Wi-Fi behavior in Nickel when toggling between KOReader and Nickel (use NM/KFMon, and run a current FW for best results).
* For developers, this involves various cleanups around NetworkMgr and NetworkListener. Documentation is in-line, above the concerned functions.
2020-07-27 03:39:06 +02:00
-- NOTE: wifi_was_on does not necessarily mean that Wi-Fi is *currently* on! It means *we* enabled it.
2018-05-10 06:26:07 -04:00
-- This is critical on Kobos (c.f., #3936), where it might still be on from KSM or Nickel,
-- without us being aware of it (i.e., wifi_was_on still unset or false),
Various Wi-Fi QoL improvements (#6424)
* Revamped most actions that require an internet connection to a new/fixed backend that allows forwarding the initial action and running it automatically once connected. (i.e., it'll allow you to set "Action when Wi-Fi is off" to "turn_on", and whatch stuff connect and do what you wanted automatically without having to re-click anywhere instead of showing you a Wi-Fi prompt and then not doing anything without any other feedback).
* Speaking of, fixed the "turn_on" beforeWifi action to, well, actually work. It's no longer marked as experimental.
* Consistently use "Wi-Fi" everywhere.
* On Kobo/Cervantes/Sony, implemented a "Kill Wi-Fi connection when inactive" system that will automatically disconnect from Wi-Fi after sustained *network* inactivity (i.e., you can keep reading, it'll eventually turn off on its own). This should be smart and flexible enough not to murder Wi-Fi while you need it, while still not keeping it uselessly on and murdering your battery.
(i.e., enable that + turn Wi-Fi on when off and enjoy never having to bother about Wi-Fi ever again).
* Made sending `NetworkConnected` / `NetworkDisconnected` events consistent (they were only being sent... sometimes, which made relying on 'em somewhat problematic).
* restoreWifiAsync is now only run when really needed (i.e., we no longer stomp on an existing working connection just for the hell of it).
* We no longer attempt to kill a bogus non-existent Wi-Fi connection when going to suspend, we only do it when it's actually needed.
* Every method of enabling Wi-Fi will now properly tear down Wi-Fi on failure, instead of leaving it in an undefined state.
* Fixed an issue in the fancy crash screen on Kobo/reMarkable that could sometime lead to the log excerpt being missing.
* Worked-around a number of sneaky issues related to low-level Wi-Fi/DHCP/DNS handling on Kobo (see the lengthy comments [below](https://github.com/koreader/koreader/pull/6424#issuecomment-663881059) for details). Fix #6421
Incidentally, this should also fix the inconsistencies experienced re: Wi-Fi behavior in Nickel when toggling between KOReader and Nickel (use NM/KFMon, and run a current FW for best results).
* For developers, this involves various cleanups around NetworkMgr and NetworkListener. Documentation is in-line, above the concerned functions.
2020-07-27 03:39:06 +02:00
-- because suspend will at best fail, and at worst deadlock the system if Wi-Fi is on,
2018-05-10 06:26:07 -04:00
-- regardless of who enabled it!
Various Wi-Fi QoL improvements (#6424)
* Revamped most actions that require an internet connection to a new/fixed backend that allows forwarding the initial action and running it automatically once connected. (i.e., it'll allow you to set "Action when Wi-Fi is off" to "turn_on", and whatch stuff connect and do what you wanted automatically without having to re-click anywhere instead of showing you a Wi-Fi prompt and then not doing anything without any other feedback).
* Speaking of, fixed the "turn_on" beforeWifi action to, well, actually work. It's no longer marked as experimental.
* Consistently use "Wi-Fi" everywhere.
* On Kobo/Cervantes/Sony, implemented a "Kill Wi-Fi connection when inactive" system that will automatically disconnect from Wi-Fi after sustained *network* inactivity (i.e., you can keep reading, it'll eventually turn off on its own). This should be smart and flexible enough not to murder Wi-Fi while you need it, while still not keeping it uselessly on and murdering your battery.
(i.e., enable that + turn Wi-Fi on when off and enjoy never having to bother about Wi-Fi ever again).
* Made sending `NetworkConnected` / `NetworkDisconnected` events consistent (they were only being sent... sometimes, which made relying on 'em somewhat problematic).
* restoreWifiAsync is now only run when really needed (i.e., we no longer stomp on an existing working connection just for the hell of it).
* We no longer attempt to kill a bogus non-existent Wi-Fi connection when going to suspend, we only do it when it's actually needed.
* Every method of enabling Wi-Fi will now properly tear down Wi-Fi on failure, instead of leaving it in an undefined state.
* Fixed an issue in the fancy crash screen on Kobo/reMarkable that could sometime lead to the log excerpt being missing.
* Worked-around a number of sneaky issues related to low-level Wi-Fi/DHCP/DNS handling on Kobo (see the lengthy comments [below](https://github.com/koreader/koreader/pull/6424#issuecomment-663881059) for details). Fix #6421
Incidentally, this should also fix the inconsistencies experienced re: Wi-Fi behavior in Nickel when toggling between KOReader and Nickel (use NM/KFMon, and run a current FW for best results).
* For developers, this involves various cleanups around NetworkMgr and NetworkListener. Documentation is in-line, above the concerned functions.
2020-07-27 03:39:06 +02:00
if network_manager : isWifiOn ( ) then
2017-04-01 20:24:15 +01:00
network_manager : releaseIP ( )
network_manager : turnOffWifi ( )
end
UIManager : scheduleIn ( self.suspend_wait_timeout , self.suspend )
end )
2014-10-30 19:42:18 +01:00
end
end
2020-06-19 09:41:50 +02:00
function Device : info ( )
return self.model
end
2016-10-22 00:04:37 -07:00
-- 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
2016-03-07 00:02:15 -08:00
-- Hardware specific method to suspend the device
2016-02-26 17:46:23 +08:00
function Device : suspend ( ) end
2014-10-30 19:42:18 +01:00
2016-03-07 00:02:15 -08:00
-- Hardware specific method to resume the device
2016-02-26 17:46:23 +08:00
function Device : resume ( ) end
2014-10-30 19:42:18 +01:00
2016-04-26 23:30:52 +01:00
-- Hardware specific method to power off the device
function Device : powerOff ( ) end
2017-05-14 18:43:08 +02:00
-- Hardware specific method to reboot the device
function Device : reboot ( ) end
2016-06-12 11:50:30 -07:00
-- Hardware specific method to initialize network manager module
2016-10-22 00:04:37 -07:00
function Device : initNetworkManager ( ) end
2016-06-12 11:50:30 -07:00
2017-04-13 19:55:31 +02:00
function Device : supportsScreensaver ( ) return false end
2017-09-24 05:58:34 +08:00
-- Device specific method to set datetime
function Device : setDateTime ( year , month , day , hour , min , sec ) end
2017-09-04 21:05:05 +02:00
-- Device specific method if any setting needs being saved
function Device : saveSettings ( ) end
2020-07-20 22:37:00 +02:00
-- Simulates suspend/resume
function Device : simulateSuspend ( ) end
function Device : simulateResume ( ) end
2019-09-29 15:42:05 +02:00
--[[--
Device specific method for performing haptic feedback .
@ string type Type of haptic feedback . See < https : // developer.android . com / reference / android / view / HapticFeedbackConstants.html > .
--]]
function Device : performHapticFeedback ( type ) end
2020-06-13 12:57:08 +02:00
-- Device specific method for toggling input events
function Device : setIgnoreInput ( enable ) return true end
2019-01-08 02:59:47 +01:00
-- Device specific method for toggling the GSensor
2019-07-01 17:12:24 +02:00
function Device : toggleGSensor ( toggle ) end
2019-01-08 02:59:47 +01:00
2020-07-09 19:11:44 +02:00
-- Whether or not the GSensor should be locked to the current orientation (i.e. Portrait <-> Inverted Portrait or Landscape <-> Inverted Landscape only)
function Device : lockGSensor ( toggle )
if not self : hasGSensor ( ) then
return
end
if toggle == true then
-- Lock GSensor to current roientation
self.isGSensorLocked = yes
elseif toggle == false then
-- Unlock GSensor
self.isGSensorLocked = no
else
-- Toggle it
if self : isGSensorLocked ( ) then
self.isGSensorLocked = no
else
self.isGSensorLocked = yes
end
end
end
2014-10-30 19:42:18 +01:00
--[[
prepare for application shutdown
--]]
function Device : exit ( )
require ( " ffi/input " ) : closeAll ( )
self.screen : close ( )
end
2016-07-26 21:32:13 -07:00
function Device : retrieveNetworkInfo ( )
local std_out = io.popen ( " ifconfig | " ..
" sed -n " ..
" -e 's/ \\ +$//g' " ..
" -e 's/ \\ +/ /g' " ..
2016-12-04 15:23:57 +01:00
" -e 's/ \\ ?inet6 \\ ? addr: \\ ? \\ ([^ ] \\ + \\ ) .*$/IP: \\ 1/p' " ..
" -e 's/Link encap:Ethernet \\ (.* \\ )/ \\ 1/p' " ,
2016-07-26 21:32:13 -07:00
" r " )
if std_out then
local result = std_out : read ( " *all " )
std_out : close ( )
2018-05-01 14:49:37 +02:00
std_out = io.popen ( ' 2>/dev/null iwconfig | grep ESSID | cut -d \\ " -f2 ' )
2016-12-04 15:23:57 +01:00
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
2019-06-05 21:36:38 +02:00
-- NOTE: No -w flag available in the old busybox build used on Legacy Kindles...
local pingok
if self : isKindle ( ) and self : hasKeyboard ( ) then
2019-06-28 18:57:20 +02:00
pingok = os.execute ( " ping -q -c 2 `ip r | grep default | tail -n 1 | cut -d ' ' -f 3` > /dev/null " )
2019-06-05 21:36:38 +02:00
else
2019-06-28 18:57:20 +02:00
pingok = os.execute ( " ping -q -w 3 -c 2 `ip r | grep default | tail -n 1 | cut -d ' ' -f 3` > /dev/null " )
2019-06-05 21:36:38 +02:00
end
2016-12-04 15:23:57 +01:00
if pingok == 0 then
2017-03-25 21:07:47 +00:00
result = result .. " Gateway ping successful "
2016-12-04 15:23:57 +01:00
else
result = result .. " Gateway ping FAILED "
end
else
result = result .. " No default gateway to ping "
end
2016-07-26 21:32:13 -07:00
return result
end
end
2017-08-15 19:54:02 +02:00
function Device : setTime ( hour , min )
return false
end
2017-06-14 10:32:16 -07:00
-- Return an integer value to indicate the brightness of the environment. The value should be in
2017-06-24 00:55:31 -07:00
-- range [0, 4].
2017-06-14 10:32:16 -07:00
-- 0: dark.
-- 1: dim, frontlight is needed.
2017-06-24 00:55:31 -07:00
-- 2: neutral, turning frontlight on or off does not impact the reading experience.
-- 3: bright, frontlight is not needed.
-- 4: dazzling.
2017-06-14 10:32:16 -07:00
function Device : ambientBrightnessLevel ( )
return 0
end
2020-06-25 21:33:51 +02:00
--- Returns true if the file is a script we allow running
--- Basically a helper method to check a specific list of file extensions for executable scripts
---- @string filename
---- @treturn boolean
function Device : canExecuteScript ( file )
local file_ext = string.lower ( util.getFileNameSuffix ( file ) )
if file_ext == " sh " or file_ext == " py " then
return true
end
end
2014-10-30 19:42:18 +01:00
return Device