Kobo Elipsa support (#7986)

Includes a few minor cleanups along the way ;).
pull/8004/head
NiLuJe 3 years ago committed by GitHub
parent b31b7728db
commit ae35e898fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1 +1 @@
Subproject commit 13f0d3decc2c5c4cc7a1f17dfad8fd5d53721e68
Subproject commit 85d96920d952ccb0f47f054df179a230a2a7544f

@ -434,7 +434,7 @@ To:
},
}
}
if Device:isKobo() then
if Device:isKobo() and not Device:isSunxi() then
table.insert(self.menu_items.developer_options.sub_item_table, {
text = _("Disable forced 8-bit pixel depth"),
checked_func = function()
@ -524,7 +524,7 @@ To:
if Device:hasEinkScreen() and Device:isKobo() then
table.insert(self.menu_items.developer_options.sub_item_table, {
-- @translators Highly technical (ioctl is a Linux API call, the uppercase stuff is a constant). What's translatable is essentially only the action ("bypass") and the article.
text = _("Bypass the MXCFB_WAIT_FOR_* ioctls"),
text = _("Bypass the WAIT_FOR ioctls"),
checked_func = function()
local mxcfb_bypass_wait_for
if G_reader_settings:has("mxcfb_bypass_wait_for") then

@ -88,6 +88,7 @@ local linux_evdev_key_code_map = {
[C.BTN_TOOL_RUBBER] = "BTN_TOOL_RUBBER",
[C.BTN_TOUCH] = "BTN_TOUCH",
[C.BTN_STYLUS] = "BTN_STYLUS",
[C.BTN_STYLUS2] = "BTN_STYLUS2",
}
local linux_evdev_abs_code_map = {
@ -589,6 +590,9 @@ function Input:handleTouchEv(ev)
self:setCurrentMtSlot("x", ev.value)
elseif ev.code == C.ABS_MT_POSITION_Y then
self:setCurrentMtSlot("y", ev.value)
elseif ev.code == C.ABS_MT_PRESSURE and ev.value == 0 then
-- Drop hovering pen events
self:setCurrentMtSlot("id", -1)
-- code to emulate mt protocol on kobos
-- we "confirm" abs_x, abs_y only when pressure ~= 0
@ -1101,30 +1105,33 @@ function Input:waitEvent(now, deadline)
-- We're guaranteed that ev is an array of event tables. Might be an array of *one* event, but an array nonetheless ;).
for __, event in ipairs(ev) do
if DEBUG.is_on then
-- NOTE: This is rather spammy and computationally intensive,
-- and we can't conditionally prevent evalutation of function arguments,
-- so, just hide the whole thing behind a branch ;).
DEBUG:logEv(event)
if event.type == C.EV_KEY then
logger.dbg(string.format(
"key event => code: %d (%s), value: %s, time: %d.%d",
"key event => code: %d (%s), value: %s, time: %d.%06d",
event.code, self.event_map[event.code] or linux_evdev_key_code_map[event.code], event.value,
event.time.sec, event.time.usec))
elseif event.type == C.EV_SYN then
logger.dbg(string.format(
"input event => type: %d (%s), code: %d (%s), value: %s, time: %d.%d",
"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_syn_code_map[event.code], event.value,
event.time.sec, event.time.usec))
elseif event.type == C.EV_ABS then
logger.dbg(string.format(
"input event => type: %d (%s), code: %d (%s), value: %s, time: %d.%d",
"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_abs_code_map[event.code], event.value,
event.time.sec, event.time.usec))
elseif event.type == C.EV_MSC then
logger.dbg(string.format(
"input event => type: %d (%s), code: %d (%s), value: %s, time: %d.%d",
"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))
else
logger.dbg(string.format(
"input event => type: %d (%s), code: %d, value: %s, time: %d.%d",
"input event => type: %d (%s), code: %d, value: %s, time: %d.%06d",
event.type, linux_evdev_type_map[event.type], event.code, event.value,
event.time.sec, event.time.usec))
end

@ -5,6 +5,11 @@ local logger = require("logger")
local util = require("ffi/util")
local _ = require("gettext")
-- We're going to need a few <linux/fb.h> constants...
local ffi = require("ffi")
local C = ffi.C
require("ffi/linux_fb_h")
local function yes() return true end
local function no() return false end
@ -53,6 +58,16 @@ local Kobo = Generic:new{
isMk7 = no,
-- MXCFB_WAIT_FOR_UPDATE_COMPLETE ioctls are generally reliable
hasReliableMxcWaitFor = yes,
-- Sunxi devices require a completely different fb backend...
isSunxi = no,
-- On sunxi, "native" panel layout used to compute the G2D rotation handle (e.g., deviceQuirks.nxtBootRota in FBInk).
boot_rota = nil,
-- Standard sysfs path to the battery directory
battery_sysfs = "/sys/class/power_supply/mc13892_bat",
-- Stable path to the NTX input device
ntx_dev = "/dev/input/event0",
-- Stable path to the Touch input device
touch_dev = "/dev/input/event1",
}
--- @todo hasKeys for some devices?
@ -288,6 +303,22 @@ local KoboLuna = Kobo:new{
display_dpi = 212,
}
-- Kobo Elipsa
local KoboEuropa = Kobo:new{
model = "Kobo_europa",
isSunxi = yes,
canToggleChargingLED = yes,
hasFrontlight = yes,
hasGSensor = yes,
canToggleGSensor = yes,
misc_ntx_gsensor_protocol = true,
display_dpi = 227,
boot_rota = C.FB_ROTATE_CCW,
battery_sysfs = "/sys/class/power_supply/battery",
ntx_dev = "/dev/input/by-path/platform-ntx_event0-event",
touch_dev = "/dev/input/by-path/platform-0-0010-event",
}
function Kobo:init()
-- Check if we need to disable MXCFB_WAIT_FOR_UPDATE_COMPLETE ioctls...
local mxcfb_bypass_wait_for
@ -297,16 +328,29 @@ function Kobo:init()
mxcfb_bypass_wait_for = not self:hasReliableMxcWaitFor()
end
self.screen = require("ffi/framebuffer_mxcfb"):new{
device = self,
debug = logger.dbg,
is_always_portrait = self.isAlwaysPortrait(),
mxcfb_bypass_wait_for = mxcfb_bypass_wait_for,
}
if self.screen.fb_bpp == 32 then
-- Ensure we decode images properly, as our framebuffer is BGRA...
logger.info("Enabling Kobo @ 32bpp BGR tweaks")
self.hasBGRFrameBuffer = yes
if self:isSunxi() then
self.screen = require("ffi/framebuffer_sunxi"):new{
device = self,
debug = logger.dbg,
is_always_portrait = self.isAlwaysPortrait(),
mxcfb_bypass_wait_for = mxcfb_bypass_wait_for,
boot_rota = self.boot_rota,
}
-- Sunxi means no HW inversion :(
self.canHWInvert = no
else
self.screen = require("ffi/framebuffer_mxcfb"):new{
device = self,
debug = logger.dbg,
is_always_portrait = self.isAlwaysPortrait(),
mxcfb_bypass_wait_for = mxcfb_bypass_wait_for,
}
if self.screen.fb_bpp == 32 then
-- Ensure we decode images properly, as our framebuffer is BGRA...
logger.info("Enabling Kobo @ 32bpp BGR tweaks")
self.hasBGRFrameBuffer = yes
end
end
-- Automagically set this so we never have to remember to do it manually ;p
@ -318,17 +362,23 @@ function Kobo:init()
self.canHWDither = yes
end
self.powerd = require("device/kobo/powerd"):new{device = self}
self.powerd = require("device/kobo/powerd"):new{
device = self,
battery_sysfs = self.battery_sysfs,
}
-- NOTE: For the Forma, with the buttons on the right, 193 is Top, 194 Bottom.
self.input = require("device/input"):new{
device = self,
event_map = {
[35] = "SleepCover", -- KEY_H, Elipsa
[59] = "SleepCover",
[90] = "LightButton",
[102] = "Home",
[116] = "Power",
[193] = "RPgBack",
[194] = "RPgFwd",
[331] = "Eraser",
[332] = "Highlighter",
},
event_map_adapter = {
SleepCover = function(ev)
@ -350,8 +400,8 @@ function Kobo:init()
Generic.init(self)
-- When present, event2 is the raw accelerometer data (3-Axis Orientation/Motion Detection)
self.input.open("/dev/input/event0") -- Various HW Buttons, Switches & Synthetic NTX events
self.input.open("/dev/input/event1")
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)
self.input.open("fake_events")
@ -791,7 +841,8 @@ function Kobo:toggleChargingLED(toggle)
-- we've seen *extremely* weird behavior in the past when playing with it on older devices (c.f., #5479).
-- In fact, Nickel itself doesn't provide this feature on said older devices
-- (when it does, it's an option in the Energy saving settings),
-- which is why we also limit ourselves to "true" Mk. 7 devices.
-- which is why we also limit ourselves to "true" on devices where this was tested.
-- c.f., drivers/misc/ntx_misc_light.c
local f = io.open("/sys/devices/platform/ntx_led/lit", "w")
if not f then
logger.err("cannot open /sys/devices/platform/ntx_led/lit for writing!")
@ -800,9 +851,18 @@ function Kobo:toggleChargingLED(toggle)
-- c.f., strace -fittvyy -e trace=ioctl,file,signal,ipc,desc -s 256 -o /tmp/nickel.log -p $(pidof -s nickel) &
-- This was observed on a Forma, so I'm mildly hopeful that it's safe on other Mk. 7 devices ;).
-- NOTE: ch stands for channel, cur for current, dc for duty cycle. c.f., the driver source.
if toggle == true then
-- NOTE: Technically, Nickel forces a toggle off before that, too.
-- But since we do that on startup, it shouldn't be necessary here...
if self:isSunxi() then
f:write("ch 3")
f:flush()
f:write("cur 1")
f:flush()
f:write("dc 63")
f:flush()
end
f:write("ch 4")
f:flush()
f:write("cur 1")
@ -881,6 +941,8 @@ elseif codename == "storm" then
return KoboStorm
elseif codename == "luna" then
return KoboLuna
elseif codename == "europa" then
return KoboEuropa
else
error("unrecognized Kobo model "..codename)
end

@ -5,9 +5,6 @@ local SysfsLight = require ("device/sysfs_light")
local ffiUtil = require("ffi/util")
local RTC = require("ffi/rtc")
local batt_state_folder =
"/sys/devices/platform/pmic_battery.1/power_supply/mc13892_bat/"
-- Here, we only deal with the real hw intensity.
-- Dealing with toggling and remembering/restoring
-- previous intensity when toggling/untoggling is done
@ -17,8 +14,7 @@ local KoboPowerD = BasePowerD:new{
fl_min = 0, fl_max = 100,
fl = nil,
batt_capacity_file = batt_state_folder .. "capacity",
is_charging_file = batt_state_folder .. "status",
battery_sysfs = nil,
fl_warmth_min = 0, fl_warmth_max = 100,
fl_warmth = nil,
auto_warmth = false,
@ -108,6 +104,10 @@ function KoboPowerD:_syncKoboLightOnStart()
end
function KoboPowerD:init()
-- Setup the sysfs paths
self.batt_capacity_file = self.battery_sysfs .. "/capacity"
self.is_charging_file = self.battery_sysfs .. "/status"
-- Default values in case self:_syncKoboLightOnStart() does not find
-- any previously saved setting (and for unit tests where it will
-- not be called)

@ -35,7 +35,7 @@ fi
wpa_cli terminate
[ "${WIFI_MODULE}" != "8189fs" ] && [ "${WIFI_MODULE}" != "8192es" ] && [ "${WIFI_MODULE}" != "8821cs" ] && wlarm_le -i "${INTERFACE}" down
[ "${WIFI_MODULE}" = "dhd" ] && wlarm_le -i "${INTERFACE}" down
ifconfig "${INTERFACE}" down
# Some sleep in between may avoid system getting hung

@ -28,12 +28,19 @@ fi
# Moar sleep!
usleep 250000
# NOTE: Used to be exported in WIFI_MODULE_PATH before FW 4.23
grep -q "${WIFI_MODULE}" "/proc/modules" || insmod "/drivers/${PLATFORM}/wifi/${WIFI_MODULE}.ko"
if ! grep -q "${WIFI_MODULE}" "/proc/modules"; then
if [ -e "/drivers/${PLATFORM}/wifi/${WIFI_MODULE}.ko" ]; then
insmod "/drivers/${PLATFORM}/wifi/${WIFI_MODULE}.ko"
elif [ -e "/drivers/${PLATFORM}/${WIFI_MODULE}.ko" ]; then
# NOTE: Modules are unsorted on Mk. 8
insmod "/drivers/${PLATFORM}/${WIFI_MODULE}.ko"
fi
fi
# Race-y as hell, don't try to optimize this!
sleep 1
ifconfig "${INTERFACE}" up
[ "${WIFI_MODULE}" != "8189fs" ] && [ "${WIFI_MODULE}" != "8192es" ] && [ "${WIFI_MODULE}" != "8821cs" ] && wlarm_le -i "${INTERFACE}" up
[ "${WIFI_MODULE}" = "dhd" ] && wlarm_le -i "${INTERFACE}" up
pkill -0 wpa_supplicant ||
env -u LD_LIBRARY_PATH \

@ -241,6 +241,36 @@ if [ -z "${INTERFACE}" ]; then
export INTERFACE
fi
# We'll enforce UR in ko_do_fbdepth, so make sure further FBInk usage (USBMS)
# will also enforce UR... (Only actually meaningful on sunxi).
if [ "${PLATFORM}" = "b300-ntx" ]; then
export FBINK_FORCE_ROTA=0
# And we also cannot use batched updates for the crash screens, as buffers are private,
# so each invocation essentially draws in a different buffer...
FBINK_BATCH_FLAG=""
# Same idea for backgroundless...
FBINK_BGLESS_FLAG="-B GRAY9"
# It also means we need explicit background padding in the OT codepath...
FBINK_OT_PADDING=",padding=BOTH"
# Make sure we poke the right input device
KOBO_TS_INPUT="/dev/input/by-path/platform-0-0010-event"
else
FBINK_BATCH_FLAG="-b"
FBINK_BGLESS_FLAG="-O"
FBINK_OT_PADDING=""
KOBO_TS_INPUT="/dev/input/event1"
fi
# Make sure we only keep two cores online on the Elipsa.
# NOTE: That's a bit optimistic, we might actually need to tone that down to one,
# and just toggle the second one on demand (e.g., PDF).
if [ "${PRODUCT}" = "europa" ]; then
echo "1" >"/sys/devices/system/cpu/cpu1/online"
echo "0" >"/sys/devices/system/cpu/cpu2/online"
echo "0" >"/sys/devices/system/cpu/cpu3/online"
fi
# We'll want to ensure Portrait rotation to allow us to use faster blitting codepaths @ 8bpp,
# so remember the current one before fbdepth does its thing.
IFS= read -r ORIG_FB_ROTA <"/sys/class/graphics/fb0/rotate"
@ -269,6 +299,15 @@ esac
# The actual swap is done in a function, because we can disable it in the Developer settings, and we want to honor it on restart.
ko_do_fbdepth() {
# On sunxi, the fb state is meaningless, and the minimal disp fb doesn't actually support 8bpp anyway,
# so just make sure we're set @ UR.
if [ "${PLATFORM}" = "b300-ntx" ]; then
echo "Making sure that rotation is set to Portrait" >>crash.log 2>&1
./fbdepth -d 32 -R UR >>crash.log 2>&1
return
fi
# Check if the swap has been disabled...
if grep -q '\["dev_startup_no_fbdepth"\] = true' 'settings.reader.lua' 2>/dev/null; then
# Swap back to the original bitdepth (in case this was a restart)
@ -280,14 +319,14 @@ ko_do_fbdepth() {
./fbdepth -d "${ORIG_FB_BPP}" -r "${ORIG_FB_ROTA}" >>crash.log 2>&1
else
echo "Making sure we're using the original fb bitdepth @ ${ORIG_FB_BPP}bpp, and that rotation is set to Portrait" >>crash.log 2>&1
./fbdepth -d "${ORIG_FB_BPP}" -r -1 >>crash.log 2>&1
./fbdepth -d "${ORIG_FB_BPP}" -R UR >>crash.log 2>&1
fi
fi
else
# Swap to 8bpp if things looke sane
if [ -n "${ORIG_FB_BPP}" ]; then
echo "Switching fb bitdepth to 8bpp & rotation to Portrait" >>crash.log 2>&1
./fbdepth -d 8 -r -1 >>crash.log 2>&1
./fbdepth -d 8 -R UR >>crash.log 2>&1
fi
fi
}
@ -363,21 +402,25 @@ while [ ${RETURN_VALUE} -ne 0 ]; do
# Height @ ~56.7%, w/ a margin worth 1.5 lines
bombHeight=$((viewHeight / 2 + viewHeight / 15))
bombMargin=$((FONTH + FONTH / 2))
# Start with a big gray screen of death, and our friendly old school crash icon ;)
# U+1F4A3, the hard way, because we can't use \u or \U escape sequences...
# shellcheck disable=SC2039,SC3003
./fbink -q ${FBINK_BATCH_FLAG} -c -B GRAY9 -m -t regular=./fonts/freefont/FreeSerif.ttf,px=${bombHeight},top=${bombMargin} -W GL16 -- $'\xf0\x9f\x92\xa3'
# With a little notice at the top of the screen, on a big gray screen of death ;).
./fbink -q -b -c -B GRAY9 -m -y 1 "Don't Panic! (Crash n°${CRASH_COUNT} -> ${RETURN_VALUE})"
./fbink -q ${FBINK_BATCH_FLAG} ${FBINK_BGLESS_FLAG} -m -y 1 "Don't Panic! (Crash n°${CRASH_COUNT} -> ${RETURN_VALUE})" -W GL16
if [ ${CRASH_COUNT} -eq 1 ]; then
# Warn that we're waiting on a tap to continue...
./fbink -q -b -O -m -y 2 "Tap the screen to continue."
./fbink -q ${FBINK_BATCH_FLAG} ${FBINK_BGLESS_FLAG} -m -y 2 "Tap the screen to continue." -W GL16
fi
# U+1F4A3, the hard way, because we can't use \u or \U escape sequences...
# shellcheck disable=SC2039,SC3003
./fbink -q -b -O -m -t regular=./fonts/freefont/FreeSerif.ttf,px=${bombHeight},top=${bombMargin} -- $'\xf0\x9f\x92\xa3'
# And then print the tail end of the log on the bottom of the screen...
crashLog="$(tail -n 25 crash.log | sed -e 's/\t/ /g')"
# The idea for the margins being to leave enough room for an fbink -Z bar, small horizontal margins, and a font size based on what 6pt looked like @ 265dpi
./fbink -q -b -O -t regular=./fonts/droid/DroidSansMono.ttf,top=$((viewHeight / 2 + FONTH * 2 + FONTH / 2)),left=$((viewWidth / 60)),right=$((viewWidth / 60)),px=$((viewHeight / 64)) -- "${crashLog}"
# So far, we hadn't triggered an actual screen refresh, do that now, to make sure everything is bundled in a single flashing refresh.
./fbink -q -f -s
# shellcheck disable=SC2086
./fbink -q ${FBINK_BATCH_FLAG} ${FBINK_BGLESS_FLAG} -t regular=./fonts/droid/DroidSansMono.ttf,top=$((viewHeight / 2 + FONTH * 2 + FONTH / 2)),left=$((viewWidth / 60)),right=$((viewWidth / 60)),px=$((viewHeight / 64))${FBINK_OT_PADDING} -W GL16 -- "${crashLog}"
if [ "${PLATFORM}" != "b300-ntx" ]; then
# So far, we hadn't triggered an actual screen refresh, do that now, to make sure everything is bundled in a single flashing refresh.
./fbink -q -f -s
fi
# Cue a lemming's faceplant sound effect!
{
@ -395,7 +438,7 @@ while [ ${RETURN_VALUE} -ne 0 ]; do
# NOTE: We don't actually care about what read read, we're just using it as a fancy sleep ;).
# i.e., we pause either until the 15s timeout, or until the user touches the screen.
# shellcheck disable=SC2039,SC3045
read -r -t 15 </dev/input/event1
read -r -t 15 <"${KOBO_TS_INPUT}"
fi
# Cycle the last crash timestamp
CRASH_PREV_TS=${CRASH_TS}

@ -14,6 +14,7 @@ cd /
unset OLDPWD
unset LC_ALL TESSDATA_PREFIX STARDICT_DATA_DIR EXT_FONT_DIR
unset KOREADER_DIR KO_DONT_GRAB_INPUT
unset FBINK_FORCE_ROTA
# Ensures fmon will restart. Note that we don't have to worry about reaping this, nickel kills on-animator.sh on start.
(
@ -24,8 +25,7 @@ unset KOREADER_DIR KO_DONT_GRAB_INPUT
) &
# Make sure we kill the Wi-Fi first, because nickel apparently doesn't like it if it's up... (cf. #1520)
# NOTE: That check is possibly wrong on PLATFORM == freescale (because I don't know if the sdio_wifi_pwr module exists there), but we don't terribly care about that.
if grep -q "sdio_wifi_pwr" "/proc/modules"; then
if grep -q "${WIFI_MODULE}" "/proc/modules"; then
killall -q -TERM restore-wifi-async.sh enable-wifi.sh obtain-ip.sh
cp -a "/etc/resolv.conf" "/tmp/resolv.ko"
old_hash="$(md5sum "/etc/resolv.conf" | cut -f1 -d' ')"
@ -56,7 +56,7 @@ if grep -q "sdio_wifi_pwr" "/proc/modules"; then
rm -f "/tmp/resolv.ko"
fi
wpa_cli terminate
[ "${WIFI_MODULE}" != "8189fs" ] && [ "${WIFI_MODULE}" != "8192es" ] && [ "${WIFI_MODULE}" != "8821cs" ] && wlarm_le -i "${INTERFACE}" down
[ "${WIFI_MODULE}" = "dhd" ] && wlarm_le -i "${INTERFACE}" down
ifconfig "${INTERFACE}" down
# NOTE: Kobo's busybox build is weird. rmmod appears to be modprobe in disguise, defaulting to the -r flag...
# But since there's currently no modules.dep file being shipped, nor do they include the depmod applet,
@ -65,14 +65,16 @@ if grep -q "sdio_wifi_pwr" "/proc/modules"; then
usleep 250000
rmmod "${WIFI_MODULE}"
if [ -n "${CPUFREQ_DVFS}" ]; then
echo "0" >"/sys/devices/platform/mxc_dvfs_core.0/enable"
# Leave Nickel in its usual state, don't try to use conservative
echo "userspace" >"/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
cat "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" >"/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
if grep -q "sdio_wifi_pwr" "/proc/modules"; then
if [ -n "${CPUFREQ_DVFS}" ]; then
echo "0" >"/sys/devices/platform/mxc_dvfs_core.0/enable"
# Leave Nickel in its usual state, don't try to use conservative
echo "userspace" >"/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
cat "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" >"/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
fi
usleep 250000
rmmod sdio_wifi_pwr
fi
usleep 250000
rmmod sdio_wifi_pwr
fi
unset CPUFREQ_DVFS CPUFREQ_CONSERVATIVE

Loading…
Cancel
Save