搜尋此網誌

Linux kernel 2.6 LED module HOW TO

1. Add kernel define
CONFIG_NEW_LEDS -> using kernel led driver code.
CONFIG_LEDS_CLASS-> enable led control by /sys/class/leds
CONFIG_LEDS_BL2348-> privacy arch and board led define
CONFIG_LEDS_TRIGGERS -> enable kernel led modue trigger feature
CONFIG_LEDS_TRIGGER_TIMER->  enable timer trigger

 CONFIG_LEDS_TRIGGER_HEARTBEAT-> enable heartbeat trigger


#
# LED devices
#
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
#
# LED drivers
#
CONFIG_LEDS_BL2348=y
#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 
2. write  driver body:
    (1)  in module init -> add bl2348_led_init
          in bl2348_led_init init  platform device add.
          platform driver as follow:
static struct platform_driver bl2348_led_driver = {
.probe = bl2348_led_probe,
.remove = bl2348_led_remove,
#ifdef CONFIG_PM
.suspend = bl2348_led_suspend,
.resume = bl2348_led_resume,
#else
.suspend = bl2348_led_suspend,
.resume = bl2348_led_resume,
#endif
.driver = {
.name = BL_2348_LED_DEV_NAME,
.owner = THIS_MODULE,
}  
};
        (2).write probe ,remove function.
           in probe function register led class by kernel _api :
                    led_classdev_register

      static struct led_classdev bl2348_power_led = {
.name = "power",
.default_trigger = "none",
.brightness_set = bl2348_power_set,
.color_set = bl2348_power_color_set,
.default_delay_on = 500,
.default_delay_off = 500,
.color = LED_RED,
.trigger_data = (void*) &bl2348_power_timer_default_on_off,
};
static struct led_classdev bl2348_gpon_link_led = {
.name = "gpon",
.default_trigger = "none",
.brightness_set = bl2348_gpon_link_set,
.default_delay_on = 500,
.default_delay_off = 500,
.color = LED_GREEN , /*Only LED_GREEN is valid,other value is no effect*/
.trigger_data = (void* )&bl2348_gpon_link_timer_default_on_off,
};
            implement  brightness_set ,color_set  callback functions.
         brightness_set will set led on or off,you need know how to call CPU r/w basic routine to
     enable/disable specific led.
        .default_trigger  will choose default trigger mode ,we have enable timer and heartbeat ,
      so possible value have "none" ,"timer" and "heartbeat"

         (3) Control in user space.
            if your led module initialize successfully.
        you will find files on
         /sys/class/leds

         Aspen@192.168.1.1:/sys/class/leds> ls -al
drwxr-xr-x 4 root root 0 Jan 1 2000 .
drwxr-xr-x 9 root root 0 Jan 1 2000 ..
drwxr-xr-x 2 root root 0 Jan 1 2000 gpon
drwxr-xr-x 2 root root 0 Jan 1 2000 power
 
            Aspen@192.168.1.1:/sys/class/leds/power> ls -al
drwxr-xr-x 2 root root 0 Jan 1 2000 .
drwxr-xr-x 4 root root 0 Jan 1 2000 ..
-rw-r--r-- 1 root root 0 Jan 1 2000 brightness
-rw-r--r-- 1 root root 0 Jan 1 2000 color
-rw-r--r-- 1 root root 0 Jan 1 2000 delay_off
-rw-r--r-- 1 root root 0 Jan 1 2000 delay_on
lrwxrwxrwx 1 root root 0 Jan 1 2000 device -> ../../../devices/platform/bl2348led
lrwxrwxrwx 1 root root 0 Jan 1 2000 subsystem -> ../../../class/leds
-rw-r--r-- 1 root root 0 Jan 1 2000 trigger
--w------- 1 root root 4096                     
 
                    check current trigger mode :
               Aspen@192.168.1.1:/sys/class/leds/power> cat trigger
none [timer] heartbeat
                      --------> see , using timer mode now.
                   want to change trigger mode jsut :
                    echo  heartbeat > trigger
                 Aspen@192.168.1.1:/sys/class/leds/power> cat trigger
none timer [heartbeat]
                     --------> see , using heartbeat mode now.
 

                      delay_off and delay_on will valid when trigger mode is timer.






                  

Kernel 2.6 platform device add method.

  1.device_initcall
static struct platform_device bl23xx_dying_gasp_device = {

.name = BL_2348_DGASP_DEV_NAME,
.id = 0,
.num_resources = ARRAY_SIZE(bl2348_dying_gasp_resources),
.resource = bl2348_dying_gasp_resources,
};

static struct platform_device bl23xx_led_device = {
.name = BL_2348_LED_DEV_NAME,
.id = -1,
.num_resources = 0,
.resource = NULL ,
};static struct platform_device *bl2348_devices[] __initdata = {

&bl23xx_led_device,
&bl23xx_dying_gasp_device,
};
void bl2348_add_platform_device(void){
int ret;
ret =platform_add_devices(bl2348_devices, ARRAY_SIZE(bl2348_devices));
#ifdef PLATFORM_DEVICE_DEBUG
if(!ret)
printk(KERN_ALERT "========> bl2348 Platform device add success\n");
else
printk(KERN_ALERT "========> bl2348 Platform device add fail\n");
#endif
}

device_initcall(bl2348_add_platform_device);/*Jacky.Xue : extra device resource required */

2. kernel API : platform_device_register_simple
EXAMPLE:
led2348pdev = platform_device_register_simple(BL_2348_LED_DEV_NAME, -1, NULL, 0);

if (IS_ERR(led2348pdev)) {
ret = PTR_ERR(led2348pdev);
platform_driver_unregister(&bl2348_led_driver);
goto out;

Build kernel module in kernel source tree,avoid external symbol reference WARNNING make exit!

   export KBUILD_MODPOST_WARN
   export KBUILD_MODPOST_WARN:=1
   export KBUILD_MODPOST_WARN:=0

Kernel 2.6 Default config name rule.

     Kernel 2.6 support
make -C $(KDIR) ARCH=mips xxxxxxxx_defconfig

   the xxxxxxxx_defconfig should copy into $(KDIR)/arch/mips/configs


   Here, the xxxxxxxx_defconfig ,xxxxxxxx can be any string, and _defconfig must be same string.