PowerD: Add a framework to report the status of auxiliary batteries

Implement it on the Kobo Sage, for the PowerCover

TouchMenu: Display auxiliary battery status

Kobo: More accurately report the PowerCover's charging status

i.e., try to actually figure out if the auxiliary battery is charging
instead of just checking the reader's battery (because that one will
often swap between the charging and discharging state as it drains the
aux battery...).

PowerD: Use a cached timestamp when doing battery pull checks
reviewable/pr8694/r1
NiLuJe 2 years ago committed by poire-z
parent 1084c6e151
commit dc98384177

@ -33,6 +33,7 @@ local Device = {
-- hardware feature tests: (these are functions!)
hasBattery = yes,
hasAuxBattery = no,
hasKeyboard = no,
hasKeys = no,
hasDPad = no,

@ -1,12 +1,15 @@
local TimeVal = require("ui/timeval")
local logger = require("logger")
local BasePowerD = {
fl_min = 0, -- min frontlight intensity
fl_max = 10, -- max frontlight intensity
fl_intensity = nil, -- frontlight intensity
battCapacity = 0, -- battery capacity
batt_capacity = 0, -- battery capacity
aux_batt_capacity = 0, -- auxiliary battery capacity
device = nil, -- device object
last_capacity_pull_time = 0, -- timestamp of last pull
last_capacity_pull_time = TimeVal:new{ sec = 0, usec = 0}, -- timestamp of last pull
last_aux_capacity_pull_time = TimeVal:new{ sec = 0, usec = 0}, -- timestamp of last pull
is_fl_on = false, -- whether the frontlight is on
}
@ -27,9 +30,12 @@ end
function BasePowerD:init() end
function BasePowerD:setIntensityHW(intensity) end
function BasePowerD:getCapacityHW() return 0 end
function BasePowerD:getAuxCapacityHW() return 0 end
function BasePowerD:isAuxBatteryConnectedHW() return false end
function BasePowerD:getDismissBatteryStatus() return self.battery_warning end
function BasePowerD:setDismissBatteryStatus(status) self.battery_warning = status end
function BasePowerD:isChargingHW() return false end
function BasePowerD:isAuxChargingHW() return false end
function BasePowerD:frontlightIntensityHW() return 0 end
function BasePowerD:isFrontlightOnHW() return self.fl_intensity > self.fl_min end
function BasePowerD:turnOffFrontlightHW() self:setIntensityHW(self.fl_min) end
@ -133,18 +139,41 @@ function BasePowerD:setIntensity(intensity)
end
function BasePowerD:getCapacity()
local now_ts = os.time()
if now_ts - self.last_capacity_pull_time >= 60 then
self.battCapacity = self:getCapacityHW()
-- NOTE: UIManager *should* be loaded at this point.
-- If that doesn't hold, c.f., :stateChanged below.
local UIManager = require("ui/uimanager")
local now_ts = UIManager:getTime()
if (now_ts - self.last_aux_capacity_pull_time):tonumber() >= 60 then
self.batt_capacity = self:getCapacityHW()
self.last_capacity_pull_time = now_ts
end
return self.battCapacity
return self.batt_capacity
end
function BasePowerD:isCharging()
return self:isChargingHW()
end
function BasePowerD:getAuxCapacity()
local UIManager = require("ui/uimanager")
local now_ts = UIManager:getTime()
if (now_ts - self.last_aux_capacity_pull_time):tonumber() >= 60 then
self.aux_batt_capacity = self:getAuxCapacityHW()
self.last_aux_capacity_pull_time = now_ts
end
return self.aux_batt_capacity
end
function BasePowerD:isAuxCharging()
return self:isAuxChargingHW()
end
function BasePowerD:isAuxBatteryConnected()
return self:isAuxBatteryConnectedHW()
end
function BasePowerD:stateChanged()
-- BasePowerD is loaded before UIManager. So we cannot broadcast events before UIManager has been loaded.
if package.loaded["ui/uimanager"] ~= nil then

@ -354,6 +354,8 @@ local KoboCadmus = Kobo:new{
},
boot_rota = C.FB_ROTATE_CW,
battery_sysfs = "/sys/class/power_supply/battery",
hasAuxBattery = yes,
aux_battery_sysfs = "/sys/class/misc/cilix",
ntx_dev = "/dev/input/by-path/platform-ntx_event0-event",
touch_dev = "/dev/input/by-path/platform-0-0010-event",
isSMP = yes,
@ -431,6 +433,7 @@ function Kobo:init()
self.powerd = require("device/kobo/powerd"):new{
device = self,
battery_sysfs = self.battery_sysfs,
aux_battery_sysfs = self.aux_battery_sysfs,
}
-- NOTE: For the Forma, with the buttons on the right, 193 is Top, 194 Bottom.
self.input = require("device/input"):new{

@ -14,6 +14,7 @@ local KoboPowerD = BasePowerD:new{
fl = nil,
battery_sysfs = nil,
aux_battery_sysfs = nil,
fl_warmth_min = 0, fl_warmth_max = 100,
fl_warmth = nil,
fl_was_on = nil,
@ -93,6 +94,28 @@ function KoboPowerD:init()
self.batt_capacity_file = self.battery_sysfs .. "/capacity"
self.is_charging_file = self.battery_sysfs .. "/status"
if self.device:hasAuxBattery() then
self.aux_batt_capacity_file = self.aux_battery_sysfs .. "/cilix_bat_capacity"
self.aux_batt_connected_file = self.aux_battery_sysfs .. "/cilix_conn" -- or "active"
self.aux_batt_charging_file = self.aux_battery_sysfs .. "/charge_status" -- "usb_conn" would not allow us to detect the "Full" state
self.getAuxCapacityHW = function(this)
return this:read_int_file(this.aux_batt_capacity_file)
end
self.isAuxBatteryConnectedHW = function(this)
return this:read_int_file(this.aux_batt_connected_file) == 1
end
self.isAuxChargingHW = function(this)
-- 0 when not charging
-- 3 when full
-- 2 when charging via DCP and/or when battery is high (> 70%)
local charge_status = this:read_int_file(this.aux_batt_charging_file)
return charge_status ~= 0 and charge_status ~= 3
end
end
-- Default values in case self:_syncKoboLightOnStart() does not find
-- any previously saved setting (and for unit tests where it will
-- not be called)

@ -636,6 +636,36 @@ function TouchMenu:_recalculatePageLayout()
self.page_num = math.ceil(#self.item_table / self.perpage)
end
local function getBatterySymbol(is_charging, capacity)
if is_charging then
return ""
else
if capacity >= 100 then
return ""
elseif capacity >= 90 then
return ""
elseif capacity >= 80 then
return ""
elseif capacity >= 70 then
return ""
elseif capacity >= 60 then
return ""
elseif capacity >= 50 then
return ""
elseif capacity >= 40 then
return ""
elseif capacity >= 30 then
return ""
elseif capacity >= 20 then
return ""
elseif capacity >= 10 then
return ""
else
return ""
end
end
end
function TouchMenu:updateItems()
local old_dimen = self.dimen and self.dimen:copy()
self:_recalculatePageLayout()
@ -687,37 +717,16 @@ function TouchMenu:updateItems()
local time_info_txt = util.secondsToHour(os.time(), G_reader_settings:isTrue("twelve_hour_clock"))
local powerd = Device:getPowerDevice()
local batt_lvl = powerd:getCapacity()
local batt_symbol
if powerd:isCharging() then
batt_symbol = ""
else
if batt_lvl >= 100 then
batt_symbol = ""
elseif batt_lvl >= 90 then
batt_symbol = ""
elseif batt_lvl >= 80 then
batt_symbol = ""
elseif batt_lvl >= 70 then
batt_symbol = ""
elseif batt_lvl >= 60 then
batt_symbol = ""
elseif batt_lvl >= 50 then
batt_symbol = ""
elseif batt_lvl >= 40 then
batt_symbol = ""
elseif batt_lvl >= 30 then
batt_symbol = ""
elseif batt_lvl >= 20 then
batt_symbol = ""
elseif batt_lvl >= 10 then
batt_symbol = ""
else
batt_symbol = ""
end
end
if Device:hasBattery() then
local batt_lvl = powerd:getCapacity()
local batt_symbol = getBatterySymbol(powerd:isCharging(), batt_lvl)
time_info_txt = BD.wrap(time_info_txt) .. " " .. BD.wrap("") .. BD.wrap(batt_symbol) .. BD.wrap(batt_lvl .. "%")
if Device:hasAuxBattery() and powerd:isAuxBatteryConnected() then
local aux_batt_lvl = powerd:getAuxCapacity()
local aux_batt_symbol = getBatterySymbol(powerd:isAuxCharging(), aux_batt_lvl)
time_info_txt = time_info_txt .. " " .. BD.wrap("+") .. BD.wrap(aux_batt_symbol) .. BD.wrap(aux_batt_lvl .. "%")
end
end
self.time_info:setText(time_info_txt)

Loading…
Cancel
Save