现在的位置: 首页 > 综合 > 正文

Android电源管理系统调研报告-(5)

2013年09月21日 ⁄ 综合 ⁄ 共 4253字 ⁄ 字号 评论关闭

2

kernel

sysfs
接口函数的建立

这里所分析的代码基于三星公司的手机产品
i5700
。涉及到电源管理的设备,该设备驱动应该增添相应的代码以支持相应的电源管理,如
suspend

resume
。同时应该有相应的代码向
sysfs
提供相应的
entry
供用户使用。由于该流程分析的是
Lcd
亮度的调节,所以涉及到
Lcd
驱动向
sysfs
提供的
entry

suspend

resume
等功能在
android
层调用

int release_wake_lock(const char* id);

int acquire_wake_lock(int lock, const char* id);

时起作用。

 


i5700
中,
Lcd
驱动包括两个文件,一个是与特定硬件相关的
s3cfb_s6d05a.c
,该文件实现了与硬件相关的操作,包括
GPIO
口的初始化和电源管理的相关功能函数等;一个是三星通用的
s3cfb.c
,作为桥梁作用联系着

sysfs
提供的
entry

s3cfb_s6d05a.c
中相关功能函数

 

1
)、
/drivers/video/samsung/s3cfb.c

该文件向
sys
提供了三个
entry
,让我们来看看这三个
entry
的建立流程。

 

(1)

entry
对应的读、写功能函数:

三个
entry
分别是
lcd_power

backlight_power

backlight_level
,这几个
entry

android
系统起来后,在终端通过
adb shell
,敲入如下命令就可以看到:

# ls /sys/devices/platform/s3c-lcd

其中
*show*
表示读操作的功能函数,
*store*
表示写操作的功能函数。在后面会对其中一个函数有进行详细的分析。

static int s3cfb_sysfs_show_lcd_power(struct device *dev, struct device_attribute *attr, char *buf)

static int s3cfb_sysfs_store_lcd_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)

static int s3cfb_sysfs_show_backlight_power(struct device *dev, struct device_attribute *attr, char *buf)

static int s3cfb_sysfs_store_backlight_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)

static int s3cfb_sysfs_show_backlight_level(struct device *dev, struct device_attribute *attr, char *buf)

static int s3cfb_sysfs_store_backlight_level(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)

 

(2)

entry
属性的建立:


内核



中,
sysfs 
属性一般是由
 __ATTR 
系列的宏来声明的,如对设备的使用
 DEVICE_ATTR 
,对总线使用
 BUS_ATTR 
,对驱动使用
DRIVER_ATTR 
,对类别
(class)
使用
 CLASS_ATTR, 
这四个高级的宏来自于
<include/linux/device.h>
。在
s3cfb.c
里,使用的是
DEVICE_ATTR
来建立
entry

sysfs
中的属性。

static DEVICE_ATTR(lcd_power, 0666,

                     
s3cfb_sysfs_show_lcd_power,

                     
s3cfb_sysfs_store_lcd_power);

 

static DEVICE_ATTR(backlight_power, 0666,

                     
s3cfb_sysfs_show_backlight_power,

                     
s3cfb_sysfs_store_backlight_power);

 

static DEVICE_ATTR(backlight_level, 0644,

                     
s3cfb_sysfs_show_backlight_level,

                     
s3cfb_sysfs_store_backlight_level);

 

DEVICE_ATTR 
宏声明有四个参数,分别是名称、权限位、读函数、写函数。其中读函数和写函数是读写功能函数的函数名。

 

(3)

entry
的创建

entry
的创建是通过函数
device_create_file
完成,在
static int __inits3cfb_probe(struct platform_device *pdev)
函数内实现的。

       
ret = device_create_file(&(pdev->dev), &dev_attr_backlight_power);

 

       
if (ret < 0)

              
printk(KERN_WARNING "s3cfb: failed to add entries/n");

 

       
ret = device_create_file(&(pdev->dev), &dev_attr_backlight_level);

 

       
if (ret < 0)

              
printk(KERN_WARNING "s3cfb: failed to add entries/n");

 

       
ret = device_create_file(&(pdev->dev), &dev_attr_lcd_power);

 

       
if (ret < 0)

              
printk(KERN_WARNING "s3cfb: failed to add entries/n");

 

通过以上简单的三个步骤,就可以在
shell
终端查看到这三个
entry
了。当我们将数据
echo
到这几个
entry
中时,在上层实际上完成了一次
write
操作,对应到
kernel
,分别调用了
lcd
驱动中的三个
*store*
。同理,当我们
cat
一个
entry
时则会调用
*show*
。通过在
*show*

*store*
中插桩就可以看到效果。到这里,只是简单的建立了
android
层到
kernel
的桥梁,真正实现对硬件操作的,还是在
*show*

*store*
中完成的。

 

 

 

 

 

(4)

backlight_level

 entry
写函数分析

static int s3cfb_sysfs_store_backlight_level(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)

{

       
unsigned long value = simple_strtoul(buf, NULL, 10);

 

       
if (value < s3c_fimd.backlight_min || value > s3c_fimd.backlight_max)

              
return -ERANGE;

 

       
s3cfb_set_backlight_level(value);

 

       
return len;

}

 

这里调用了
s3cfb_set_backlight_level(value);

static void s3cfb_set_backlight_level(int to)

{

       
backlight_level = to;

 

       
if (s3c_fimd.set_brightness)

              
(s3c_fimd.set_brightness)(to);

}

 

 

在这个函数里,
s3c_fimd.set_brightness
是一个函数指针,如果不为空,刚调用
(s3c_fimd.set_brightness)(to);
。在这里还看不到到底调用了哪个函数,在
s3cfb_s6d05a.c
中有能该函数指针的初始化以及最终功能函数的实现。

 

 

2
)、
/drivers/video/samsung/s3cfb_s6d05a.c

上文提到的函数接口的初始化是在
static voids3cfb_set_fimd_info(void)
中完成的:

       
s3c_fimd.set_lcd_power             
 = lcd_power_ctrl;

       
s3c_fimd.set_backlight_power = backlight_power_ctrl;

       
s3c_fimd.set_brightness     
 
= backlight_level_ctrl;

 

因此
(s3c_fimd.set_brightness)(to);
实际上是调用了
backlight_level_ctrl(to);

void backlight_level_ctrl(s32 value)

{

       
if ((value < BACKLIGHT_LEVEL_MIN) ||      
/* Invalid Value */

              
(value > BACKLIGHT_LEVEL_MAX) ||

              
(value == backlight_level))  
/* Same Value */

              
return;

 

       
if (backlight_power)

              
backlight_ctrl(value);   

       

       
backlight_level = value;      

}

 

这个函数实现的是
LCD
背光的调节,可以参考程杰SX的博客:

http://hi.baidu.com/aokikyon/blog/item/ea947e36e42949d0a2cc2b55.html

抱歉!评论已关闭.