本文共 26268 字,大约阅读时间需要 87 分钟。
android中和电源相关的服务有两个他们在/frameworks/base/services/core/java/com/android/server/
一个是BatteryService.java
,另一个是在目录powe下的PowerManagerService.java
。
Android电源管理主要通过Wakelock机制来管理系统的状态,整个android电源管理,可以分为四个层次:应用接口层(PowerManager.java),Framework层(PowerManagerService.java), HAL(power.c)和linux内核层(kernel/power)。
应用接口层:PowerManager中开放的接口,应用可以调用PM的接口申请wakelock,唤醒系统,使系统进入休眠等操作。
Framework层:应用程序调用PowerManager开放的接口,对系统操作在PowerManagerService中完成,PowerManagerService计算系统中和power相关的计算,是整个电源管理的决策系统。同时协调power如何与系统其它模块的交互,如亮屏,暗屏,系统睡眠,唤醒等。
HAL层:该层只有一个power.c文件,该文件通过上层传下来的参数,向/sys/power/wake_lock或/sys/power/wake_unlock文件节点写入数据来与kernel进行通信,主要功能是申请/释放锁,维持屏幕亮灭。
kernel层:kernel/power实现电源管理框架。 drivers/power,设备特定的电源管理框架。
Android系统对电池的管理驱动继承了linux的power supply class。在用户层在BatteryService.java中通过广播的方式将电池相关的属性报给app使用,并且注册了uevent监听电池状态变化,以实时获取电池状态。
frameworks/base/services/core/java/com/android/server/BatteryService.java
当检测到电池状态变化时,给 {@link android.content.Intent#ACTION_BATTERY_CHANGED BATTERY_CHANGED action}广播给{@link android.content.BroadcastReceiver IntentReceivers}这类的服务。
电池状态新的值存放在{@link android.content.Intent#getExtra Intent.getExtra} ,存放的内容如下:
scale:最大电池电量值,通常100level:当前电量值,从0到scalestatus;当前充电状态health:电池状态present:bool值,如果有电池则值为trueicon-small:整型,该状态建议使用的icon。plugged:0,设备未插入,1:AC适配器插入, 2, USB插入voltage:当前电池电压mvtemperature:当前电池温度。technology:电池类型,如:Li-ion
onStart将电池监听注册到底层
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());}
当底层有信息,会调用update更新BatteryService中相关值。
private void update(BatteryProperties props) { synchronized (mLock) { if (!mUpdatesStopped) { mBatteryProps = props; // Process the new values. processValuesLocked(false); } else { mLastBatteryProps.set(props); } } }
processValuesLocked函数如下:
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 the371 // 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 again378 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 is396 // 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 @Override435 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 @Override445 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 @Override457 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 @Override467 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 LED476 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 }
healthd是安卓4.4之后提出来的,监听来自kernel的电池事件,并向上传递电池数据给framework层的BatteryService。BatteryService计算电池电量显示,剩余电量,电量级别等信息,其代码位于/system/core/healthd。
根据Android.mk文件。
LOCAL_SRC_FILES := \ healthd.cpp \ healthd_mode_android.cpp \ healthd_mode_charger.cpp \ BatteryMonitor.cpp \ BatteryPropertiesRegistrar.cppLOCAL_MODULE := healthdLOCAL_MODULE_TAGS := optionalLOCAL_FORCE_STATIC_EXECUTABLE := true
这个目录下的文件会被编译成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的初始化如下:
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分为三种情况。
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函数
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);
接下来main函数调用periodic_chores更新电池状态信息。
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处理函数如下。
#define UEVENT_MSG_LEN 2048static 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函数里调用了 gBatteryMonitor->update()方法去完成实际意义上的更新。
//BatteryMonitor.cpp181 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目录下的文件节点。
接下来将信息保存到dmesgline里。这样dmesg就可以看到这样的信息了。
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" : "");
获取到以上信息后,更新电池状态
healthd_mode_ops->battery_update(&props); //返回电池是否处在充电状态 return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline;
对于安卓情况的battery update情况如下:
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的定义如下:
class BatteryPropertiesRegistrar : public BnBatteryPropertiesRegistrar, public IBinder::DeathRecipient {public: void publish(); void notifyListeners(struct BatteryProperties props); private: Mutex mRegistrationLock; Vector> mListeners; void registerListener(const sp & listener); void unregisterListener(const sp & listener); status_t getProperty(int id, struct BatteryProperty *val); status_t dump(int fd, const Vector & args); void binderDied(const wp & 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());
一个是充电芯片驱动,一个是电量计,这两个设备统一由power子系统管理。
power子系统主要由如下文件组成:
适合充电芯片相关的。
一个例子如下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.hstruct 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);
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; };
在probe函数中初始化并注册这个电源驱动到
static int bq2589x_charger1_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bq2589x *bq; //初始化相关字段 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);
//创建sys下节点
ret = sysfs_create_group(&bq->dev->kobj, &bq2589x_attr_group);//处理充电芯片电池事件
ret = request_irq(client->irq, bq2589x_charger1_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "bq2589x_charger1_irq", bq);第二步,调用power_supply_register注册这个psy设备
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;}
对于电量计BMS,也是这个类型的一种设备,照样子添加。