执行流程
驱动结构
1) 内核提供的接口
struct power_supply 在文件 include\linux\power_supply.h 中
2) 提供给用户的接口
sys/class/power_supply
通过 drivers\power\power_supply_core.c 中的
int power_supply_register(struct device *parent,struct power_supply *psy)
来创建.
power_supply_register() 在 K:\linux学习资料\bible\驱动程序开发\电源电池管理\电源电池管理.pdf中介绍
当电源变化时,调用:drivers\power\power_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 \n", __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 \n", __func__, vol); level = battary_level(vol); dev_info(dev,"%s, level = %d \n", __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); } |