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,
static DEVICE_ATTR(backlight_power, 0666,
static DEVICE_ATTR(backlight_level, 0644, |
DEVICE_ATTR
宏声明有四个参数,分别是名称、权限位、读函数、写函数。其中读函数和写函数是读写功能函数的函数名。
(3)
、
entry
的创建
entry
的创建是通过函数
device_create_file
完成,在
static int __inits3cfb_probe(struct platform_device *pdev)
函数内实现的。
|
通过以上简单的三个步骤,就可以在
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) {
} |
这里调用了
s3cfb_set_backlight_level(value);
static void s3cfb_set_backlight_level(int 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_brightness)(to);
实际上是调用了
backlight_level_ctrl(to);
void backlight_level_ctrl(s32 value) {
} |
这个函数实现的是
LCD
背光的调节,可以参考程杰SX的博客:
http://hi.baidu.com/aokikyon/blog/item/ea947e36e42949d0a2cc2b55.html