Android模拟器学framework和driver之battery & backlight-----1.battery in linux

在linux中battery驱动主要是去处理供电方面的东西,大家看下driver在bsp中的路径就可以知道,android模拟器使用的goldfish内核中battery驱动的位置是:

android/common/drivers/power/goldfish_battery.c

目前手机,平板电脑日益普及,在嵌入式领域battery的续航能力也一直制约着手机等嵌入式设备的发展,iphone比android手机做的好多了,希望android可以再处理上下功夫,赶超apple,废话不多说,这里battery主要是处理,电池供电、插上充电器充电、USB供电等事情的发生,还有就是一些电池的信息管理,比如说电量、温度等状态可以使用户知道。

OK,这边我们主要是使用goldfish中的battery驱动来分析一下linux中的power模块是如何工作的。

在这之前我们首先要来看一下power_supply这个device driver 子系统是如何建立的,这边我们涉及到的代码都在/common/drivers/power/下:

power_supply_core.c

power_supply_sysfs.c

goldfish_battery.c

power_supply_core.c是power_supple subsystem的核心函数,在power_supply子系统在linux启动的时候会先调用到里面的饿init函数:


这个函数比较简单首先是在class中创建了一个power_supply的class,启动模拟器后可以看到在sys/class/下会有一个power_supply文件夹生成,然后是

power_supply_class->dev_uevent = power_supply_uevent;这句话把power_supply_uevent挂到power_supply_class的dev_uevent上,这里说明下,就是说power_supply子系统都是使用uevent机制把信息传到user space的,当battery的状态发生改变的时候会向用户空间上报一个uevent,这样的话用户空间就可以知道什么时候去抓信息。

这个power_supply_uevent是个回调函数,被定义在power_supply_sysfs.c中:


稍微有点长,不怕,我们慢慢来分析,这里只是开头,什么都没有应该比较好分析,

我们抓重点,首先是ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name);这句话添加了uevent的一些环境变量,这里添加了POWER_SUPPLY_NAME,接着都是些分配内存的代码,还有就是把power_supply_properties中注册的所有属性都添加成环境变量,这样的话当battery的某个属性发生变化的时候都会通报到上层让用户知道。

这里uevent我不做详细介绍,网上资料也一大堆,后面讲到jni层的时候我也会做补充用户层是如何去开启一个socket来抓kernel中的uevent的。

回到我们的power_supply_core.c中,在linux起来的时候只有调用到core中的class_init函数,其他的函数都是为我们的driver服务的,

现在我们来看下我们的goldfish_battery驱动,打开android/common/drivers/power/goldfish_battery.c,一般我喜欢先看init函数,


很简单,注册了platform_driver,同学们看到了这个函数第一反应应该是去找device_register函数,以为只有这2个函数匹配了才算在linux系统中注册了platform 设备,那么在哪呢?在我们goldfish的板级文件中有注册device,这边很奇怪,其实我没有找到具体的goldfish-battery的device_register但是在板级文件中有一个pdev_bus的注册

arch/arm/mach-goldfish/pdev_bus.c


可以看下上面这个代码中,在工作队列中遍历所有的pdev链表,调用platform_device_register把设备注册进去,之后就会调用到我们的probe函数了。

---------------------------------------------------------------------------------

probe函数主要还是做一些初始化,probe的意思就是探测的意思,就是试着去初始化(我是这么理解的),


首先来看几个结构体,其实个人认为,linux驱动给开发人员做的很多就是填充结构体,因为基本框架linux已经实现了,我们要做的是把这个大框架填满,使这个框架有血有肉,这样才能正常工作。

首先是goldfish_battery_data 这个结构体:


这个结构体中我们关注的是power_supply这个结构体,别的没什么好说的,中断啊,寄存器地址啊,自旋锁什么的。


这部分我们对照着probe中的代码一起分析,主要还是填充这个结构体:


首先是对battery的属性信息的填写:


这边电池的信息由status health present等,我们比较关注的还是电池的电量,capacity,

然后是属性的数目,不多说了,下面第三个参数比较重要 data->battery.get_property = goldfish_battery_get_property;


驱动中就是通过这个函数去实时得到电池的信息,然后使用uevent传到user space,我们重点讲下这个函数是怎么工作的。

大家注意到这里这个函数的参数,struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val

第一个参数是我们最重要的data struct,第二个参数是属性的类型,选择我们要得到的属性,第三个参数就是这个属性的值是多少,比如说电池电量是百分之多少。

这个函数是被挂在power_supply结构体中的get_property上的,它是在哪被回调呢?我们先在这里打个问号,我们知道这里只是在一些结构体中填充好了我们battery的信息,至于在什么时候回调,什么时候使用,什么时候上传uevent,我们后面会讲到,留意下!!

继续回到probe函数,下面是


名字和类型的填写。

下面就是跟硬件相关的东西了,一般的device是会用中断的方法去触发,这里goldfish的内核使用的是PC的中断资源。


得到中断好,然后申请中断,挂好中断触发的函数,这里发生中断后会做一系列的事情,我们也先放一下,先来看看下面的power_supply注册函数:


power_supply_register函数在power_supply_core中被定义


首先是时候device_create函数在class下创建设备驱动,传入的第一个参数就是我们的power_supply class

然后是初始化了工作队列INIT_WORK(&psy->changed_work, power_supply_changed_work);

oK,我们来看下这个工作队列的回调函数,power_supply_changed_work


这里就是调用了2个函数,第一个 class_for_each_device(power_supply_class, NULL, psy,
__power_supply_changed_work);

它遍历了我们power_supply_class上的所有节点,用psy作为参数调用了__power_supply_changed_work函数,__power_supply_changed_work函数的作用是匹配我们的驱动


之后再调用到了我们最最最最关键的地方kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);这里就是注册了kobject uevent事件,当我们的属性发生变化的时候会把uevent传给用户空间。

所以说,调用到我们的工作队列的时候就会向用户空间上报event,这个动作被封装在


之后会被使用到。

回到我们的power_supply_register函数中

rc = power_supply_create_attrs(psy);被定义在power_supply_sysfs.c中


这边遍历了我们的属性数组,把每个属性在我们的驱动中声称文件系统,调用到device_create_flie函数,我们运行模拟器在power_supply/battery/下会发现我们填进去的属性值生成的所有文件。

这里介绍完毕,回到我们的goldfish驱动文件,最后就是我们的中断函数了。



这里我什么也不看只想看一句话


之前讲过,就是power_supply_changed函数触发了向用户空间上报event事件的代码。OK ,android goldfish battery驱动就讲到这边,我看android模拟器的电池老是动啊动的很是不爽所以我在get_property函数中充电状态改成了不是充电状态,然后把电池电量设置为恒定的,嘿嘿,这样的话就不会动了,哈哈。下面贴张图,有图有真相

Android模拟器学framework和driver之battery & backlight-----1.battery in linux

Android模拟器学framework和driver之battery & backlight-----1.battery in linux

下面一篇我们会讲到android framework中jni对驱动的封装,好累啊,一口气写完battery driver分析。

你可能感兴趣的:(framework)