mirror of https://github.com/koreader/koreader
[feat] Add support for BQ/Fnac devices (#4294)
Adds support for devices found in https://blog.bq.com/es/bq-ereaders-developers-program/. Tested on BQ Cervantes 4 (last BQ device from 2017). It adds a new touch input event handler (discussed in #4275) which should work on other single touch devices (ie: Kobo Touch, Mini, Glo, Aura HD) but wasn't tested. Includes base bump with: [feat] Add BQ/Fnac device support (https://github.com/koreader/koreader-base/pull/745)pull/4299/head v2018.11
parent
d1298ff8e5
commit
1e69fae7bc
@ -1 +1 @@
|
||||
Subproject commit 42bc013b62c8039d733513e00a92dd6c70d8b421
|
||||
Subproject commit f13f1ce2ee42a64788ad80adb12d34197406b984
|
@ -0,0 +1,220 @@
|
||||
local Generic = require("device/generic/device")
|
||||
local TimeVal = require("ui/timeval")
|
||||
local logger = require("logger")
|
||||
|
||||
local function yes() return true end
|
||||
|
||||
local function getProductId()
|
||||
local ntxinfo_pcb = io.popen("/usr/bin/ntxinfo /dev/mmcblk0 | grep pcb | cut -d ':' -f2", "r")
|
||||
if not ntxinfo_pcb then return 0 end
|
||||
local product_id = tonumber(ntxinfo_pcb:read()) or 0
|
||||
ntxinfo_pcb:close()
|
||||
return product_id
|
||||
end
|
||||
|
||||
local Cervantes = Generic:new{
|
||||
model = "Cervantes",
|
||||
isCervantes = yes,
|
||||
isAlwaysPortrait = yes,
|
||||
isTouchDevice = yes,
|
||||
touch_legacy = true, -- SingleTouch input events
|
||||
touch_switch_xy = true,
|
||||
touch_mirrored_x = true,
|
||||
touch_probe_ev_epoch_time = true,
|
||||
hasOTAUpdates = yes,
|
||||
hasKeys = yes,
|
||||
internal_storage_mount_point = "/mnt/public/",
|
||||
}
|
||||
-- Cervantes Touch
|
||||
local CervantesTouch = Cervantes:new{
|
||||
model = "Cervantes Touch",
|
||||
display_dpi = 167,
|
||||
}
|
||||
-- Cervantes TouchLight / Fnac Touch Plus
|
||||
local CervantesTouchLight = Cervantes:new{
|
||||
model = "Cervantes TouchLight",
|
||||
display_dpi = 167,
|
||||
hasFrontlight = yes,
|
||||
}
|
||||
-- Cervantes 2013 / Fnac Touch Light
|
||||
local Cervantes2013 = Cervantes:new{
|
||||
model = "Cervantes 2013",
|
||||
display_dpi = 212,
|
||||
hasFrontlight = yes,
|
||||
}
|
||||
-- Cervantes 3 / Fnac Touch Light 2
|
||||
local Cervantes3 = Cervantes:new{
|
||||
model = "Cervantes 3",
|
||||
display_dpi = 300,
|
||||
hasFrontlight = yes,
|
||||
}
|
||||
-- Cervantes 4
|
||||
local Cervantes4 = Cervantes:new{
|
||||
model = "Cervantes 4",
|
||||
display_dpi = 300,
|
||||
hasFrontlight = yes,
|
||||
hasNaturalLight = yes,
|
||||
frontlight_settings = {
|
||||
frontlight_white = "/sys/class/backlight/lm3630a_ledb",
|
||||
frontlight_red = "/sys/class/backlight/lm3630a_leda",
|
||||
},
|
||||
}
|
||||
|
||||
-- input events
|
||||
local probeEvEpochTime
|
||||
-- this function will update itself after the first touch event
|
||||
probeEvEpochTime = function(self, ev)
|
||||
local now = TimeVal:now()
|
||||
-- This check should work as long as main UI loop is not blocked for more
|
||||
-- than 10 minute before handling the first touch event.
|
||||
if ev.time.sec <= now.sec - 600 then
|
||||
-- time is seconds since boot, force it to epoch
|
||||
probeEvEpochTime = function(_, _ev)
|
||||
_ev.time = TimeVal:now()
|
||||
end
|
||||
ev.time = now
|
||||
else
|
||||
-- time is already epoch time, no need to do anything
|
||||
probeEvEpochTime = function(_, _) end
|
||||
end
|
||||
end
|
||||
function Cervantes:initEventAdjustHooks()
|
||||
if self.touch_switch_xy then
|
||||
self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY)
|
||||
end
|
||||
if self.touch_mirrored_x then
|
||||
self.input:registerEventAdjustHook(
|
||||
self.input.adjustTouchMirrorX,
|
||||
self.screen:getWidth()
|
||||
)
|
||||
end
|
||||
if self.touch_probe_ev_epoch_time then
|
||||
self.input:registerEventAdjustHook(function(_, ev)
|
||||
probeEvEpochTime(_, ev)
|
||||
end)
|
||||
end
|
||||
|
||||
if self.touch_legacy then
|
||||
self.input.handleTouchEv = self.input.handleTouchEvLegacy
|
||||
end
|
||||
end
|
||||
|
||||
function Cervantes:init()
|
||||
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg}
|
||||
self.powerd = require("device/cervantes/powerd"):new{device = self}
|
||||
self.input = require("device/input"):new{
|
||||
device = self,
|
||||
event_map = {
|
||||
[61] = "Home",
|
||||
[116] = "Power",
|
||||
}
|
||||
}
|
||||
self.input.open("/dev/input/event0") -- Keys
|
||||
self.input.open("/dev/input/event1") -- touchscreen
|
||||
self.input.open("fake_events") -- usb events
|
||||
self:initEventAdjustHooks()
|
||||
Generic.init(self)
|
||||
end
|
||||
|
||||
function Cervantes: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 Cervantes:saveSettings()
|
||||
self.powerd:saveSettings()
|
||||
end
|
||||
|
||||
-- wireless
|
||||
function Cervantes:initNetworkManager(NetworkMgr)
|
||||
function NetworkMgr:turnOffWifi(complete_callback)
|
||||
logger.info("Cervantes: disabling WiFi")
|
||||
os.execute("./disable-wifi.sh")
|
||||
if complete_callback then
|
||||
complete_callback()
|
||||
end
|
||||
end
|
||||
function NetworkMgr:turnOnWifi(complete_callback)
|
||||
logger.info("Cervantes: enabling WiFi")
|
||||
os.execute("./enable-wifi.sh")
|
||||
self:showNetworkMenu(complete_callback)
|
||||
end
|
||||
NetworkMgr:setWirelessBackend("wpa_supplicant", {ctrl_interface = "/var/run/wpa_supplicant/eth0"})
|
||||
function NetworkMgr:obtainIP()
|
||||
os.execute("./obtain-ip.sh")
|
||||
end
|
||||
function NetworkMgr:releaseIP()
|
||||
os.execute("./release-ip.sh")
|
||||
end
|
||||
function NetworkMgr:restoreWifiAsync()
|
||||
os.execute("./restore-wifi-async.sh")
|
||||
end
|
||||
function NetworkMgr:isWifiOn()
|
||||
return 0 == os.execute("lsmod | grep -q 8189fs")
|
||||
end
|
||||
end
|
||||
|
||||
-- screensaver
|
||||
function Cervantes:supportsScreensaver()
|
||||
return true
|
||||
end
|
||||
function Cervantes: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 Cervantes: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
|
||||
|
||||
-- power functions: suspend, resume, reboot, poweroff
|
||||
function Cervantes:suspend()
|
||||
os.execute("./suspend.sh")
|
||||
end
|
||||
function Cervantes:resume()
|
||||
os.execute("./resume.sh")
|
||||
end
|
||||
function Cervantes:reboot()
|
||||
os.execute("reboot")
|
||||
end
|
||||
function Cervantes:powerOff()
|
||||
os.execute("halt")
|
||||
end
|
||||
|
||||
-------------- device probe ------------
|
||||
local product_id = getProductId()
|
||||
|
||||
if product_id == 22 then
|
||||
return CervantesTouch
|
||||
elseif product_id == 23 then
|
||||
return CervantesTouchLight
|
||||
elseif product_id == 33 then
|
||||
return Cervantes2013
|
||||
elseif product_id == 51 then
|
||||
return Cervantes3
|
||||
elseif product_id == 68 then
|
||||
return Cervantes4
|
||||
else
|
||||
error("unrecognized Cervantes: board id " .. product_id)
|
||||
end
|
@ -0,0 +1,210 @@
|
||||
local BasePowerD = require("device/generic/powerd")
|
||||
local SysfsLight = require ("device/sysfs_light")
|
||||
local PluginShare = require("pluginshare")
|
||||
|
||||
local battery_sysfs = "/sys/devices/platform/pmic_battery.1/power_supply/mc13892_bat/"
|
||||
|
||||
local CervantesPowerD = BasePowerD:new{
|
||||
fl = nil,
|
||||
fl_warmth = nil,
|
||||
auto_warmth = false,
|
||||
max_warmth_hour = 23,
|
||||
|
||||
fl_min = 0,
|
||||
fl_max = 100,
|
||||
capacity_file = battery_sysfs .. 'capacity',
|
||||
status_file = battery_sysfs .. 'status'
|
||||
}
|
||||
|
||||
function CervantesPowerD:_syncLightOnStart()
|
||||
-- We can't read value from the OS or hardware.
|
||||
-- Use last values stored in koreader settings.
|
||||
local new_intensity = G_reader_settings:readSetting("frontlight_intensity") or nil
|
||||
local is_frontlight_on = G_reader_settings:readSetting("is_frontlight_on") or nil
|
||||
local new_warmth, auto_warmth = nil
|
||||
|
||||
if self.fl_warmth ~= nil then
|
||||
new_warmth = G_reader_settings:readSetting("frontlight_warmth") or nil
|
||||
auto_warmth = G_reader_settings:readSetting("frontlight_auto_warmth") or nil
|
||||
end
|
||||
|
||||
if new_intensity ~= nil then
|
||||
self.hw_intensity = new_intensity
|
||||
end
|
||||
|
||||
if is_frontlight_on ~= nil then
|
||||
self.initial_is_fl_on = is_frontlight_on
|
||||
end
|
||||
|
||||
local max_warmth_hour =
|
||||
G_reader_settings:readSetting("frontlight_max_warmth_hour")
|
||||
if max_warmth_hour then
|
||||
self.max_warmth_hour = max_warmth_hour
|
||||
end
|
||||
if auto_warmth then
|
||||
self.auto_warmth = true
|
||||
self:calculateAutoWarmth()
|
||||
elseif new_warmth ~= nil then
|
||||
self.fl_warmth = new_warmth
|
||||
end
|
||||
|
||||
if self.initial_is_fl_on == false and self.hw_intensity == 0 then
|
||||
self.hw_intensity = 1
|
||||
end
|
||||
end
|
||||
|
||||
function CervantesPowerD:init()
|
||||
-- Default values in case self:_syncLightOnStart() does not find
|
||||
-- any previously saved setting (and for unit tests where it will
|
||||
-- not be called)
|
||||
self.hw_intensity = 20
|
||||
self.initial_is_fl_on = true
|
||||
self.autowarmth_job_running = false
|
||||
|
||||
if self.device.hasFrontlight() then
|
||||
if self.device.hasNaturalLight() then
|
||||
local nl_config = G_reader_settings:readSetting("natural_light_config")
|
||||
if nl_config then
|
||||
for key,val in pairs(nl_config) do
|
||||
self.device.frontlight_settings[key] = val
|
||||
end
|
||||
end
|
||||
self.fl = SysfsLight:new(self.device.frontlight_settings)
|
||||
self.fl_warmth = 0
|
||||
self:_syncLightOnStart()
|
||||
else
|
||||
local kobolight = require("ffi/kobolight")
|
||||
local ok, light = pcall(kobolight.open)
|
||||
if ok then
|
||||
self.fl = light
|
||||
self:_syncLightOnStart()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CervantesPowerD:saveSettings()
|
||||
if self.device.hasFrontlight() then
|
||||
-- Store BasePowerD values into settings (and not our hw_intensity, so
|
||||
-- that if frontlight was toggled off, we save and restore the previous
|
||||
-- untoggled intensity and toggle state at next startup)
|
||||
local cur_intensity = self.fl_intensity
|
||||
local cur_is_fl_on = self.is_fl_on
|
||||
local cur_warmth = self.fl_warmth
|
||||
local cur_auto_warmth = self.auto_warmth
|
||||
local cur_max_warmth_hour = self.max_warmth_hour
|
||||
-- Save intensity to koreader settings
|
||||
G_reader_settings:saveSetting("frontlight_intensity", cur_intensity)
|
||||
G_reader_settings:saveSetting("is_frontlight_on", cur_is_fl_on)
|
||||
if cur_warmth ~= nil then
|
||||
G_reader_settings:saveSetting("frontlight_warmth", cur_warmth)
|
||||
G_reader_settings:saveSetting("frontlight_auto_warmth", cur_auto_warmth)
|
||||
G_reader_settings:saveSetting("frontlight_max_warmth_hour", cur_max_warmth_hour)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CervantesPowerD:frontlightIntensityHW()
|
||||
return self.hw_intensity
|
||||
end
|
||||
|
||||
function CervantesPowerD:isFrontlightOnHW()
|
||||
if self.initial_is_fl_on ~= nil then -- happens only once after init()
|
||||
-- give initial state to BasePowerD, which will
|
||||
-- reset our self.hw_intensity to 0 if self.initial_is_fl_on is false
|
||||
local ret = self.initial_is_fl_on
|
||||
self.initial_is_fl_on = nil
|
||||
return ret
|
||||
end
|
||||
return self.hw_intensity > 0
|
||||
end
|
||||
|
||||
function CervantesPowerD:turnOffFrontlightHW()
|
||||
self:_setIntensity(0) -- will call setIntensityHW(0)
|
||||
end
|
||||
|
||||
function CervantesPowerD:setIntensityHW(intensity)
|
||||
if self.fl == nil then return end
|
||||
if self.fl_warmth == nil then
|
||||
self.fl:setBrightness(intensity)
|
||||
else
|
||||
self.fl:setNaturalBrightness(intensity, self.fl_warmth)
|
||||
end
|
||||
self.hw_intensity = intensity
|
||||
-- Now that we have set intensity, we need to let BasePowerD
|
||||
-- know about possibly changed frontlight state (if we came
|
||||
-- from light toggled off to some intensity > 0).
|
||||
self:_decideFrontlightState()
|
||||
end
|
||||
|
||||
function CervantesPowerD:setWarmth(warmth)
|
||||
if self.fl == nil then return end
|
||||
if not warmth and self.auto_warmth then
|
||||
self:calculateAutoWarmth()
|
||||
end
|
||||
self.fl_warmth = warmth or self.fl_warmth
|
||||
self.fl:setWarmth(self.fl_warmth)
|
||||
end
|
||||
|
||||
function CervantesPowerD:calculateAutoWarmth()
|
||||
local current_time = os.date("%H") + os.date("%M")/60
|
||||
local max_hour = self.max_warmth_hour
|
||||
local diff_time = max_hour - current_time
|
||||
if diff_time < 0 then
|
||||
diff_time = diff_time + 24
|
||||
end
|
||||
if diff_time < 12 then
|
||||
-- We are before bedtime. Use a slower progression over 5h.
|
||||
self.fl_warmth = math.max(20 * (5 - diff_time), 0)
|
||||
elseif diff_time > 22 then
|
||||
-- Keep warmth at maximum for two hours after bedtime.
|
||||
self.fl_warmth = 100
|
||||
else
|
||||
-- Between 2-4h after bedtime, return to zero.
|
||||
self.fl_warmth = math.max(100 - 50 * (22 - diff_time), 0)
|
||||
end
|
||||
self.fl_warmth = math.floor(self.fl_warmth + 0.5)
|
||||
|
||||
-- Enable background job for setting Warmth, if not already done.
|
||||
if not self.autowarmth_job_running then
|
||||
table.insert(PluginShare.backgroundJobs, {
|
||||
when = 180,
|
||||
repeated = true,
|
||||
executable = function()
|
||||
if self.auto_warmth then
|
||||
self:setWarmth()
|
||||
end
|
||||
end,
|
||||
})
|
||||
self.autowarmth_job_running = true
|
||||
end
|
||||
end
|
||||
|
||||
function CervantesPowerD:getCapacityHW()
|
||||
return self:read_int_file(self.capacity_file)
|
||||
end
|
||||
|
||||
function CervantesPowerD:isChargingHW()
|
||||
return self:read_str_file(self.status_file) == "Charging\n"
|
||||
end
|
||||
|
||||
function CervantesPowerD:beforeSuspend()
|
||||
if self.fl == nil then return end
|
||||
-- just turn off frontlight without remembering its state
|
||||
self.fl:setBrightness(0)
|
||||
end
|
||||
|
||||
function CervantesPowerD:afterResume()
|
||||
if self.fl == nil then return end
|
||||
-- just re-set it to self.hw_intensity that we haven't change on Suspend
|
||||
if self.fl_warmth == nil then
|
||||
self.fl:setBrightness(self.hw_intensity)
|
||||
else
|
||||
if self.auto_warmth then
|
||||
self:calculateAutoWarmth()
|
||||
end
|
||||
self.fl:setNaturalBrightness(self.hw_intensity, self.fl_warmth)
|
||||
end
|
||||
end
|
||||
|
||||
return CervantesPowerD
|
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
lsmod | grep -q g_file_storage || exit 1
|
||||
|
||||
modprobe -r g_file_storage
|
||||
sleep 1
|
||||
|
||||
PCB_ID=$(/usr/bin/ntxinfo /dev/mmcblk0 | grep pcb | cut -d ":" -f2)
|
||||
DISK=/dev/mmcblk
|
||||
|
||||
if [ "$PCB_ID" -eq 22 ] || [ "$PCB_ID" -eq 23 ]; then
|
||||
PARTITION="${DISK}0p7"
|
||||
else
|
||||
PARTITION="${DISK}0p4"
|
||||
fi
|
||||
|
||||
MOUNT_ARGS="noatime,nodiratime,shortname=mixed,utf8"
|
||||
|
||||
dosfsck -a -w "$PARTITION" >dosfsck.log 2>&1
|
||||
|
||||
mount -o "$MOUNT_ARGS" -t vfat "$PARTITION" /mnt/onboard
|
||||
|
||||
PARTITION=${DISK}1p1
|
||||
|
||||
[ -e "$PARTITION" ] && mount -o "$MOUNT_ARGS" -t vfat "$PARTITION" /mnt/sd
|
||||
|
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# disable wifi and remove all modules
|
||||
killall udhcpc default-script wpa_supplicant 2>/dev/null
|
||||
ifconfig eth0 down
|
||||
|
||||
if lsmod | grep -q 8189fs; then
|
||||
modprobe -r 8189fs
|
||||
fi
|
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
# based on https://github.com/baskerville/plato/blob/master/scripts/usb-enable.sh
|
||||
|
||||
lsmod | grep -q g_file_storage && exit 1
|
||||
|
||||
PCB_ID=$(/usr/bin/ntxinfo /dev/mmcblk0 | grep pcb | cut -d ":" -f2)
|
||||
DISK=/dev/mmcblk
|
||||
|
||||
if [ "$PCB_ID" -eq 22 ] || [ "$PCB_ID" -eq 23 ]; then
|
||||
PRODUCT_ID=${PRODUCT_ID:-"0xAD78"}
|
||||
PARTITIONS="${DISK}0p7"
|
||||
else
|
||||
PRODUCT_ID=${PRODUCT_ID:-"0xAD79"}
|
||||
PARTITIONS="${DISK}0p4"
|
||||
fi
|
||||
|
||||
[ -e "${DISK}1p1" ] && PARTITIONS="${PARTITIONS},${DISK}1p1"
|
||||
|
||||
sync
|
||||
echo 3 >/proc/sys/vm/drop_caches
|
||||
|
||||
for name in public sd; do
|
||||
DIR=/mnt/"$name"
|
||||
if grep -q "$DIR" /proc/mounts; then
|
||||
umount "$DIR" || umount -l "$DIR"
|
||||
fi
|
||||
done
|
||||
|
||||
MODULE_PARAMETERS="vendor=0x2A47 product=${PRODUCT_ID} vendor_id=BQ product_id=Cervantes"
|
||||
modprobe g_file_storage file="$PARTITIONS" stall=1 removable=1 "$MODULE_PARAMETERS"
|
||||
|
||||
sleep 1
|
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
WPA_SUPPLICANT_CONF="/mnt/private/koreader/wpa_supplicant.conf"
|
||||
CTRL_INTERFACE="/var/run/wpa_supplicant"
|
||||
|
||||
# create a new configuration if neccesary.
|
||||
if [ ! -f "$WPA_SUPPLICANT_CONF" ]; then
|
||||
echo "ctrl_interface=DIR=${CTRL_INTERFACE}" >"$WPA_SUPPLICANT_CONF"
|
||||
echo "update_config=1" >>"$WPA_SUPPLICANT_CONF"
|
||||
sync
|
||||
fi
|
||||
|
||||
if ! lsmod | grep -q 8189fs; then
|
||||
modprobe 8189fs
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
ifconfig eth0 up && sleep 1
|
||||
wpa_supplicant -B -D wext -i eth0 -s -O "$CTRL_INTERFACE" -c "$WPA_SUPPLICANT_CONF" 2>/dev/null
|
@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
# Standalone KOReader application for BQ Cervantes
|
||||
# this file is intended to replace /etc/rc.local on BQ developers firmware
|
||||
|
||||
# turn off the green flashing led.
|
||||
echo "ch 4" >/sys/devices/platform/pmic_light.1/lit
|
||||
echo "cur 0" >/sys/devices/platform/pmic_light.1/lit
|
||||
echo "dc 0" >/sys/devices/platform/pmic_light.1/lit
|
||||
|
||||
# ensure we have a proper time.
|
||||
if [ "$(date '+%Y')" -lt 2010 ]; then
|
||||
echo "Fixing date before 2010"
|
||||
date +%Y%m%d -s "20100101"
|
||||
hwclock -w
|
||||
fi
|
||||
|
||||
# assign public & private partition devices based on pcb.
|
||||
PCB_ID=$(/usr/bin/ntxinfo /dev/mmcblk0 | grep pcb | cut -d ":" -f2)
|
||||
if [ "$PCB_ID" -eq 22 ] || [ "$PCB_ID" -eq 23 ]; then
|
||||
PRIVATE="/dev/mmcblk0p5"
|
||||
PUBLIC="/dev/mmcblk0p7"
|
||||
else
|
||||
PRIVATE="/dev/mmcblk0p7"
|
||||
PUBLIC="/dev/mmcblk0p4"
|
||||
fi
|
||||
|
||||
# mount internal partitions
|
||||
mount $PRIVATE /mnt/private
|
||||
mount $PUBLIC /mnt/public
|
||||
|
||||
# mount sdcard if present
|
||||
if [ -b /dev/mmcblk1p1 ]; then
|
||||
mount /dev/mmcblk1p1 /mnt/sd
|
||||
fi
|
||||
|
||||
# remove wireless module since it wastes battery.
|
||||
if lsmod | grep -q 8189fs; then
|
||||
modprobe -r 8189fs
|
||||
fi
|
||||
|
||||
# start usbnet using BQ scripts (192.168.4.1/24 w/ hardcoded MAC addr)
|
||||
/usr/bin/usbup.sh
|
||||
/usr/sbin/inetd
|
||||
|
||||
# check if KOReader script exists.
|
||||
if [ -x /mnt/private/koreader/koreader.sh ]; then
|
||||
# yada! KOReader is installed and ready to run.
|
||||
while true; do
|
||||
/mnt/private/koreader/koreader.sh
|
||||
sleep 1
|
||||
done
|
||||
else
|
||||
# nothing to do, leaving rc.local.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
@ -0,0 +1,89 @@
|
||||
#!/bin/sh
|
||||
|
||||
export LC_ALL="en_US.UTF-8"
|
||||
|
||||
# working directory of koreader
|
||||
KOREADER_DIR="${0%/*}"
|
||||
|
||||
# we're always starting from our working directory
|
||||
cd "${KOREADER_DIR}" || exit
|
||||
|
||||
# update to new version from OTA directory
|
||||
ko_update_check() {
|
||||
NEWUPDATE="${KOREADER_DIR}/ota/koreader.updated.tar"
|
||||
INSTALLED="${KOREADER_DIR}/ota/koreader.installed.tar"
|
||||
if [ -f "${NEWUPDATE}" ]; then
|
||||
#./fbink -q -y -7 -pmh "Updating KOReader"
|
||||
# NOTE: See frontend/ui/otamanager.lua for a few more details on how we squeeze a percentage out of tar's checkpoint feature
|
||||
# NOTE: %B should always be 512 in our case, so let stat do part of the maths for us instead of using %s ;).
|
||||
FILESIZE="$(stat -c %b "${NEWUPDATE}")"
|
||||
BLOCKS="$((FILESIZE / 20))"
|
||||
export CPOINTS="$((BLOCKS / 100))"
|
||||
# shellcheck disable=SC2016
|
||||
./tar xf "${NEWUPDATE}" --strip-components=1 --no-same-permissions --no-same-owner --checkpoint="${CPOINTS}" --checkpoint-action=exec='./fbink -q -y -6 -P $(($TAR_CHECKPOINT/$CPOINTS))'
|
||||
fail=$?
|
||||
# Cleanup behind us...
|
||||
if [ "${fail}" -eq 0 ]; then
|
||||
mv "${NEWUPDATE}" "${INSTALLED}"
|
||||
# ./fbink -q -y -6 -pm "Update successful :)"
|
||||
# ./fbink -q -y -5 -pm "KOReader will start momentarily . . ."
|
||||
#else
|
||||
# # Huh ho...
|
||||
# ./fbink -q -y -6 -pmh "Update failed :("
|
||||
# ./fbink -q -y -5 -pm "KOReader may fail to function properly!"
|
||||
fi
|
||||
rm -f "${NEWUPDATE}" # always purge newupdate in all cases to prevent update loop
|
||||
unset BLOCKS CPOINTS
|
||||
fi
|
||||
}
|
||||
|
||||
# if no args were passed to the script, start the FM on public partition.
|
||||
if [ "$#" -eq 0 ]; then
|
||||
args="/mnt/public"
|
||||
else
|
||||
args="$*"
|
||||
fi
|
||||
|
||||
# NOTE: Keep doing an initial update check, in addition to one during the restart loop, so we can pickup potential updates of this very script...
|
||||
ko_update_check
|
||||
# If an update happened, and was successful, reexec
|
||||
if [ -n "${fail}" ] && [ "${fail}" -eq 0 ]; then
|
||||
# By now, we know we're in the right directory, and our script name is pretty much set in stone, so we can forgo using $0
|
||||
exec ./koreader.sh "${args}"
|
||||
fi
|
||||
|
||||
# load our own shared libraries if possible
|
||||
export LD_LIBRARY_PATH="${KOREADER_DIR}/libs"
|
||||
|
||||
# export trained OCR data directory
|
||||
export TESSDATA_PREFIX="data"
|
||||
|
||||
# export dict directory
|
||||
export STARDICT_DATA_DIR="data/dict"
|
||||
|
||||
# we keep at most 500k worth of crash log
|
||||
if [ -e crash.log ]; then
|
||||
tail -c 500000 crash.log >crash.log.new
|
||||
mv -f crash.log.new crash.log
|
||||
fi
|
||||
|
||||
# check if QBookApp was started before us, then
|
||||
# restart the application after leaving KOReader
|
||||
export STANDALONE="true"
|
||||
if pkill -0 QBookpp; then
|
||||
STANDALONE="false"
|
||||
fi
|
||||
|
||||
if [ "${STANDALONE}" != "true" ]; then
|
||||
stopapp.sh >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
RETURN_VALUE=85
|
||||
while [ "${RETURN_VALUE}" -eq 85 ]; do
|
||||
./reader.lua "${args}" >>crash.log 2>&1
|
||||
RETURN_VALUE=$?
|
||||
done
|
||||
|
||||
if [ "${STANDALONE}" != "true" ]; then
|
||||
restart.sh >/dev/null 2>&1
|
||||
fi
|
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
./release-ip.sh
|
||||
|
||||
# Use udhcpc to obtain IP.
|
||||
udhcpc -S -i eth0 -s /etc/udhcpc/default.script -t15 -T10 -A3 -b -q
|
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Release IP and shutdown udhcpc.
|
||||
pkill -9 -f '/bin/sh /etc/udhcpc/default.script'
|
||||
ifconfig eth0 0.0.0.0
|
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
RestoreWifi() {
|
||||
echo "[$(date)] restore-wifi-async.sh: Restarting WiFi"
|
||||
./enable-wifi.sh
|
||||
./obtain-ip.sh
|
||||
echo "[$(date)] restore-wifi-async.sh: Restarted WiFi"
|
||||
}
|
||||
|
||||
RestoreWifi &
|
@ -0,0 +1,4 @@
|
||||
#! /bin/sh
|
||||
|
||||
echo 0 >/sys/power/state-extended
|
||||
|
@ -0,0 +1,15 @@
|
||||
#! /bin/sh
|
||||
|
||||
# De-activate the touch screen.
|
||||
echo 1 >/sys/power/state-extended
|
||||
|
||||
# Prevent the following error on the last line:
|
||||
# *write error: Operation not permitted*.
|
||||
sleep 2
|
||||
|
||||
# Synchronize the file system.
|
||||
sync
|
||||
|
||||
# Suspend to RAM.
|
||||
echo mem >/sys/power/state
|
||||
|
Loading…
Reference in New Issue