val->intval = battmgr->status.capacity;
break;
case POWER_SUPPLY_PROP_CAPACITY:
+ if (battmgr->status.percent == (unsigned int)-1)
+ return -ENODATA;
val->intval = battmgr->status.percent;
break;
case POWER_SUPPLY_PROP_TEMP:
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
battmgr->ac.online = source == BATTMGR_CHARGING_SOURCE_AC;
battmgr->usb.online = source == BATTMGR_CHARGING_SOURCE_USB;
battmgr->wireless.online = source == BATTMGR_CHARGING_SOURCE_WIRELESS;
+ if (battmgr->info.last_full_capacity != 0) {
+ /*
+ * 100 * battmgr->status.capacity can overflow a 32bit
+ * unsigned integer. FW readings are in m{W/A}h, which
+ * are multiplied by 1000 converting them to u{W/A}h,
+ * the format the power_supply API expects.
+ * To avoid overflow use the original value for dividend
+ * and convert the divider back to m{W/A}h, which can be
+ * done without any loss of precision.
+ */
+ battmgr->status.percent =
+ (100 * le32_to_cpu(resp->status.capacity)) /
+ (battmgr->info.last_full_capacity / 1000);
+ } else {
+ /*
+ * Let the sysfs handler know no data is available at
+ * this time.
+ */
+ battmgr->status.percent = (unsigned int)-1;
+ }
break;
case BATTMGR_BAT_DISCHARGE_TIME:
battmgr->status.discharge_time = le32_to_cpu(resp->time);