第2课第1节_Android灯光系统_led_class驱动


2. Linux的led class驱动
android-5.0.2\hardware\libhardware\include\hardware\lights.h

 

 


怎么写驱动:
a1. 分配led_classdev
a2. 设置 :
led_cdev->max_brightness
led_cdev->brightness_set
led_cdev->flags
led_cdev->brightness
led_cdev->name

 

驱动放入Linux内核:

v1:
放入内核 drivers/char
修改 drivers/char/Makefile,添加:
obj-y += leds_4412.o

 


重新编译内核

v2:
把 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 Timer Trigger
   
重新编译内核
make zImage
开发板从SD卡启动,烧写zImage

 

 


echo 255 > /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/max_brightness

闪烁
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_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"
timer_trig_activate
// 6. 创建2个文件: delay_on, delay_off
device_create_file
device_create_file
led_blink_set // 让LED闪烁
led_set_software_blink


}
}


echo 100 > /sys/class/leds/led1/delay_on
led_delay_on_store
state = simple_strtoul(buf, &after, 10);
led_blink_set // // 让LED闪烁
led_cdev->blink_delay_on = state;

 

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;

 

 leds_4412.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
 
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>

#include <linux/leds.h>

struct led_desc {
    int gpio;
    char *name;
};

static struct led_desc led_gpios[] = {
    {EXYNOS4212_GPM4(0), "led1"},
    {EXYNOS4212_GPM4(1), "led2"},
    {EXYNOS4212_GPM4(2), "led3"},
    {EXYNOS4212_GPM4(3), "led4"},
};

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_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_gpios[i].gpio, 1);

        /* 2. set */
        led_devs[i].cdev.max_brightness = LED_FULL;   //LED_FULL=255
        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_devs[i].cdev.name = led_gpios[i].name;
        //led_devs[i].cdev.default_trigger = "timer";
        led_devs[i].gpio = led_gpios[i].gpio;

        /* 3. led_classdev_register */
        ret = led_classdev_register(NULL, &led_devs[i].cdev);
        if (ret) {
            i--;
            while (i >= 0) {
                led_classdev_unregister(&led_devs[i].cdev);
                i--;
            }
            kfree(led_devs);
            return -EIO;
        }
    }
    
    return 0;
}

static void leds_exit(void)
{
    int i;
    for (i = 0; i < sizeof(led_gpios)/sizeof(led_gpios[0]); i++)
    {
        led_classdev_unregister(&led_devs[i].cdev);
    }
    kfree(led_devs);
}

module_init(leds_init);
module_exit(leds_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.100ask.net");

 

posted on 2017-06-22 16:02  竹林海宝  阅读(454)  评论(0编辑  收藏  举报

导航