Power Supply 模块分析
1. 模块定位与核心价值
1.1 模块定位
power_supply 是华为MATE X5电源管理子系统的电源设备抽象层,作为Linux内核标准power_supply框架与华为电源驱动之间的适配桥梁。它封装了6种电源类型(电池、原始电池、辅助电池、市电、USB、无线充电),为上层应用和Android框架提供统一的电源属性访问接口。
1.2 核心价值
标准化适配:将华为自定义的电源驱动适配到Linux标准power_supply框架
多电源支持:同时管理多种电源类型(主电池、辅助电池、充电器等)
回调机制:通过ops注册机制解耦底层驱动和上层框架
应用层封装:提供简化的应用层接口,屏蔽底层实现细节
灵活配置:支持通过DTS配置启用/禁用特定电源类型
1.3 在Android系统中的位置
┌─────────────────────────────────────────────────────────┐
│ Android Framework (BatteryService) │
└────────────────────┬────────────────────────────────────┘
│ /sys/class/power_supply/
┌────────────────────┴────────────────────────────────────┐
│ Linux Power Supply Framework (内核标准) │
└────────────────────┬────────────────────────────────────┘
│ power_supply_register()
┌────────────────────┴────────────────────────────────────┐
│ power_supply Module (适配层) ← 当前模块 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Battery │ │ USB │ │ Wireless │ ... │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
└───────┼─────────────┼─────────────┼────────────────────┘
│ │ │ power_supply_ops_register()
┌───────┴─────────────┴─────────────┴────────────────────┐
│ Hardware Drivers (coul/charger/wireless) │
└─────────────────────────────────────────────────────────┘
2. 模块架构
2.1 三层架构设计
┌─────────────────────────────────────────────────────────┐
│ Layer 3: Application (power_supply_application.c) │
│ • power_supply_app_get_bat_capacity() │
│ • power_supply_app_get_bat_temp() │
│ • power_supply_app_get_usb_voltage_now() │
│ 作用:为其他内核模块提供便捷访问接口 │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────────┐
│ Layer 2: Interface (power_supply_interface.c) │
│ • power_supply_get_int_property_value() │
│ • power_supply_set_int_property_value() │
│ • power_supply_sync_changed() │
│ 作用:封装标准power_supply接口,简化调用 │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────────┐
│ Layer 1: Core (power_supply.c) │
│ • power_supply_ops_register() │
│ • power_supply_battery_get_property() │
│ • power_supply_register_power_supply() │
│ 作用:核心适配层,连接Linux框架和硬件驱动 │
└─────────────────────────────────────────────────────────┘
2.2 核心数据流
┌─────────────────────────────────────────────────────────┐
│ 读取电池电量流程示例 │
└─────────────────────────────────────────────────────────┘
1. Android层读取
cat /sys/class/power_supply/Battery/capacity
↓
2. Linux power_supply框架
power_supply_show_property()
↓
3. power_supply核心层
power_supply_cust_bat_get_property(POWER_SUPPLY_PROP_CAPACITY)
↓
4. 根据属性类型调用
power_supply_get_capacity_property(POWER_SUPPLY_PROP_BAT)
↓
5. 查找已注册的ops
power_supply_get_ops(POWER_SUPPLY_PROP_BAT)
↓
6. 调用底层驱动回调
l_ops->get_capacity_prop() // 由coul驱动注册
↓
7. 返回电量值
return 85; // 85%
3. 核心数据结构
3.1 电源操作接口(power_supply_ops)
struct power_supply_ops {
const char *type_name;
int (*get_status_prop)(void);
int (*get_health_prop)(void);
int (*get_present_prop)(void);
int (*get_online_prop)(void);
int (*get_technology_prop)(void);
int (*get_temp_prop)(void);
int (*get_cycle_count_prop)(void);
int (*get_limit_fcc_prop)(void);
int (*get_voltage_now_prop)(void);
int (*get_voltage_max_prop)(void);
int (*get_voltage_max_design_prop)(void);
int (*set_voltage_max_prop)(int value);
int (*get_current_now_prop)(void);
int (*get_current_max_prop)(void);
int (*get_current_avg_prop)(void);
int (*get_input_current_limit_prop)(void);
int (*set_input_current_limit_prop)(int value);
int (*get_capacity_prop)(void);
int (*get_capacity_level_prop)(void);
int (*get_capacity_rm_prop)(void);
int (*get_capacity_fcc_prop)(void);
int (*get_charge_full_prop)(void);
int (*get_charge_counter_prop)(void);
int (*get_charge_full_design_prop)(void);
int (*get_charge_now_prop)(void);
int (*get_batid_prop)(void);
const char *(*get_brand_prop)(void);
int (*get_type_prop)(void);
int (*get_usb_type_prop)(void);
};
设计说明:
所有回调函数均为可选,未实现时返回默认值
采用函数指针表避免大量if-else判断
支持读写分离(部分属性可写)
3.2 电源设备管理结构(power_supply_dev)
struct power_supply_dev {
struct device *dev;
struct device_node *np;
struct power_supply *bat;
struct power_supply *raw_bat;
struct power_supply *assist_bat;
struct power_supply *mains;
struct power_supply *usb;
struct power_supply *wireless;
int support_bat;
int support_raw_bat;
int support_assist_bat;
int support_mains;
int support_usb;
int support_wireless;
enum power_supply_bat_mode bat_mode;
unsigned int total_ops;
struct power_supply_ops *p_ops[POWER_SUPPLY_PROP_END];
};
bat_mode说明:
3.3 电源类型枚举
enum power_supply_prop_type {
POWER_SUPPLY_PROP_BEGIN = 0,
POWER_SUPPLY_PROP_BAT = 0,
POWER_SUPPLY_PROP_RAW_BAT,
POWER_SUPPLY_PROP_ASSITST_BAT,
POWER_SUPPLY_PROP_MAINS,
POWER_SUPPLY_PROP_USB,
POWER_SUPPLY_PROP_WIRELESS,
POWER_SUPPLY_PROP_END,
};
类型说明:
4. 核心功能实现
4.1 驱动注册接口
int power_supply_ops_register(struct power_supply_ops *ops)
{
int type;
if (!g_power_supply_dev || !ops || !ops->type_name)
return -EPERM;
type = power_supply_get_prop_type(ops->type_name);
if (type < 0)
return -EPERM;
g_power_supply_dev->p_ops[type] = ops;
g_power_supply_dev->total_ops++;
hwlog_info("total_ops=%d type=%d:%s ops register ok\n",
g_power_supply_dev->total_ops, type, ops->type_name);
return 0;
}
使用示例(在coul驱动中):
static int coul_get_capacity(void)
{
return coul_drv_battery_capacity();
}
static int coul_get_voltage_now(void)
{
return coul_drv_battery_voltage();
}
static struct power_supply_ops coul_bat_ops = {
.type_name = "bat",
.get_capacity_prop = coul_get_capacity,
.get_voltage_now_prop = coul_get_voltage_now,
.get_temp_prop = coul_get_temp,
};
static int coul_probe(struct platform_device *pdev)
{
power_supply_ops_register(&coul_bat_ops);
return 0;
}
4.2 属性读取流程
static int power_supply_cust_bat_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
struct power_supply_dev *l_dev = power_supply_get_dev();
if (l_dev->bat_mode == POWER_SUPPLY_BAT_BYPASS_MODE)
return power_supply_get_property_value("battery", psp, val);
return power_supply_battery_get_property(POWER_SUPPLY_PROP_BAT,
psp, val);
}
static int power_supply_battery_get_property(int type,
enum power_supply_property psp, union power_supply_propval *val)
{
switch (psp) {
case POWER_SUPPLY_PROP_CAPACITY:
struct power_supply_ops *l_ops = power_supply_get_ops(type);
if (!l_ops || !l_ops->get_capacity_prop)
return POWER_SUPPLY_DEFAULT_CAPACITY;
val->intval = l_ops->get_capacity_prop();
break;
}
return 0;
}
4.3 电源设备注册
static int power_supply_register_power_supply(struct power_supply_dev *l_dev)
{
if (l_dev->support_bat) {
l_dev->bat = power_supply_register(l_dev->dev,
&power_supply_battery_desc, NULL);
}
if (l_dev->support_raw_bat) {
l_dev->raw_bat = power_supply_register(l_dev->dev,
&power_supply_raw_battery_desc, NULL);
}
if (l_dev->support_usb) {
l_dev->usb = power_supply_register(l_dev->dev,
&power_supply_usb_desc, NULL);
}
return 0;
}
结果:创建sysfs节点
/sys/class/power_supply/
├── Battery/ # 主电池(Android读取此节点)
│ ├── capacity # 电量百分比
│ ├── voltage_now # 当前电压
│ ├── current_now # 当前电流
│ ├── temp # 温度
│ └── status # 充电状态
├── battery/ # 原始电池(调试用)
├── assist_battery/ # 辅助电池(双电池)
├── usb/ # USB充电器
│ ├── online # 是否在线
│ ├── voltage_now # USB电压
│ └── usb_type # USB类型(SDP/DCP/PD等)
└── Wireless/ # 无线充电
└── online
4.4 辅助接口层(power_supply_interface.c)
int power_supply_get_int_property_value(const char *name,
enum power_supply_property psp, int *val)
{
union power_supply_propval union_val = { 0 };
ret = power_supply_get_property_value(name, psp, &union_val);
if (!ret)
*val = union_val.intval;
return ret;
}
int capacity;
power_supply_get_int_property_value("Battery",
POWER_SUPPLY_PROP_CAPACITY, &capacity);
4.5 应用层接口(power_supply_application.c)
int power_supply_app_get_bat_capacity(void)
{
struct power_supply_app_dev *l_dev = power_supply_app_get_dev();
int val = POWER_SUPPLY_DEFAULT_CAPACITY;
ret = power_supply_get_int_property_value(l_dev->bat_psy,
POWER_SUPPLY_PROP_CAPACITY, &val);
if (ret)
hwlog_err("use default bat_capacity: value=%d\n", val);
return val;
}
#include <chipset_common/hwpower/common_module/power_supply_application.h>
int capacity = power_supply_app_get_bat_capacity();
int temp = power_supply_app_get_bat_temp();
int vbat = power_supply_app_get_bat_voltage_now();
优势:
隐藏power_supply框架复杂性
提供类型安全的接口
自动处理单位转换(如温度÷10)
内置默认值处理
5. 支持的属性列表
5.1 电池属性(23个)
| 属性名 | 类型 | 说明 | 默认值 |
|---|
POWER_SUPPLY_PROP_STATUS | int | 充电状态 | 1 (UNKNOWN) |
POWER_SUPPLY_PROP_HEALTH | int | 健康状态 | UNKNOWN |
POWER_SUPPLY_PROP_PRESENT | int | 是否在位 | 1 |
POWER_SUPPLY_PROP_ONLINE | int | 是否在线 | 1 |
POWER_SUPPLY_PROP_TECHNOLOGY | int | 电池技术 | UNKNOWN |
POWER_SUPPLY_PROP_TEMP | int | 温度(0.1°C) | 250 (25°C) |
POWER_SUPPLY_PROP_CYCLE_COUNT | int | 循环次数 | 1 |
POWER_SUPPLY_PROP_LIMIT_FCC | int | FCC限制(mA) | 4000 |
POWER_SUPPLY_PROP_VOLTAGE_NOW | int | 当前电压(uV) | 4000000 (4.0V) |
POWER_SUPPLY_PROP_VOLTAGE_MAX | int | 最大电压(uV) | 4400000 (4.4V) |
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN | int | 设计电压 | 4400000 |
POWER_SUPPLY_PROP_CURRENT_NOW | int | 当前电流(uA) | 470000 (470mA) |
POWER_SUPPLY_PROP_CURRENT_AVG | int | 平均电流 | 470000 |
POWER_SUPPLY_PROP_CAPACITY | int | 电量百分比 | 50 |
POWER_SUPPLY_PROP_CAPACITY_LEVEL | int | 电量等级 | NORMAL |
POWER_SUPPLY_PROP_CAPACITY_RM | int | 剩余容量(mAh) | 2000 |
POWER_SUPPLY_PROP_CAPACITY_FCC | int | 满充容量(mAh) | 4000 |
POWER_SUPPLY_PROP_CHARGE_FULL | int | 充满电量(uAh) | 4000000 |
POWER_SUPPLY_PROP_CHARGE_COUNTER | int | 电量计数 | 3500000 |
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN | int | 设计容量 | 4000000 |
POWER_SUPPLY_PROP_CHARGE_NOW | int | 当前电量(uAh) | 2000000 |
POWER_SUPPLY_PROP_ID_VOLTAGE | int | 电池ID电压(mV) | 200 |
POWER_SUPPLY_PROP_BRAND | str | 电池品牌 | "default" |
5.2 USB属性(8个,内核5.4+)
| 属性名 | 类型 | 说明 | 默认值 |
|---|
POWER_SUPPLY_PROP_ONLINE | int | 是否在线 | 0 |
POWER_SUPPLY_PROP_VOLTAGE_NOW | int | USB电压 | 0 |
POWER_SUPPLY_PROP_VOLTAGE_MAX | int | 最大电压 | 0 |
POWER_SUPPLY_PROP_CURRENT_NOW | int | 当前电流 | 0 |
POWER_SUPPLY_PROP_CURRENT_MAX | int | 最大电流 | 500000 (500mA) |
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT | int | 输入限流(可写) | 500000 |
POWER_SUPPLY_PROP_USB_TYPE | int | USB类型 | 0 |
POWER_SUPPLY_PROP_TEMP | int | 充电器温度 | 250 |
支持的USB类型:
POWER_SUPPLY_USB_TYPE_SDP:标准USB (5V 500mA)
POWER_SUPPLY_USB_TYPE_DCP:专用充电器 (5V 1.5A)
POWER_SUPPLY_USB_TYPE_CDP:充电数据端口
POWER_SUPPLY_USB_TYPE_PD:USB Power Delivery
POWER_SUPPLY_USB_TYPE_PD_PPS:PD PPS (可编程电源)
6. 典型使用场景
6.1 场景1:底层驱动注册电池属性
static int coul_get_bat_capacity(void)
{
return coul_battery_capacity();
}
static int coul_get_bat_voltage(void)
{
return coul_battery_voltage_uv();
}
static int coul_get_bat_current(void)
{
return coul_battery_current_ua();
}
static int coul_get_bat_temp(void)
{
return coul_battery_temperature();
}
static struct power_supply_ops coul_bat_ops = {
.type_name = "bat",
.get_capacity_prop = coul_get_bat_capacity,
.get_voltage_now_prop = coul_get_bat_voltage,
.get_current_now_prop = coul_get_bat_current,
.get_temp_prop = coul_get_bat_temp,
.get_health_prop = coul_get_bat_health,
.get_status_prop = coul_get_charge_status,
};
static int coul_probe(struct platform_device *pdev)
{
int ret;
ret = coul_hardware_init();
if (ret)
return ret;
ret = power_supply_ops_register(&coul_bat_ops);
if (ret)
hwlog_err("register bat ops fail\n");
return ret;
}
6.2 场景2:充电器驱动注册USB属性
static int charger_get_usb_online(void)
{
return charge_get_charger_online();
}
static int charger_get_usb_voltage(void)
{
return charge_get_vbus();
}
static int charger_get_usb_type(void)
{
int type = charge_get_charger_type();
switch (type) {
case CHARGER_TYPE_SDP:
return POWER_SUPPLY_USB_TYPE_SDP;
case CHARGER_TYPE_DCP:
return POWER_SUPPLY_USB_TYPE_DCP;
case CHARGER_TYPE_PD:
return POWER_SUPPLY_USB_TYPE_PD;
default:
return POWER_SUPPLY_USB_TYPE_UNKNOWN;
}
}
static int charger_set_input_current_limit(int value)
{
return charge_set_input_current(value / 1000);
}
static struct power_supply_ops charger_usb_ops = {
.type_name = "usb",
.get_online_prop = charger_get_usb_online,
.get_voltage_now_prop = charger_get_usb_voltage,
.get_usb_type_prop = charger_get_usb_type,
.set_input_current_limit_prop = charger_set_input_current_limit,
};
static int charger_probe(struct platform_device *pdev)
{
power_supply_ops_register(&charger_usb_ops);
return 0;
}
6.3 场景3:Android应用读取电池信息
adb shell cat /sys/class/power_supply/Battery/capacity
adb shell cat /sys/class/power_supply/Battery/voltage_now
adb shell cat /sys/class/power_supply/Battery/temp
adb shell cat /sys/class/power_supply/Battery/status
adb shell cat /sys/class/power_supply/usb/usb_type
6.4 场景4:内核模块使用应用层接口
#include <chipset_common/hwpower/common_module/power_supply_application.h>
static void wldc_check_battery_state(void)
{
int capacity, temp, vbat;
capacity = power_supply_app_get_bat_capacity();
temp = power_supply_app_get_bat_temp();
vbat = power_supply_app_get_bat_voltage_now();
hwlog_info("battery: capacity=%d%%, temp=%d°C, vbat=%dmV\n",
capacity, temp, vbat);
if (temp > 45)
wldc_set_power_limit(50);
else if (capacity > 90)
wldc_set_power_limit(30);
}
6.5 场景5:DTS配置示例
// 设备树配置
power_supply: power_supply {
compatible = "huawei,power_supply";
// 配置启用的电源类型
support_bat = <1>; // 启用主电池
support_raw_bat = <0>; // 禁用原始电池
support_assist_bat = <1>; // 启用辅助电池(双电池)
support_mains = <0>; // 禁用市电
support_usb = <1>; // 启用USB
support_wireless = <1>; // 启用无线充电
// 电池模式
bat_mode = <0>; // 0=注册模式, 1=透传模式
};
power_supply_app: power_supply_app {
compatible = "huawei,power_supply_app";
// 配置电池节点名(平台相关)
bat_psy_name = "battery"; // 或 "Battery"
usb_psy_name = "usb"; // 或 "USB"
};
7. 调试方法
7.1 检查注册状态
ls /sys/class/power_supply/
cat /sys/class/power_supply/Battery/type
cat /sys/class/power_supply/usb/type
dmesg | grep "power_psy\|power_supply"
7.2 测试属性读取
cd /sys/class/power_supply/Battery
for prop in *; do
echo "=== $prop ==="
cat "$prop" 2>&1
done
7.3 测试属性写入
echo 1000000 > /sys/class/power_supply/usb/input_current_limit
echo 4350000 > /sys/class/power_supply/assist_battery/voltage_max
cat /sys/class/power_supply/usb/input_current_limit
7.4 调试回调函数
static int coul_get_bat_capacity(void)
{
int capacity = coul_battery_capacity();
hwlog_info("[PSY_DEBUG] get_capacity called, value=%d\n", capacity);
return capacity;
}
dmesg -w | grep PSY_DEBUG
# [ 123.456] coul: [PSY_DEBUG] get_capacity called, value=85
7.5 常见问题排查
| 问题现象 | 可能原因 | 排查方法 |
|---|
/sys/class/power_supply/Battery 不存在 | power_supply模块未加载 | dmesg | grep power_supply 检查是否probe成功 |
cat capacity 返回50(默认值) | ops未注册或回调未实现 | 检查 total_ops 日志,确认驱动已注册 |
cat voltage_now 显示固定值不变 | 回调函数返回常量 | 在回调中加日志,确认硬件读取正常 |
| Android无法读取电量 | 节点名称不匹配 | Android期望 Battery,检查desc.name |
echo xxx > input_current_limit 失败 | 属性不可写或权限不足 | 检查 property_is_writeable 实现 |
| 双电池显示不正确 | assist_battery未启用 | DTS中设置 support_assist_bat=1 |
8. 与其他模块的交互
8.1 依赖关系
power_supply 模块依赖:
├── Linux power_supply框架 --> 标准内核接口
├── power_dts.h --> DTS解析
├── power_event_ne.h --> 事件通知(可选)
└── power_printk.h --> 日志打印
8.2 被依赖关系
几乎所有电源相关模块都依赖power_supply:
电量计驱动(coul)
注册 bat 类型ops
提供电压/电流/容量/温度读取
充电器驱动(charger)
注册 usb 类型ops
提供充电器在线状态、VBUS电压、USB类型
支持输入限流设置
无线充电驱动(wireless_charger)
注册 wireless 类型ops
提供无线充电在线状态
直充驱动(direct_charge)
电池健康管理(battery_health)
8.3 与Android Framework的交互
┌─────────────────────────────────────────────────────┐
│ Android Java层 (BatteryService) │
│ frameworks/base/services/core/java/com/android/ │
│ server/BatteryService.java │
└────────────────────┬────────────────────────────────┘
│ JNI
┌────────────────────┴────────────────────────────────┐
│ Android Native层 (BatteryMonitor) │
│ system/core/healthd/BatteryMonitor.cpp │
│ 读取 /sys/class/power_supply/Battery/* │
└────────────────────┬────────────────────────────────┘
│ sysfs
┌────────────────────┴────────────────────────────────┐
│ Linux power_supply框架 │
│ drivers/power/supply/power_supply_sysfs.c │
└────────────────────┬────────────────────────────────┘
│ get_property()
┌────────────────────┴────────────────────────────────┐
│ power_supply模块 (适配层) │
│ drivers/hwpower/cc_common_module/power_supply/ │
└────────────────────┬────────────────────────────────┘
│ ops回调
┌────────────────────┴────────────────────────────────┐
│ coul/charger等硬件驱动 │
└─────────────────────────────────────────────────────┘
Android读取的关键属性:
9. 关键设计细节
9.1 为何需要BAT和RAW_BAT两种电池类型
设计原因:
RAW_BAT:底层真实数据,用于工厂测试和调试
BAT:对外展示数据,用于Android显示
可能经过平滑处理(避免跳变)
可能应用电量修正算法
节点名 Battery(Android标准)
实际案例:
RAW_BAT读取:capacity = 87% (硬件返回值)
BAT显示: capacity = 85% (应用平滑算法后)
9.2 为何需要ASSIST_BAT辅助电池
硬件背景:MATE X5折叠屏采用双电池方案
┌──────────────┐
│ 主屏幕 │ ← 主电池 (4000mAh)
├──────────────┤
│ 副屏幕 │ ← 辅助电池 (4000mAh)
└──────────────┘
总容量:8000mAh
软件实现:
9.3 为何USB属性在内核5.4前后不同
Linux 5.4内核重大变更:
兼容性处理:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
static enum power_supply_property power_supply_usb_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_USB_TYPE,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};
#else
static enum power_supply_property power_supply_usb_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
#endif
9.4 为何需要三层架构
分层理由:
| 层级 | 职责 | 优势 |
|---|
| Application | 简化接口 | 其他模块无需了解power_supply框架 |
| Interface | 辅助函数 | 自动处理union/指针,减少重复代码 |
| Core | 核心适配 | 连接Linux标准和华为实现 |
对比传统方式:
struct power_supply *psy;
union power_supply_propval val;
psy = power_supply_get_by_name("Battery");
power_supply_get_property(psy, POWER_SUPPLY_PROP_CAPACITY, &val);
int capacity = val.intval;
power_supply_put(psy);
int capacity = power_supply_app_get_bat_capacity();
10. 最佳实践建议
10.1 驱动开发者
完整实现ops回调:
static struct power_supply_ops coul_bat_ops = {
.type_name = "bat",
.get_capacity_prop = coul_get_capacity,
.get_voltage_now_prop = coul_get_voltage,
.get_current_now_prop = coul_get_current,
.get_temp_prop = coul_get_temp,
.get_status_prop = coul_get_status,
.get_health_prop = coul_get_health,
.get_cycle_count_prop = coul_get_cycles,
.get_brand_prop = coul_get_brand,
};
注意单位转换:
static int get_voltage_now(void)
{
int mv = read_voltage_from_hardware();
return mv * 1000;
}
static int get_current_now(void)
{
int ma = read_current_from_hardware();
return ma * 1000;
}
static int get_temp(void)
{
int celsius = read_temp_from_hardware();
return celsius * 10;
}
错误处理:
static int get_voltage_now(void)
{
int ret, voltage;
ret = i2c_read_voltage(&voltage);
if (ret) {
hwlog_err("read voltage fail, ret=%d\n", ret);
return POWER_SUPPLY_DEFAULT_VOLTAGE_NOW;
}
return voltage * 1000;
}
10.2 平台集成者
DTS配置建议:
// 标准Android设备
power_supply {
support_bat = <1>; // 必须
support_usb = <1>; // 推荐
support_wireless = <1>; // 如果支持无线充电
bat_mode = <0>; // 注册模式
};
// 双电池折叠屏
power_supply {
support_bat = <1>;
support_assist_bat = <1>; // 启用辅助电池
support_usb = <1>;
};
确保初始化顺序:
fs_initcall_sync(power_supply_init);
device_initcall(coul_init);
late_initcall(charger_init);
10.3 应用开发者
优先使用application接口:
#include <chipset_common/hwpower/common_module/power_supply_application.h>
int capacity = power_supply_app_get_bat_capacity();
struct power_supply *psy = power_supply_get_by_name("Battery");
处理默认值:
int capacity = power_supply_app_get_bat_capacity();
if (capacity == POWER_SUPPLY_DEFAULT_CAPACITY) {
hwlog_warn("battery capacity unavailable\n");
}
11. 性能优化建议
11.1 避免频繁读取
for (i = 0; i < 1000; i++) {
int vbat = power_supply_app_get_bat_voltage_now();
}
static int g_cached_vbat;
static unsigned long g_cache_time;
int get_bat_voltage_cached(void)
{
unsigned long now = jiffies;
if (time_before(now, g_cache_time + msecs_to_jiffies(100)))
return g_cached_vbat;
g_cached_vbat = power_supply_app_get_bat_voltage_now();
g_cache_time = now;
return g_cached_vbat;
}
11.2 使用批量读取
struct power_supply *psy = power_supply_get_by_name("Battery");
union power_supply_propval val;
power_supply_get_property_value_with_psy(psy, POWER_SUPPLY_PROP_CAPACITY, &val);
int capacity = val.intval;
power_supply_get_property_value_with_psy(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
int voltage = val.intval;
power_supply_put(psy);
12. 总结
12.1 核心特性
| 特性 | 说明 |
|---|
| 多电源支持 | 同时管理6种电源类型(电池/充电器/无线) |
| 标准适配 | 连接Linux power_supply框架和华为驱动 |
| 回调机制 | 通过ops注册实现驱动解耦 |
| 三层架构 | Core + Interface + Application分层设计 |
| 灵活配置 | DTS配置启用/禁用特定电源 |
| 双电池支持 | 为折叠屏提供辅助电池管理 |
12.2 价值体现
统一接口:所有电源属性通过标准sysfs访问
简化开发:应用层接口隐藏框架复杂性
兼容性:支持内核5.4前后版本
扩展性:新增电源类型只需注册ops
Android兼容:完全兼容Android BatteryService
12.3 模块定位总结
华为电源管理子系统模块定位:
基础设施层:
├── power_sysfs --> sysfs节点管理
├── power_supply --> 电源设备抽象 ← 当前模块
├── power_event --> 事件通知
├── power_vote --> 参数仲裁
├── power_dsm --> 异常上报
└── power_log --> 日志收集
业务功能层:
├── coul --> 电量计驱动(注册bat ops)
├── charger --> 充电器驱动(注册usb ops)
├── wireless_charger --> 无线充电(注册wireless ops)
└── direct_charge --> 直充驱动(读取bat属性)
power_supply的关键作用:
作为电源设备的统一抽象层
连接Linux标准框架和华为硬件驱动
为Android系统提供标准电源信息接口