执行流程
驱动结构
1) 内核提供的接口
struct power_supply 在文件 includelinuxpower_supply.h 中
2) 提供给用户的接口
sys/class/power_supply
通过 driverspowerpower_supply_core.c 中的
int power_supply_register(struct device *parent,struct power_supply *psy)
来创建.
power_supply_register() 在 K:linux学习资料ible驱动程序开发电源电池管理电源电池管理.pdf中介绍
当电源变化时,调用:driverspowerpower_supply_core.c 中的
power_supply_changed()更新sysfs文件系统中的信息.
把握以上两点!
1. 填充 struct power_supply
路径: include/linux/power_supply.h
1.) 结构体含义
struct power_supply {
const char *name; // 名字,例如: "usb", "battary", "ac"
enum power_supply_type type; // 电源类型,在power_supply.h定义,分为usb,battery,ups,mains四种
enum power_supply_property *properties; // 电源属性,比较多,常用的在后面介绍.枚举类型数组
size_t num_properties; // 属性数量,假设为3,则回调get_property()3次
char **supplied_to;
size_t num_supplicants;
int (*get_property)(struct power_supply *psy, // 回调函数,执行power_supply_changed()后被
enum power_supply_property psp, // 调用,调用次数由num_properties决定
union power_supply_propval *val);
int (*set_property)(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val);
int (*property_is_writeable)(struct power_supply *psy,
enum power_supply_property psp);
void (*external_power_changed)(struct power_supply *psy);
void (*set_charged)(struct power_supply *psy);
/* For APM emulation, think legacy userspace. */
int use_for_apm;
/* private */
struct device *dev;
struct work_struct changed_work; // 工作队列,相当于一个线程,由它发起power_supply_changed()
spinlock_t changed_lock;
bool changed;
struct wake_lock work_wake_lock;
#ifdef CONFIG_LEDS_TRIGGERS
struct led_trigger *charging_full_trig;
char *charging_full_trig_name;
struct led_trigger *charging_trig;
char *charging_trig_name;
struct led_trigger *full_trig;
char *full_trig_name;
struct led_trigger *online_trig;
char *online_trig_name;
#endif
};
2) 常用的power_supply_propety
android下用到的:
# cat /sys/class/power_supply/ac/type
Mains
# cat /sys/class/power_supply/ac/online
1
# cd /sys/class/power_supply/battery/
# cat type status health present technology capacity
Battery
Charging
Good
1
Li-ion
50
这些宏已经定义过:
enum { // 对应 POWER_SUPPLY_PROP_STATUS
POWER_SUPPLY_STATUS_UNKNOWN = 0,
POWER_SUPPLY_STATUS_CHARGING,
POWER_SUPPLY_STATUS_DISCHARGING,
POWER_SUPPLY_STATUS_NOT_CHARGING,
POWER_SUPPLY_STATUS_FULL,
};
enum { // 对应 POWER_SUPPLY_PROP_CHARGE_TYPE
POWER_SUPPLY_CHARGE_TYPE_UNKNOWN = 0,
POWER_SUPPLY_CHARGE_TYPE_NONE,
POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
POWER_SUPPLY_CHARGE_TYPE_FAST,
};
enum { // 对应 POWER_SUPPLY_PROP_HEALTH
POWER_SUPPLY_HEALTH_UNKNOWN = 0,
POWER_SUPPLY_HEALTH_GOOD,
POWER_SUPPLY_HEALTH_OVERHEAT,
POWER_SUPPLY_HEALTH_DEAD,
POWER_SUPPLY_HEALTH_OVERVOLTAGE,
POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
POWER_SUPPLY_HEALTH_COLD,
};
enum { // 对应 POWER_SUPPLY_PROP_TECHNOLOGY
POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
POWER_SUPPLY_TECHNOLOGY_NiMH,
POWER_SUPPLY_TECHNOLOGY_LION,
POWER_SUPPLY_TECHNOLOGY_LIPO,
POWER_SUPPLY_TECHNOLOGY_LiFe,
POWER_SUPPLY_TECHNOLOGY_NiCd,
POWER_SUPPLY_TECHNOLOGY_LiMn,
};
enum { // 对应 POWER_SUPPLY_PROP_CAPACITY_LEVEL
POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
POWER_SUPPLY_CAPACITY_LEVEL_LOW,
POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
POWER_SUPPLY_CAPACITY_LEVEL_FULL,
};
一个struct power_supply的例子:
struct max17040_chip {
struct power_supply battery; // 三种供电方式
struct power_supply ac;
struct power_supply usb;
struct timespec next_update_time;
struct delayed_work work; // 两个队列
struct delayed_work battary_vol_state_wq;
/* State Of Connect */
int online;
/* battery voltage */
int vcell;
/* battery capacity */
int soc;
/* State Of Charge */
int status;
/* usb online */
int usb_online;
};
struct max17040_chip *chip;
初始化:
chip->battery.name = "battery";
chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
chip->battery.get_property = max17040_get_property; // 回调函数,执行power_supply_changed()后被调用,调用次数由battery.num_properties决定, 函数内容在下面.
chip->battery.properties = max17040_battery_props; // 内容在下面
chip->battery.num_properties = ARRAY_SIZE(max17040_battery_props);
chip->battery.external_power_changed = NULL;
chip->ac.name = "ac";
chip->ac.type = POWER_SUPPLY_TYPE_MAINS;
chip->ac.get_property = adapter_get_property;
chip->ac.properties = adapter_get_props;
chip->ac.num_properties = ARRAY_SIZE(adapter_get_props);
chip->ac.external_power_changed = NULL;
chip->usb.name = "usb";
chip->usb.type = POWER_SUPPLY_TYPE_USB;
chip->usb.get_property = usb_get_property;
chip->usb.properties = usb_get_props;
chip->usb.num_properties = ARRAY_SIZE(usb_get_props);
chip->usb.external_power_changed = NULL;
// 两个队列
INIT_DELAYED_WORK_DEFERRABLE(&chip->work, work_max17040);
INIT_DELAYED_WORK_DEFERRABLE(&chip->battary_vol_state_wq, work_battary_vol_sample);
schedule_delayed_work(&chip->work, MAX17040_DELAY);
schedule_delayed_work(&chip->battary_vol_state_wq, POLLING_BATTARY_VOL_MSEC);
max17040_battery_props[] 枚举类型数组内容
static enum power_supply_property max17040_battery_props[] = { // 一共有7项,
// 意味着max17040_get_property()将被回调7次
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_STATUS,
/*POWER_SUPPLY_PROP_ONLINE,*/
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_TEMP,
};
max17040_get_property() 函数:
static int max17040_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
dev_info(dev,"%s
", __func__);
switch (psp) { // 一共有7项, 将被回调7次. 执行power_supply_changed()后被回调.
case POWER_SUPPLY_PROP_STATUS:
val->intval = chip->status;
break;
case POWER_SUPPLY_PROP_ONLINE:
val->intval = 1;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
case POWER_SUPPLY_PROP_PRESENT:
val->intval = 3800;//chip->vcell;
if(psp == POWER_SUPPLY_PROP_PRESENT)
val->intval = 1; /* You must never run Odrioid1 without Battery. */
break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = 80;//chip->soc;
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
break;
case POWER_SUPPLY_PROP_HEALTH:
// if(chip->vcell < 2850)
// val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
// else
val->intval = POWER_SUPPLY_HEALTH_GOOD;
break;
case POWER_SUPPLY_PROP_TEMP:
break;
default:
return -EINVAL;
}
return 0;
}
work_queue队列
static void work_max17040(struct work_struct *work)
{
int old_usb_online, old_online, old_vcell, old_soc;
int vol, level;
old_online = chip->online;
old_usb_online = chip->usb_online;
old_vcell = chip->vcell;
old_soc = chip->soc;
max17040_update_values();
vol = battary_vol_average();
printk("+++ %s: vol = %d
", __func__, vol);
level = battary_level(vol);
dev_info(dev,"%s, level = %d
", __func__, level);
// s3c_get_bat_level();
/*
if((old_vcell != chip->vcell) || (old_soc != chip->soc))
power_supply_changed(&chip->battery);
if(old_usb_online != chip->usb_online)
power_supply_changed(&chip->usb);
if(old_online != chip->online)
power_supply_changed(&chip->ac);
*/
power_supply_changed(&chip->ac); // 回调ac 中的get_property()
// for test
power_supply_changed(&chip->battery); // 回调battery中的get_property()
power_supply_changed(&chip->usb); // 回调usb中的get_property()
//
schedule_delayed_work(&chip->work, MAX17040_DELAY);
}