@ -12,73 +12,25 @@
*/
# include <linux/module.h>
# include <linux/jiffies.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/list.h>
# include <linux/spinlock.h>
# include <linux/device.h>
# include <linux/sysdev.h>
# include <linux/timer.h>
# include <linux/ctype.h>
# include <linux/leds.h>
# include <linux/slab.h>
# include "leds.h"
struct timer_trig_data {
int brightness_on ; /* LED brightness during "on" period.
* ( LED_OFF < brightness_on < = LED_FULL )
*/
unsigned long delay_on ; /* milliseconds on */
unsigned long delay_off ; /* milliseconds off */
struct timer_list timer ;
} ;
static void led_timer_function ( unsigned long data )
{
struct led_classdev * led_cdev = ( struct led_classdev * ) data ;
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
unsigned long brightness ;
unsigned long delay ;
if ( ! timer_data - > delay_on | | ! timer_data - > delay_off ) {
led_set_brightness ( led_cdev , LED_OFF ) ;
return ;
}
brightness = led_get_brightness ( led_cdev ) ;
if ( ! brightness ) {
/* Time to switch the LED on. */
brightness = timer_data - > brightness_on ;
delay = timer_data - > delay_on ;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over .
*/
timer_data - > brightness_on = brightness ;
brightness = LED_OFF ;
delay = timer_data - > delay_off ;
}
led_set_brightness ( led_cdev , brightness ) ;
mod_timer ( & timer_data - > timer , jiffies + msecs_to_jiffies ( delay ) ) ;
}
static ssize_t led_delay_on_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
return sprintf ( buf , " %lu \n " , timer_data - > delay_on ) ;
return sprintf ( buf , " %lu \n " , led_cdev - > blink_delay_on ) ;
}
static ssize_t led_delay_on_store ( struct device * dev ,
struct device_attribute * attr , const char * buf , size_t size )
{
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
int ret = - EINVAL ;
char * after ;
unsigned long state = simple_strtoul ( buf , & after , 10 ) ;
@ -88,21 +40,7 @@ static ssize_t led_delay_on_store(struct device *dev,
count + + ;
if ( count = = size ) {
if ( timer_data - > delay_on ! = state ) {
/* the new value differs from the previous */
timer_data - > delay_on = state ;
/* deactivate previous settings */
del_timer_sync ( & timer_data - > timer ) ;
/* try to activate hardware acceleration, if any */
if ( ! led_cdev - > blink_set | |
led_cdev - > blink_set ( led_cdev ,
& timer_data - > delay_on , & timer_data - > delay_off ) ) {
/* no hardware acceleration, blink via timer */
mod_timer ( & timer_data - > timer , jiffies + 1 ) ;
}
}
led_blink_set ( led_cdev , & state , & led_cdev - > blink_delay_off ) ;
ret = count ;
}
@ -113,16 +51,14 @@ static ssize_t led_delay_off_show(struct device *dev,
struct device_attribute * attr , char * buf )
{
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
return sprintf ( buf , " %lu \n " , timer_data - > delay_off ) ;
return sprintf ( buf , " %lu \n " , led_cdev - > blink_ delay_off) ;
}
static ssize_t led_delay_off_store ( struct device * dev ,
struct device_attribute * attr , const char * buf , size_t size )
{
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
int ret = - EINVAL ;
char * after ;
unsigned long state = simple_strtoul ( buf , & after , 10 ) ;
@ -132,21 +68,7 @@ static ssize_t led_delay_off_store(struct device *dev,
count + + ;
if ( count = = size ) {
if ( timer_data - > delay_off ! = state ) {
/* the new value differs from the previous */
timer_data - > delay_off = state ;
/* deactivate previous settings */
del_timer_sync ( & timer_data - > timer ) ;
/* try to activate hardware acceleration, if any */
if ( ! led_cdev - > blink_set | |
led_cdev - > blink_set ( led_cdev ,
& timer_data - > delay_on , & timer_data - > delay_off ) ) {
/* no hardware acceleration, blink via timer */
mod_timer ( & timer_data - > timer , jiffies + 1 ) ;
}
}
led_blink_set ( led_cdev , & led_cdev - > blink_delay_on , & state ) ;
ret = count ;
}
@ -158,60 +80,34 @@ static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
static void timer_trig_activate ( struct led_classdev * led_cdev )
{
struct timer_trig_data * timer_data ;
int rc ;
timer_data = kzalloc ( sizeof ( struct timer_trig_data ) , GFP_KERNEL ) ;
if ( ! timer_data )
return ;
timer_data - > brightness_on = led_get_brightness ( led_cdev ) ;
if ( timer_data - > brightness_on = = LED_OFF )
timer_data - > brightness_on = led_cdev - > max_brightness ;
led_cdev - > trigger_data = timer_data ;
init_timer ( & timer_data - > timer ) ;
timer_data - > timer . function = led_timer_function ;
timer_data - > timer . data = ( unsigned long ) led_cdev ;
led_cdev - > trigger_data = NULL ;
rc = device_create_file ( led_cdev - > dev , & dev_attr_delay_on ) ;
if ( rc )
goto err_out ;
return ;
rc = device_create_file ( led_cdev - > dev , & dev_attr_delay_off ) ;
if ( rc )
goto err_out_delayon ;
/* If there is hardware support for blinking, start one
* user friendly blink rate chosen by the driver .
*/
if ( led_cdev - > blink_set )
led_cdev - > blink_set ( led_cdev ,
& timer_data - > delay_on , & timer_data - > delay_off ) ;
led_cdev - > trigger_data = ( void * ) 1 ;
return ;
err_out_delayon :
device_remove_file ( led_cdev - > dev , & dev_attr_delay_on ) ;
err_out :
led_cdev - > trigger_data = NULL ;
kfree ( timer_data ) ;
}
static void timer_trig_deactivate ( struct led_classdev * led_cdev )
{
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
unsigned long on = 0 , off = 0 ;
if ( timer_data ) {
if ( led_cdev - > trigger_data ) {
device_remove_file ( led_cdev - > dev , & dev_attr_delay_on ) ;
device_remove_file ( led_cdev - > dev , & dev_attr_delay_off ) ;
del_timer_sync ( & timer_data - > timer ) ;
kfree ( timer_data ) ;
}
/* If there is hardware support for blinking, stop it */
if ( led_cdev - > blink_set )
led_cdev - > blink_set ( led_cdev , & on , & off ) ;
/* Stop blinking */
led_brightness_set ( led_cdev , LED_OFF ) ;
}
static struct led_trigger timer_led_trigger = {