Android Power
android and power-related service they have two/frameworks/base/services/core/java/com/android/server/
One is BatteryService.java
, the other is in the directory powe PowerManagerService.java
.
Power Management Architecture
Android primarily through Wakelock power management mechanism to manage the state of the system, the entire android power management can be divided into four layers: Application Interface Layer (PowerManager.java), Framework layer (PowerManagerService.java), HAL (power.c) and linux inner nuclear layer (kernel / power).
Application Interface Layer: PowerManager in the open interfaces, applications can call interface application wakelock PM and wake up the system, the system into sleep and other operations.
Framework layers: application calls PowerManager open interface, complete PowerManagerService the operating system, the computing system PowerManagerService and related calculations Power, the whole system is power management decisions. And coordinate power system how to interact with other modules, such as the bright screen, dark screen, system sleep, wake up and so on.
HAL layer: This layer is only a power.c file parameters passed down by the upper layer, data is written to / sys / power / wake_lock or / sys / power / wake_unlock file node to communicate with the Kernel, the main function is to apply / release locks to maintain screen flickering.
kernel layer: kernel / power implement power management framework. drivers / power, device specific power management framework.
Battery Management Architecture
Android battery management system drive inherit the power supply class linux is. In the user layer BatteryService.java manner by the broadcast-related attributes reported to the battery using the app, and registers the battery status monitor uevent varied to obtain real-time status of the battery.
frameworks/base/services/core/java/com/android/server/BatteryService.java
When detecting the battery state changes, a {@link android.content.Intent # ACTION_BATTERY_CHANGED BATTERY_CHANGED action} broadcast to {@link android.content.BroadcastReceiver IntentReceivers} such services.
The new value is stored in the battery state {@link android.content.Intent # getExtra Intent.getExtra}, the contents of storage are as follows:
scale:最大电池电量值,通常100
level:当前电量值,从0到scale
status;当前充电状态
health:电池状态
present:bool值,如果有电池则值为true
icon-small:整型,该状态建议使用的icon。
plugged:0,设备未插入,1:AC适配器插入, 2, USB插入
voltage:当前电池电压mv
temperature:当前电池温度。
technology:电池类型,如:Li-ion
onStart battery monitor registered to the underlying
public void onStart() {
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
//注册电池监听,当底层电池电量发生变化调用此监听,并调用update。
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
//将POWER_SERVICE作为Binder的服务端,注册到SystemService中
publishBinderService("battery", new BinderService());
//将BatteryManagerInternal注册到本地服务
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
When the underlying information, call update will update BatteryService related values.
private void update(BatteryProperties props) {
synchronized (mLock) {
if (!mUpdatesStopped) {
mBatteryProps = props;
// Process the new values.
processValuesLocked(false);
} else {
mLastBatteryProps.set(props);
}
}
}
processValuesLocked function as follows:
private void processValuesLocked(boolean force) {
313 boolean logOutlier = false;
314 long dischargeDuration = 0;
315 //获取电池电量是否低于critical界限
316 mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
//获取充电状态,AC,USB,无线以及什么都没有接
317 if (mBatteryProps.chargerAcOnline) {
318 mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
319 } else if (mBatteryProps.chargerUsbOnline) {
320 mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
321 } else if (mBatteryProps.chargerWirelessOnline) {
322 mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
323 } else {
324 mPlugType = BATTERY_PLUGGED_NONE;
325 }
344 // Let the battery stats keep track of the current level.电池统计信息和当前状态保持一致
345 try {
346 mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
347 mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
348 mBatteryProps.batteryVoltage);
349 } catch (RemoteException e) {
350 // Should never happen.
351 }
//低电量关机
353 shutdownIfNoPowerLocked();
//电池温度过高关机
354 shutdownIfOverTempLocked();
//force是第一次调用时标志,如果状态有更改依然会调用下面的代码
356 if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus ||
357 mBatteryProps.batteryHealth != mLastBatteryHealth ||
358 mBatteryProps.batteryPresent != mLastBatteryPresent ||
359 mBatteryProps.batteryLevel != mLastBatteryLevel ||
360 mPlugType != mLastPlugType ||
361 mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
362 mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
363 mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent ||
364 mInvalidCharger != mLastInvalidCharger))
//插入状态有更改
366 if (mPlugType != mLastPlugType) {
367 if (mLastPlugType == BATTERY_PLUGGED_NONE) {
368 // 不充电-->充电
369
370 // There's no value in this data unless we've discharged at least once and the
371 // battery level has changed; so don't log until it does.
372 if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {
373 dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
374 logOutlier = true;
375 EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
376 mDischargeStartLevel, mBatteryProps.batteryLevel);
377 // make sure we see a discharge event before logging again
378 mDischargeStartTime = 0;
379 }
380 } else if (mPlugType == BATTERY_PLUGGED_NONE) {
381 // 充电-->不充电 或者开机上电
382 mDischargeStartTime = SystemClock.elapsedRealtime();
383 mDischargeStartLevel = mBatteryProps.batteryLevel;
384 }
385 }
//电池状态更新
386 if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
387 mBatteryProps.batteryHealth != mLastBatteryHealth ||
388 mBatteryProps.batteryPresent != mLastBatteryPresent ||
389 mPlugType != mLastPlugType) {
390 EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
391 mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
392 mPlugType, mBatteryProps.batteryTechnology);
393 }
//电池电量更新
394 if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
395 // Don't do this just from voltage or temperature changes, that is
396 // too noisy.
397 EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
398 mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
399 }
...
//发送电池状态变化广播
427 sendIntentLocked();
//对电源连接/断开进行单独的广播,因为标准的intent将不会唤醒任何应用程序并且一些应用程序基于这个信息可以做一些单独的“智能”行为
432 if (mPlugType != 0 && mLastPlugType == 0) {
433 mHandler.post(new Runnable() {
434 @Override
435 public void run() {
436 Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
437 statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
438 mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
439 }
440 });
441 }
442 else if (mPlugType == 0 && mLastPlugType != 0) {
443 mHandler.post(new Runnable() {
444 @Override
445 public void run() {
446 Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
447 statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
448 mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
449 }
450 });
451 }
//低电量电池事件通知
453 if (shouldSendBatteryLowLocked()) {
454 mSentLowBatteryBroadcast = true;
455 mHandler.post(new Runnable() {
456 @Override
457 public void run() {
458 Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
459 statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
460 mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
461 }
462 });
463 } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
464 mSentLowBatteryBroadcast = false;
465 mHandler.post(new Runnable() {
466 @Override
467 public void run() {
468 Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
469 statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
470 mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
471 }
472 });
473 }
475 // Update the battery LED
476 mLed.updateLightsLocked();
478 // This needs to be done after sendIntent() so that we get the lastest battery stats.
479 if (logOutlier && dischargeDuration != 0) {
480 logOutlierLocked(dischargeDuration);
481 }
482
483 mLastBatteryStatus = mBatteryProps.batteryStatus;
484 mLastBatteryHealth = mBatteryProps.batteryHealth;
485 mLastBatteryPresent = mBatteryProps.batteryPresent;
486 mLastBatteryLevel = mBatteryProps.batteryLevel;
487 mLastPlugType = mPlugType;
488 mLastBatteryVoltage = mBatteryProps.batteryVoltage;
489 mLastBatteryTemperature = mBatteryProps.batteryTemperature;
490 mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
491 mLastBatteryLevelCritical = mBatteryLevelCritical;
492 mLastInvalidCharger = mInvalidCharger;
493 }
healtd
healthd was put forward after Android 4.4, monitor events from the kernel of the battery, battery data BatteryService to the framework layer to pass on. BatteryService calculated battery display, remaining power, power level and other information, which code is located in / system / core / healthd.
According Android.mk file.
LOCAL_SRC_FILES := \
healthd.cpp \
healthd_mode_android.cpp \
healthd_mode_charger.cpp \
BatteryMonitor.cpp \
BatteryPropertiesRegistrar.cpp
LOCAL_MODULE := healthd
LOCAL_MODULE_TAGS := optional
LOCAL_FORCE_STATIC_EXECUTABLE := true
Files in this directory will be compiled into an executable program healthd.
int main(int argc, char **argv) {
int ch;
int ret;
static pthread_t thread;//Talen
klog_set_level(KLOG_LEVEL);
//正常开机启动
healthd_mode_ops = &android_ops;
if (!strcmp(basename(argv[0]), "charger")) {
//关机充电
healthd_mode_ops = &charger_ops;
} else {
while ((ch = getopt(argc, argv, "cr")) != -1) {
switch (ch) {
case 'c':
healthd_mode_ops = &charger_ops;
break;
case 'r':
//recovery下操作
healthd_mode_ops = &recovery_ops;
break;
case '?':
default:
KLOG_ERROR(LOG_TAG, "Talen, Unrecognized healthd option: %c\n", optopt);
exit(1);
}
}
}
ret = healthd_init();
healthd_init initialization is as follows:
static int healthd_init() {
epollfd = epoll_create(MAX_EPOLL_EVENTS);
if (epollfd == -1) {
KLOG_ERROR(LOG_TAG,
"epoll_create failed; errno=%d\n",
errno);
return -1;
}
//和板子级别相关的初始化
healthd_board_init(&healthd_config);
//根据所处的模式,有三种情况的init,分别是正常安卓系统,关机充电以及recovery。
healthd_mode_ops->init(&healthd_config);
//wakealarm定时器初始化
wakealarm_init();
//uevent事件初始化,用以监听电池的uevent事件
uevent_init();
//BatteryMonitor初始化。
gBatteryMonitor = new BatteryMonitor();
gBatteryMonitor->init(&healthd_config);
return 0;
}
init is divided into three cases.
android(healthd_mode_android.cpp)
void healthd_mode_android_init(struct healthd_config* /*config*/) {
ProcessState::self()->setThreadPoolMaxThreadCount(0);//获取线程池最大线程数
IPCThreadState::self()->disableBackgroundScheduling(true);//禁止后台调用
IPCThreadState::self()->setupPolling(&gBinderFd);//将gBinderFd加入到epoll中。
if (gBinderFd >= 0) {
//将binder_event事件注册到gBinderfd文件节点用以监听Binder事件。
if (healthd_register_event(gBinderFd, binder_event))
KLOG_ERROR(LOG_TAG,
"Register for binder events failed\n");
}
gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
//将batteryProperties注册到ServiceManager中
gBatteryPropertiesRegistrar->publish();
}
charger情况(healthd_mode_charger.cpp)
1105 void healthd_mode_charger_init(struct healthd_config* config)
1106 {
1118 ret = ev_init(input_callback, charger);
1119 if (!ret) {
1120 epollfd = ev_get_epollfd();
1121 healthd_register_event(epollfd, charger_event_handler);
1122 }
1123
1124 ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown);
1125 if (ret < 0) {
1126 LOGE("Cannot load battery_fail image\n");
1127 charger->surf_unknown = NULL;
1128 }
1129
1130 charger->batt_anim = &battery_animation;
1131
1132 GRSurface** scale_frames;
1133 int scale_count;
1134 ret = res_create_multi_display_surface("charger/battery_scale", &scale_count, &scale_frames);
1135 if (ret < 0) {
1136 LOGE("Cannot load battery_scale image\n");
1137 charger->batt_anim->num_frames = 0;
1138 charger->batt_anim->num_cycles = 1;
1139 } else if (scale_count != charger->batt_anim->num_frames) {
1140 LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n",
1141 scale_count, charger->batt_anim->num_frames);
uevent_init function
static void uevent_init(void) {
//创建并打开一个64K的socket文件描述符uevent_fd.
uevent_fd = uevent_open_socket(64*1024, true);
//将其设置为非阻塞模式
fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
//将其注册到healthd_init创建的描述符集合里
if (healthd_register_event(uevent_fd, uevent_event))
KLOG_ERROR(LOG_TAG,
"register for uevent events failed\n");
}
BatteryMonitor.cpp
void BatteryMonitor::init(struct healthd_config *hc) {
String8 path;
char pval[PROPERTY_VALUE_MAX];
mHealthdConfig = hc;
//打开/sys/class/power_supply,遍历该节点下的电池参数初始化healthd的config参数
DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
The next main function calls periodic_chores updated battery status information.
void healthd_battery_update(void) {
// Fast wake interval when on charger (watch for overheat);
// slow wake interval when on battery (watch for drained battery).
//获取新的wakealarm唤醒间隔,fast wake处于充电模式,slow是处于非充电模式的唤醒间隔。
int new_wake_interval = gBatteryMonitor->update() ?
healthd_config.periodic_chores_interval_fast :
healthd_config.periodic_chores_interval_slow;
//判定并跟新新的唤醒间隔
if (new_wake_interval != wakealarm_wake_interval)
wakealarm_set_interval(new_wake_interval);
// During awake periods poll at fast rate. If wake alarm is set at fast
// rate then just use the alarm; if wake alarm is set at slow rate then
// poll at fast rate while awake and let alarm wake up at slow rate when
// asleep.
if (healthd_config.periodic_chores_interval_fast == -1)
awake_poll_interval = -1;
else
//轮询间隔时间调节
awake_poll_interval =
new_wake_interval == healthd_config.periodic_chores_interval_fast ?
-1 : healthd_config.periodic_chores_interval_fast * 1000;
}
static void periodic_chores() {
healthd_battery_update();
}
uevent_event handler as follows.
#define UEVENT_MSG_LEN 2048
static void uevent_event(uint32_t /*epevents*/) {
char msg[UEVENT_MSG_LEN+2];
char *cp;
int n;
n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
if (n <= 0)
return;
if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
return;
msg[n] = '\0';
msg[n+1] = '\0';
cp = msg;
while (*cp) {
//判断是否是power_supply目录下的事件,如果是则更新电池状态。
if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
healthd_battery_update();
break;
}
/* advance to after the next \0 */
while (*cp++)
;
}
}
update function was called gBatteryMonitor-> update () method to complete the update on the practical significance.
//BatteryMonitor.cpp
181 bool BatteryMonitor::update(void) {
182 bool logthis;
183
184 props.chargerAcOnline = false;
185 props.chargerUsbOnline = false;
186 props.chargerWirelessOnline = false;
187 props.batteryStatus = BATTERY_STATUS_UNKNOWN;
188 props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
189 props.maxChargingCurrent = 0;
接下来跟新props.batteryPresent,props.batteryLevel,props.batteryVoltage等信息,这些信息的来源是/sys/class/power_supply/battery目录下的文件节点。
Then save the information to dmesgline years. Dmesg so you can see this information up.
if (props.batteryPresent) {
snprintf(dmesgline, sizeof(dmesgline),
"battery l=%d v=%d t=%s%d.%d h=%d st=%d",
props.batteryLevel, props.batteryVoltage,
props.batteryTemperature < 0 ? "-" : "",
abs(props.batteryTemperature / 10),
abs(props.batteryTemperature % 10), props.batteryHealth,
props.batteryStatus);
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
int c = getIntField(mHealthdConfig->batteryCurrentNowPath);
char b[20];
snprintf(b, sizeof(b), " c=%d", c / 1000);
strlcat(dmesgline, b, sizeof(dmesgline));
}
}
size_t len = strlen(dmesgline);
snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
props.chargerAcOnline ? "a" : "",
props.chargerUsbOnline ? "u" : "",
props.chargerWirelessOnline ? "w" : "");
After obtaining the above information, battery status update
healthd_mode_ops->battery_update(&props);
//返回电池是否处在充电状态
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
For the case where the battery update Andrews follows:
void healthd_mode_android_battery_update(
struct android::BatteryProperties *props) {
if (gBatteryPropertiesRegistrar != NULL)
gBatteryPropertiesRegistrar->notifyListeners(*props);
return;
}
void BatteryPropertiesRegistrar::notifyListeners(struct BatteryProperties props) {
Mutex::Autolock _l(mRegistrationLock);
for (size_t i = 0; i < mListeners.size(); i++) {
mListeners[i]->batteryPropertiesChanged(props);
}
}
MListeners defined above are as follows:
class BatteryPropertiesRegistrar : public BnBatteryPropertiesRegistrar,
public IBinder::DeathRecipient {
public:
void publish();
void notifyListeners(struct BatteryProperties props);
private:
Mutex mRegistrationLock;
Vector<sp<IBatteryPropertiesListener> > mListeners;
void registerListener(const sp<IBatteryPropertiesListener>& listener);
void unregisterListener(const sp<IBatteryPropertiesListener>& listener);
status_t getProperty(int id, struct BatteryProperty *val);
status_t dump(int fd, const Vector<String16>& args);
void binderDied(const wp<IBinder>& who);
};
调用batteryPropertiesRegistrar的notifyListeners通知props改变了。这个通知必然是给调用registerListener注册的,也必然是给framework层的。
@Override
public void onStart() {
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
publishBinderService("battery", new BinderService());
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
在初始化时,healthd初始化时候会创建BatteryPropertiesRegister对象,并将其publish到系统服务中去。
void BatteryPropertiesRegistrar::publish() {
defaultServiceManager()->addService(String16("batteryproperties"), this);
}
framework/base/services/core/java/com/android/server/BatteryService.java
@Override
public void onStart() {
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
publishBinderService("battery", new BinderService());
publishLocalService(BatteryManagerInternal.class, new LocalService());
kernel层
一个是充电芯片驱动,一个是电量计,这两个设备统一由power子系统管理。
power子系统主要由如下文件组成:
- power_supply.h (include\linux)
- power_supply_core.c (drivers\power)
power_supply_sysfs.c (drivers\power)
charger充电芯片
适合充电芯片相关的。
一个例子如下https://github.com/tibms/dual-bq2589x;这个并没有battery。
电量计
对于高通平台,早期使用了分立的器件,但现在采用AP内部集成了该模块。高通平台常用的名词如下:
qpnp-bms.c(qcom plug n play)
qpnp-charger.c
BMS:battery monitoring system;
ICC:intelligent coulomb counter,基于高通BMS系统。
RC:remaing capacity。当前状态下的剩余电量,充满电时RC=FCC。假设放电电流小于1/20C。
UUC:unusable capacity。由于电池电阻导致的电池压降而无法使用的电量,其是放电电流的函数。
UC:usable capacity。UC=FCC-UUC
RUC:剩余可用电量RUC=RC-UUC
SoC:state of charge;SoC=RC/FCC,对于上层应用,包含UUC更好:SoC=RUC/UC=(RC-UUC)/(FCC-UUC)。
C(rate):放电速率的测量方法,一个小时放完电的情况测量;如如果电池等级是1Ah,也就是1A放电能持续1h,也就是按1C标准放电。如果按0.5C放电,则500mA可以持续2h。
OCV:open circuit voltage。近乎于0电流情况下的稳定电压。电池带负载工作后,需要5~30min恢复OCV。
FCC:Full-charge capacity
CC:Coulumb counter
### linux 电源子系统核心框架
#include/linux/power_supply.h
struct power_supply
{
const char *name;//对应于/sys/class/power_supply/XXX 文件夹
enum power_supply_type type;//电池类型,UPS/BATTERY/USB等
enum power_supply_property *properties;//其具有的属性集合
size_t num_properties;//属性的数量
char **supplied_to;//此电源模块变化时,需要通知的模块。
size_t num_supplicants;//通知对象数量
//获取属性值
int (*get_property)(struct power_supply *psy,
enum power_supply_property psp,
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;
spinlock_t changed_lock;
bool changed;
struct wake_lock work_wake_lock;
}
extern int power_supply_register(struct device *parent,
struct power_supply *psy);
extern void power_supply_unregister(struct power_supply *psy);
power_supply_register函数
int power_supply_register(struct device *parent, struct power_supply *psy)
{
struct device *dev;
int rc;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
device_initialize(dev);
dev->class = power_supply_class;
dev->type = &power_supply_dev_type;
dev->parent = parent;
dev->release = power_supply_dev_release;
dev_set_drvdata(dev, psy);
psy->dev = dev;
INIT_WORK(&psy->changed_work, power_supply_changed_work);
rc = kobject_set_name(&dev->kobj, "%s", psy->name);
if (rc)
goto kobject_set_name_failed;
rc = device_add(dev);//添加电源设备
if (rc)
goto device_add_failed;
spin_lock_init(&psy->changed_lock);
wake_lock_init(&psy->work_wake_lock, WAKE_LOCK_SUSPEND, "power-supply");
//和电源led相关的门限设置
rc = power_supply_create_triggers(psy);
if (rc)
goto create_triggers_failed;
//调度psy的power_supply_changed_work,即上面的INIT_WORK初始化的函数,向用户空间发送uevent, 通知系统和用户电源有变化
power_supply_changed(psy);
goto success;
create_triggers_failed:
wake_lock_destroy(&psy->work_wake_lock);
device_del(dev);
kobject_set_name_failed:
device_add_failed:
put_device(dev);
success:
return rc;
}
总结来说电源驱动一般要做如下几部分工作:
1.定义struct power_supply,该定义可以是全局的或者是嵌入到驱动中的专有数据,如上面给的参考程序:
struct bq2589x {
struct device *dev;
struct i2c_client *client;
enum bq2589x_part_no part_no;
int revision;
unsigned int status;
int vbus_type;
bool enabled;
bool interrupt;
int vbus_volt;
int vbat_volt;
int rsoc;
struct bq2589x_config cfg;
struct work_struct irq_work;
struct work_struct adapter_in_work;
struct work_struct adapter_out_work;
struct delayed_work monitor_work;
struct delayed_work ico_work;
struct delayed_work pe_volt_tune_work;
struct delayed_work check_pe_tuneup_work;
struct delayed_work charger2_enable_work;
struct power_supply usb;
struct power_supply wall;
struct power_supply *batt_psy;
};
Initialize the probe function and power driver to register
static int bq2589x_charger1_probe (struct i2c_client Client,
const struct i2c_device_id ID)
{
struct bq2589x * BQ;
// initialize relevant fields
bq = devm_kzalloc (& client-> dev , sizeof (struct bq2589x), GFP_KERNEL);
bq->dev = &client->dev;
bq->client = client;
i2c_set_clientdata(client, bq);
ret = bq2589x_detect_device(bq);
bq->batt_psy = power_supply_get_by_name("battery");
g_bq1 = bq;
ret = bq2589x_psy_register(bq);
INIT_WORK(&bq->irq_work, bq2589x_charger1_irq_workfunc);
INIT_WORK(&bq->adapter_in_work, bq2589x_adapter_in_workfunc);
INIT_WORK(&bq->adapter_out_work, bq2589x_adapter_out_workfunc);
INIT_DELAYED_WORK(&bq->monitor_work, bq2589x_monitor_workfunc);
INIT_DELAYED_WORK(&bq->ico_work, bq2589x_ico_workfunc);
INIT_DELAYED_WORK(&bq->pe_volt_tune_work, bq2589x_pe_tune_volt_workfunc);
INIT_DELAYED_WORK(&bq->check_pe_tuneup_work, bq2589x_check_pe_tuneup_workfunc);
INIT_DELAYED_WORK(&bq->charger2_enable_work, bq2589x_charger2_enable_workfunc);
// Create the node SYS
RET = sysfs_create_group (& bq-> the dev-> Kobj, & bq2589x_attr_group);
// Event Processing battery charging chip
ret = request_irq (client-> irq, bq2589x_charger1_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "bq2589x_charger1_irq", bq);
The second step is called power_supply_register register the psy equipment
static int bq2589x_psy_register(struct bq2589x *bq)
{
int ret;
bq->usb.name = "bq2589x-usb";
bq->usb.type = POWER_SUPPLY_TYPE_USB;
bq->usb.properties = bq2589x_charger_props;
bq->usb.num_properties = ARRAY_SIZE(bq2589x_charger_props);
bq->usb.get_property = bq2589x_usb_get_property;
bq->usb.external_power_changed = NULL;
ret = power_supply_register(bq->dev, &bq->usb);
if (ret < 0) {
dev_err(bq->dev, "%s:failed to register usb psy:%d\n", __func__, ret);
return ret;
}
bq->wall.name = "bq2589x-Wall";
bq->wall.type = POWER_SUPPLY_TYPE_MAINS;
bq->wall.properties = bq2589x_charger_props;
bq->wall.num_properties = ARRAY_SIZE(bq2589x_charger_props);
bq->wall.get_property = bq2589x_wall_get_property;
bq->wall.external_power_changed = NULL;
ret = power_supply_register(bq->dev, &bq->wall);
if (ret < 0) {
dev_err(bq->dev, "%s:failed to register wall psy:%d\n", __func__, ret);
goto fail_1;
}
For the BMS electricity meter, an apparatus of this type is, according to like is added.