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

posted on 2018-06-03 14:15  拉风摊主  阅读(467)  评论(0编辑  收藏  举报

导航