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

来源:互联网 发布:python pdf下载 编辑:程序博客网 时间:2024/04/30 07:28

2kernelsysfs接口函数的建立

这里所分析的代码基于三星公司的手机产品i5700。涉及到电源管理的设备,该设备驱动应该增添相应的代码以支持相应的电源管理,如suspendresume。同时应该有相应的代码向sysfs提供相应的entry供用户使用。由于该流程分析的是Lcd亮度的调节,所以涉及到Lcd驱动向sysfs提供的entrysuspendresume等功能在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提供的entrys3cfb_s6d05a.c中相关功能函数

 

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

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

 

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

三个entry分别是lcd_powerbacklight_powerbacklight_level,这几个entryandroid系统起来后,在终端通过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来建立entrysysfs中的属性。

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

原创粉丝点击