1.对灯光的要求

(1)亮度可调节,如背光灯
(2)颜色可变化,如电池电量指示灯
(3)能闪烁,如通知灯


2.Linux内核对led的支持

在Linux内核中已经实现了一个led class, 它里面已经实现了brightness的调节和blink,文件为:drivers/leds/led-class.c
在ledinit()中的led_class_attrs在/sys/class/leds下创建了brightness max_brightness trigger文件。


3.使用Linux内核中的led class
(1)配置内核
make menuconfig选中:
CONFIG_LEDS_CLASS
CONFIG_LEDS_TRIGGERS
CONFIG_LEDS_TRIGGER_TIMER
(2)驱动编写流程
a.分配led_classdev结构体
b.设置
c.注册
可以参考leds-s3c24xx.c,驱动Demo如下:

#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;
};

/*三星的goio引脚根本就不需要获取就可以直接使用*/
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; /*每一个led绑定的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); /*打开led*/
    else
        gpio_set_value(dev->gpio, 1); /*关闭led*/
}


static int leds_init(void)
{
    int i;
    int ret;

    /* 1. alloc led_classdev */
    led_devs = kzalloc(sizeof(struct led_classdev_4412) * ARRAY_SIZE(led_gpios), GFP_KERNEL);
    if (led_devs == NULL) {
        printk("No memory for device\n");
        return -ENOMEM;
    }

    for (i = 0; i < ARRAY_SIZE(led_gpios); i++)
    {
        s3c_gpio_cfgpin(led_gpios[i].gpio, S3C_GPIO_OUTPUT);
        /*默认led全部关闭*/
        gpio_set_value(led_gpios[i].gpio, 1);

        /* 2. set 这里面哪些域需要设置由led-class.c的实现决定的*/
        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_devs[i].cdev.name = led_gpios[i].name;
        led_devs[i].gpio = led_gpios[i].gpio;

        //led_devs[i].cdev.default_trigger = "timer";
        //led_devs[i].cdev.blink_delay_on = 100;
        //led_devs[i].cdev.blink_delay_off = 900;

        /* 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 < ARRAY_SIZE(led_gpios); i++)
    {
        led_classdev_unregister(&led_devs[i].cdev);
    }
    kfree(led_devs);
}

module_init(leds_init);
module_exit(leds_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mr.Sun");
View Code

相关文章: