diff --git a/.gitignore b/.gitignore index 3f5fde81a..30f41fb2d 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ koreader-emulator-x86_64-pc-linux-gnu* koreader-emulator-x86_64-apple-darwin* koreader-pocketbook-arm-obreey-linux-gnueabi* koreader-ubuntu-touch-arm-linux-gnueabihf* +koreader-sony[-_]prstux-arm-linux-gnueabihf* + diff --git a/Makefile b/Makefile index 37c822105..7c2f836c5 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ ANDROID_DIR=$(PLATFORM_DIR)/android ANDROID_LAUNCHER_DIR:=$(ANDROID_DIR)/luajit-launcher UBUNTUTOUCH_SDL_DIR:=$(UBUNTUTOUCH_DIR)/ubuntu-touch-sdl WIN32_DIR=$(PLATFORM_DIR)/win32 +SONY_PRSTUX_DIR=$(PLATFORM_DIR)/sony-prstux # appimage setup APPIMAGETOOL=appimagetool-x86_64.AppImage @@ -360,6 +361,32 @@ androidupdate: all cp $(ANDROID_LAUNCHER_DIR)/bin/NativeActivity-debug.apk \ koreader-android-$(MACHINE)-$(VERSION).apk +sony-prstuxupdate: all + # ensure that the binaries were built for ARM + file $(INSTALL_DIR)/koreader/luajit | grep ARM || exit 1 + # remove old package if any + rm -f koreader-sony-prstux-$(MACHINE)-$(VERSION).zip + # Sony PRSTUX launching scripts + cp $(SONY_PRSTUX_DIR)/*.sh $(INSTALL_DIR)/koreader + # create new package + cd $(INSTALL_DIR) && \ + zip -9 -r \ + ../koreader-sony-prstux-$(MACHINE)-$(VERSION).zip \ + koreader -x "koreader/resources/fonts/*" \ + "koreader/resources/icons/src/*" "koreader/spec/*" \ + $(ZIP_EXCLUDE) + # generate update package index file + zipinfo -1 koreader-sony-prstux-$(MACHINE)-$(VERSION).zip > \ + $(INSTALL_DIR)/koreader/ota/package.index + echo "koreader/ota/package.index" >> $(INSTALL_DIR)/koreader/ota/package.index + # update index file in zip package + cd $(INSTALL_DIR) && zip -u ../koreader-sony-prstux-$(MACHINE)-$(VERSION).zip \ + koreader/ota/package.index + # make gzip sonyprstux update for zsync OTA update + cd $(INSTALL_DIR) && \ + tar -I"gzip --rsyncable" -cah --no-recursion -f ../koreader-sony-prstux-$(MACHINE)-$(VERSION).targz \ + -T koreader/ota/package.index + update: ifeq ($(TARGET), kindle) make kindleupdate @@ -371,6 +398,8 @@ else ifeq ($(TARGET), kobo) make koboupdate else ifeq ($(TARGET), pocketbook) make pbupdate +else ifeq ($(TARGET), sony-prstux) + make sony-prstuxupdate else ifeq ($(TARGET), ubuntu-touch) make utupdate else ifeq ($(TARGET), appimage) diff --git a/base b/base index f43689452..d96c69131 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit f436894521f53a1440f40c35315da14d4b2a2894 +Subproject commit d96c69131f5156750fd75574b0a4b310a5178b1b diff --git a/frontend/device.lua b/frontend/device.lua index 2f03f270d..3ca5751eb 100644 --- a/frontend/device.lua +++ b/frontend/device.lua @@ -26,6 +26,11 @@ local function probeDevice() return require("device/pocketbook/device") end + local sony_prstux_test_stat = lfs.attributes("/etc/PRSTUX") + if sony_prstux_test_stat then + return require("device/sony-prstux/device") + end + -- add new ports here: -- -- if --[[ implement a proper test instead --]] false then diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index 640dcb5b2..09bcaa971 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -35,6 +35,7 @@ local Device = { isKindle = no, isKobo = no, isPocketBook = no, + isSonyPRSTUX = no, isAndroid = no, isSDL = no, diff --git a/frontend/device/sony-prstux/device.lua b/frontend/device/sony-prstux/device.lua new file mode 100644 index 000000000..e4e8ff6d9 --- /dev/null +++ b/frontend/device/sony-prstux/device.lua @@ -0,0 +1,186 @@ +local Generic = require("device/generic/device") -- <= look at this file! +local logger = require("logger") +local TimeVal = require("ui/timeval") +local ffi = require("ffi") + +local function yes() return true end +local function no() return false end + +local SonyPRSTUX = Generic:new{ + model = "Sony PRSTUX", + isSonyPRSTUX = yes, + hasKeys = yes, +} + + + +-- sony's driver does not inform of ID, so we overwrite the TOUCH_MAJOR +-- event to fake an ID event. a width == 0 means the finger was lift. +-- after all events are received, we reset the counter + +local next_touch_id = 0 +local ABS_MT_TRACKING_ID = 57 +local ABS_MT_TOUCH_MAJOR = 48 +local EV_SYN = 0 +local EV_ABS = 3 +local SYN_REPORT = 0 +local SYN_MT_REPORT = 2 +local adjustTouchEvt = function(self, ev) + ev.time = TimeVal:now() + logger.dbg('updated time to ',ev.time) + + if ev.type == EV_ABS and ev.code == ABS_MT_TOUCH_MAJOR then + ev.code = ABS_MT_TRACKING_ID + if ev.value ~= 0 then + ev.value = next_touch_id + else + ev.value = -1 + end + + next_touch_id = next_touch_id + 1 + + logger.dbg('adjusted id: ', ev.value) + elseif ev.type == EV_SYN and ev.code == SYN_REPORT then + next_touch_id = 0 + logger.dbg('reset id: ', ev.code, ev.value) + ev.code = SYN_MT_REPORT + elseif ev.type == EV_SYN and ev.code == SYN_MT_REPORT then + ev.code = SYN_REPORT + end +end + +function SonyPRSTUX:init() + self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg} + self.powerd = require("device/sony-prstux/powerd"):new{device = self} + self.input = require("device/input"):new{ + device = self, + event_map = require("device/sony-prstux/event_map"), + } + + self.input.open("/dev/input/event0") -- Keys + self.input.open("/dev/input/event1") -- touchscreen + self.input.open("/dev/input/event2") -- power button + self.input:registerEventAdjustHook(adjustTouchEvt) + + local rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED + self.screen.native_rotation_mode = rotation_mode + self.screen.cur_rotation_mode = rotation_mode + + Generic.init(self) +end + +function SonyPRSTUX:supportsScreensaver() return true end + +function SonyPRSTUX:setDateTime(year, month, day, hour, min, sec) + if hour == nil or min == nil then return true end + local command + if year and month and day then + command = string.format("date -s '%d-%d-%d %d:%d:%d'", year, month, day, hour, min, sec) + else + command = string.format("date -s '%d:%d'",hour, min) + end + if os.execute(command) == 0 then + os.execute('hwclock -u -w') + return true + else + return false + end +end + +function SonyPRSTUX:intoScreenSaver() + local Screensaver = require("ui/screensaver") + if self.screen_saver_mode == false then + Screensaver:show() + end + self.powerd:beforeSuspend() + self.screen_saver_mode = true +end + +function SonyPRSTUX:outofScreenSaver() + if self.screen_saver_mode == true then + local Screensaver = require("ui/screensaver") + Screensaver:close() + local UIManager = require("ui/uimanager") + UIManager:nextTick(function() UIManager:setDirty("all", "full") end) + end + self.powerd:afterResume() + self.screen_saver_mode = false +end + +function SonyPRSTUX:suspend() + os.execute("./suspend.sh") +end + +function SonyPRSTUX:resume() + os.execute("./resume.sh") +end + +function SonyPRSTUX:powerOff() + os.execute("poweroff") +end + +function SonyPRSTUX:reboot() + os.execute("reboot") +end + +function SonyPRSTUX:initNetworkManager(NetworkMgr) + function NetworkMgr:turnOffWifi(complete_callback) + self:releaseIP() + os.execute("./set-wifi.sh off") + if complete_callback then + complete_callback() + end + end + + function NetworkMgr:turnOnWifi(complete_callback) + os.execute("./set-wifi.sh on") + self:showNetworkMenu(complete_callback) + end + + NetworkMgr:setWirelessBackend("wpa_supplicant", {ctrl_interface = "/var/run/wpa_supplicant/wlan0"}) + + function NetworkMgr:obtainIP() + self:releaseIP() + os.execute("dhclient wlan0") + end + + function NetworkMgr:releaseIP() + logger.info("killing dhclient") + os.execute("dhclient -x wlan0") + end + + function NetworkMgr:restoreWifiAsync() + -- os.execute("./restore-wifi-async.sh") + end + + function NetworkMgr:isWifiOn() + return 0 == os.execute("wmiconfig -i wlan0 --wlan query | grep -q enabled") + end +end + + +function SonyPRSTUX:getSoftwareVersion() + return ffi.string("PRSTUX") +end + +function SonyPRSTUX:getDeviceModel() + return ffi.string("PRS-T2") +end + +-- For Sony PRS-T2 +local SonyPRSTUX_T2 = SonyPRSTUX:new{ + isTouchDevice = yes, + hasKeys = yes, + hasFrontlight = no, + display_dpi = 166, +} + +logger.info('SoftwareVersion: ', SonyPRSTUX:getSoftwareVersion()) + +local codename = SonyPRSTUX:getDeviceModel() + +if codename == "PRS-T2" then + return SonyPRSTUX_T2 +else + error("unrecognized Sony PRSTUX model " .. codename) +end diff --git a/frontend/device/sony-prstux/event_map.lua b/frontend/device/sony-prstux/event_map.lua new file mode 100644 index 000000000..518a837f0 --- /dev/null +++ b/frontend/device/sony-prstux/event_map.lua @@ -0,0 +1,8 @@ +return { + [102] = "Home", + [105] = "Left", + [106] = "Right", + [357] = "Menu", + [158] = "Back", + [116] = "Power", +} diff --git a/frontend/device/sony-prstux/powerd.lua b/frontend/device/sony-prstux/powerd.lua new file mode 100644 index 000000000..ba324e7f4 --- /dev/null +++ b/frontend/device/sony-prstux/powerd.lua @@ -0,0 +1,31 @@ +local BasePowerD = require("device/generic/powerd") + +local base_path = '/sys/devices/platform/imx-i2c.1/i2c-1/1-0049/twl6030_bci/power_supply/twl6030_battery/' + +local SonyPRSTUX_PowerD = BasePowerD:new{ + is_charging = nil, + fl_min = 0, + fl_max = 100, + capacity_file = base_path .. 'capacity', + status_file = base_path .. 'status' +} + +function SonyPRSTUX_PowerD:init() +end + +function SonyPRSTUX_PowerD:frontlightIntensityHW() + if not self.device.hasFrontlight() then return 0 end +end + +function SonyPRSTUX_PowerD:setIntensityHW(intensity) +end + +function SonyPRSTUX_PowerD:getCapacityHW() + return self:read_int_file(self.capacity_file) +end + +function SonyPRSTUX_PowerD:isChargingHW() + return self:read_str_file(self.status_file) == "Charging\n" +end + +return SonyPRSTUX_PowerD diff --git a/frontend/ui/elements/common_info_menu_table.lua b/frontend/ui/elements/common_info_menu_table.lua index 46b6fa8b6..bd170223c 100644 --- a/frontend/ui/elements/common_info_menu_table.lua +++ b/frontend/ui/elements/common_info_menu_table.lua @@ -69,7 +69,7 @@ if Device:isKindle() or Device:isKobo() then end, } end -if Device:isKobo() then +if Device:isKobo() or Device:isSonyPRSTUX() then common_info.reboot = { text = _("Reboot the device"), keep_menu_open = true, diff --git a/frontend/ui/network/manager.lua b/frontend/ui/network/manager.lua index d47c6b227..38c5da04e 100644 --- a/frontend/ui/network/manager.lua +++ b/frontend/ui/network/manager.lua @@ -121,10 +121,10 @@ end function NetworkMgr:getWifiMenuTable() return { text = _("Wi-Fi connection"), - enabled_func = function() return Device:isAndroid() or Device:isKindle() or Device:isKobo() end, - checked_func = function() return NetworkMgr:isOnline() end, + enabled_func = function() return Device:isAndroid() or Device:isKindle() or Device:isKobo() or Device:isSonyPRSTUX() end, + checked_func = function() return NetworkMgr:isWifiOn() end, callback = function(touchmenu_instance) - local wifi_status = NetworkMgr:isOnline() + local wifi_status = NetworkMgr:isWifiOn() local complete_callback = function() -- notify touch menu to update item check state touchmenu_instance:updateItems() @@ -197,7 +197,7 @@ function NetworkMgr:getInfoMenuTable() text = _("Network info"), keep_menu_open = true, -- TODO: also show network info when device is authenticated to router but offline - enabled_func = function() return self:isOnline() end, + enabled_func = function() return self:isWifiOn() end, callback = function() if Device.retrieveNetworkInfo then UIManager:show(InfoMessage:new{ diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 21eea2bad..fdae61203 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -166,6 +166,30 @@ function UIManager:init() Device:usbPlugOut() self:_afterNotCharging() end + elseif Device:isSonyPRSTUX() then + self.event_handlers["PowerPress"] = function() + UIManager:scheduleIn(2, self.poweroff_action) + end + self.event_handlers["PowerRelease"] = function() + if not self._entered_poweroff_stage then + UIManager:unschedule(self.poweroff_action) + self:_beforeSuspend() + Device:intoScreenSaver() + Device:suspend() + end + end + self.event_handlers["Suspend"] = self.event_handlers["PowerRelease"] + self.event_handlers["Resume"] = function() + Device:resume() + Device:outofScreenSaver() + self:_afterResume() + end + self.event_handlers["__default__"] = function(input_event) + -- Same as in Kobo: we want to ignore keys during suspension + if not Device.screen_saver_mode then + self:sendEvent(input_event) + end + end elseif Device:isSDL() then self.event_handlers["Suspend"] = function() self:_beforeSuspend() @@ -939,7 +963,7 @@ end -- Executes all the operations of a suspending request. This function usually puts the device into -- suspension. function UIManager:suspend() - if Device:isKobo() or Device:isSDL() then + if Device:isKobo() or Device:isSDL() or Device:isSonyPRSTUX() then self.event_handlers["Suspend"]() elseif Device:isKindle() then self.event_handlers["IntoSS"]() @@ -948,7 +972,7 @@ end -- Executes all the operations of a resume request. This function usually wakes up the device. function UIManager:resume() - if Device:isKobo() or Device:isSDL() then + if Device:isKobo() or Device:isSDL() or Device:isSonyPRSTUX() then self.event_handlers["Resume"]() elseif Device:isKindle() then self.event_handlers["OutOfSS"]() diff --git a/kodev b/kodev index 2551f581d..7b301c931 100755 --- a/kodev +++ b/kodev @@ -113,6 +113,7 @@ SUPPORTED_TARGETS=" kindlepw2 With compiler optimizations for Kindle models >= Paperwhite 2 kindle-legacy Needed only for Kindle2/3/DXG kobo + sony-prstux android pocketbook ubuntu-touch @@ -176,6 +177,10 @@ ${SUPPORTED_TARGETS}" make TARGET=kobo assert_ret_zero $? ;; + sony-prstux) + make TARGET=sony-prstux + assert_ret_zero $? + ;; kindle-legacy) make TARGET=kindle-legacy assert_ret_zero $? @@ -252,6 +257,9 @@ ${SUPPORTED_TARGETS}" kobo) make TARGET=kobo clean ;; + sony-prstux) + make TARGET=sony-prstux clean + ;; kindle-legacy) make TARGET=kindle-legacy clean ;; @@ -348,6 +356,10 @@ ${SUPPORTED_RELEASE_TARGETS}" kodev-build kobo make TARGET=kobo update ;; + sony-prstux) + kodev-build sony-prstux + make TARGET=sony-prstux update + ;; kindle-legacy) kodev-build kindle-legacy make TARGET=kindle-legacy update diff --git a/platform/sony-prstux/resume.sh b/platform/sony-prstux/resume.sh new file mode 100755 index 000000000..41a2acd1f --- /dev/null +++ b/platform/sony-prstux/resume.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -x + +# wake all devices up +echo on >/sys/power/state + +# go back to conservative governor +echo conservative >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor + +# wait for resume to complete +cat /sys/power/wait_for_fb_wake diff --git a/platform/sony-prstux/set-wifi.sh b/platform/sony-prstux/set-wifi.sh new file mode 100755 index 000000000..3e422e0b7 --- /dev/null +++ b/platform/sony-prstux/set-wifi.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -x +if [ "$1" = "on" ]; then + wmiconfig -i wlan0 --wlan enable + wmiconfig -i wlan0 --setreassocmode 0 + wmiconfig -i wlan0 --power maxperf + /sbin/wpa_supplicant -B -i wlan0 -D wext -C /var/run/wpa_supplicant -f /var/log/wpa_supplicant.log +else + if [ "$(pidof wpa_supplicant)" != "" ]; then + kill "$(pidof wpa_supplicant)" + fi + wmiconfig -i wlan0 --wlan disable +fi diff --git a/platform/sony-prstux/suspend.sh b/platform/sony-prstux/suspend.sh new file mode 100755 index 000000000..254a0932c --- /dev/null +++ b/platform/sony-prstux/suspend.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -x + +# enter sleep, disabling all devices except CPU +echo mem >/sys/power/state + +# disable WiFi +./set-wifi.sh off + +# set minimum CPU frequency during sleep +echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor + +# wait for sleep to complete +cat /sys/power/wait_for_fb_sleep diff --git a/plugins/autosuspend.koplugin/main.lua b/plugins/autosuspend.koplugin/main.lua index d2684ba8c..ff3ee0c6b 100644 --- a/plugins/autosuspend.koplugin/main.lua +++ b/plugins/autosuspend.koplugin/main.lua @@ -1,6 +1,6 @@ local Device = require("device") -if not Device:isKobo() and not Device:isSDL() then return { disabled = true, } end +if not Device:isKobo() and not Device:isSDL() and not Device:isSonyPRSTUX() then return { disabled = true, } end local DataStorage = require("datastorage") local LuaSettings = require("luasettings")