8.2 Android灯光系统_led_class驱动
android-5.0.2\hardware\libhardware\include\hardware\lights.h //系统一些宏定义
android源码只带的灯光驱动在linux内核的driver/leds/led-class.c中,其是led驱动的顶层框架文件
该驱动的提供的功能在leds_class->dev_attrs = led_class_attrs;//在led_class_attrs提供了设备属性,当通过echo或cat访问设备节点的时候会导致响应的函数被调用
//只带驱动提供的方法
echo 255 > /sys/class/leds/led1/brightness//设置亮度
cat /sys/class/leds/led1/brightness//获取当前亮度值
cat /sys/class/leds/led1/max_brightness//获取最大亮度值
闪烁
//可以在注册led_classes之前设置trigger,eg:led_devs[i].cdev.default_trigger = "timer",这样就可以不用echo timer了
echo timer > /sys/class/leds/led1/trigger //表示使用定时器作为触发器
echo 100 > /sys/class/leds/led1/delay_on //设置点亮时间
echo 200 > /sys/class/leds/led1/delay_off //设置熄灭时间
关闭
echo 0 > /sys/class/leds/led1/delay_on
或
echo 0 > /sys/class/leds/led1/brightness
分析闪烁功能:
echo timer > /sys/class/leds/led1/trigger // timer对应 ledtrig-timer.c
//在led-classes.c文件中数组led_class_attrs[]设置的dev的三个属性,其中一个是trigger,在led1下会根据这里的属性创建节点以及操作节点是对应的函数
eg:__ATTR(trigger,0644,led_trigger_show,led_trigger_store)//echo节点导致led_trigger_store被调用,cat节点导致led_trigger_show被调用
led_trigger_store // 1. 从trigger_list找出名为"timer"的trigger
list_for_each_entry(trig, &trigger_list, next_trig) {
if (!strcmp(trigger_name, trig->name)) {
// 2. 调用
led_trigger_set(led_cdev, trig);
// 3. 把trigger放入led_classdev的trig_list链表里
list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
led_cdev->trigger = trigger;
// 4.
trigger->activate(led_cdev);
// 5. 对于"timer",在ledtring-timer.c中定义
timer_trig_activate
// 6. 创建2个文件: delay_on, delay_off,同时制定读写这两个文件时调用的函数
device_create_file
device_create_file
led_blink_set // 让LED闪烁,会传入默认的点亮时间、熄灭时间,值都可以在led_classdev中设置
led_set_software_blink
mod_timer();
}
}
echo 100 > /sys/class/leds/led1/delay_on
led_delay_on_store(,,buf,size)//这里的buf中存放的是字符串“100”
state = simple_strtoul(buf, &after, 10);
led_blink_set // // 让LED闪烁
led_cdev->blink_delay_on = state;//并且在led_classes结构体中保存时间
echo 200 > /sys/class/leds/led1/delay_off
led_delay_off_store
state = simple_strtoul(buf, &after, 10);
led_blink_set // 让LED闪烁
led_cdev->blink_delay_off = state;
怎么写驱动:
a1. 分配led_classdev
a2. 设置 :
led_cdev->max_brightness
led_cdev->brightness_set
led_cdev->flags
led_cdev->brightness
led_cdev->name
a3. 注册 : led_classdev_register
驱动代码举例:
example1:
//头文件
struct led_desc{
int gpio;
char *name;
};
static struct led_desc[] = {
{EXYNOS4212_GPM(0),"led4"},
{EXYNOS4212_GPM(1),"led4"},
{EXYNOS4212_GPM(2),"led4"},
{EXYNOS4212_GPM(3),"led4"},
};
//构造一个结构体用来保存led_classdec与之对应的led灯
struct led_classdev_4412{
struct led_classdev cdev;
int gpio;
};
static struct led_classdev_4412 *led_devs;
static void brightness_set_4412(struct led_classdev *led_cdev,enum led_brightness brightness){
struct led_classdev_4412 *dev = (struct led_classdev_4412 )led_cdev;
led_cdev->brightness = brightness;
if(brightness != LED_OFF)
{
gpio_set_value(dev->gpio,0);
}
else
{
gpio_set_value(dev->gpio,1);
}
}
static int leds_init(void)
{
int i;
int ret;
/*1、alloc led_classdev 为我们的四个led灯分配led_classdev结构体*/
led_devs = kzalloc(sizeof(struct led_classdev_4412)*sizeof(led_gpios)/sizeof(led_gpios[0]),GFP_KERNEL);
if(led_devs == NULL){
printk("No memory for device\n");
return -ENOMEM;
}
for(i = 0;i<sizeof(led_gpios)/sizeof(led_gpios[0];i++)
{
s3c_gpio_cfgpin(led_gpios[i].gpio,S3C_GPIO_OUTPUT);//设置为输出引脚
gpio_set_value(led_gpio[i].gpio,1);//熄灭灯
/*2、set*/
led_devs[i].cdev.max_brightness = LED_FULL;
led_devs[i].cdev.brightness_set = brightness_set_4412;//设置函数
led_devs[i].cdev.flags = LED_CORE_SUSPENDRESUME;//表示支持休眠唤醒功能
led_devs[i].cdev.brightness = LED_OFF;//当前led值
led_devs[i].cdev.name= led_gpios[i].name;///sys/class/leds/下创建节点
led_devs[i].gpio = led_gpios[i].gpio;
/*3、led_classdev_register*/
ret = led_classes_register(NULL,&led_devs[i].cdev);
if(ret){
i--;
while(i >=0){
led_classes_unregister(&led_devs[i].cdev);
i--;
}
kfree(led_devs);
return -EIO;
}
}
}
static void leds_exit(void)
{
int i;
for(i = 0;i<sizeof(led_gpios)/sizeof(led_gpios[0];i++)
{
led_classes_unregister(&led_devs[i].cdev);
]
kfree(led_devs);
}
module_init(leds_init);
module_exit(leds_exit);
MODULE_LICENSE("GPL");
注意:我们的驱动程序是嵌入到linux的led驱动框架中去的
把 leds_4412.c 放到drivers/leds
修改 drivers/leds/Makefile:
obj-y += leds_4412.o
make menuconfig
CONFIG_LEDS_CLASS
CONFIG_LEDS_TRIGGERS
CONFIG_LEDS_TRIGGER_TIMER
-> Device Drivers
-> LED Support
[*] LED Class Support
[*] LED Trigger support //实现定时器功能,led闪烁依赖定时器
<*> LED Timer Trigger
make zImage
关掉开发板,设置为SD卡启动,使用minitools烧写Android Kernel:zImage
关掉开发板,设置为nand启动
ls /sys/class/leds 会发现有了led1、led2、led3、led4