2006-03-31 02:31:07 -08:00
/*
* LED Kernel Timer Trigger
*
* Copyright 2005 - 2006 Openedhand Ltd .
*
* Author : Richard Purdie < rpurdie @ openedhand . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
*/
# include <linux/module.h>
2006-10-18 01:47:25 -04:00
# include <linux/jiffies.h>
2006-03-31 02:31:07 -08:00
# 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>
2006-05-15 09:44:17 -07:00
# include <linux/ctype.h>
2006-03-31 02:31:07 -08:00
# include <linux/leds.h>
# include "leds.h"
struct timer_trig_data {
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 = LED_OFF ;
unsigned long delay = timer_data - > delay_off ;
if ( ! timer_data - > delay_on | | ! timer_data - > delay_off ) {
led_set_brightness ( led_cdev , LED_OFF ) ;
return ;
}
if ( ! led_cdev - > brightness ) {
brightness = LED_FULL ;
delay = timer_data - > delay_on ;
}
led_set_brightness ( led_cdev , brightness ) ;
mod_timer ( & timer_data - > timer , jiffies + msecs_to_jiffies ( delay ) ) ;
}
2007-07-08 23:19:31 +01:00
static ssize_t led_delay_on_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-03-31 02:31:07 -08:00
{
2007-07-08 23:19:31 +01:00
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
2006-03-31 02:31:07 -08:00
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
sprintf ( buf , " %lu \n " , timer_data - > delay_on ) ;
return strlen ( buf ) + 1 ;
}
2007-07-08 23:19:31 +01:00
static ssize_t led_delay_on_store ( struct device * dev ,
struct device_attribute * attr , const char * buf , size_t size )
2006-03-31 02:31:07 -08:00
{
2007-07-08 23:19:31 +01:00
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
2006-03-31 02:31:07 -08:00
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
int ret = - EINVAL ;
char * after ;
unsigned long state = simple_strtoul ( buf , & after , 10 ) ;
2006-05-15 09:44:17 -07:00
size_t count = after - buf ;
2006-03-31 02:31:07 -08:00
2006-05-15 09:44:17 -07:00
if ( * after & & isspace ( * after ) )
count + + ;
if ( count = = size ) {
2006-03-31 02:31:07 -08:00
timer_data - > delay_on = state ;
mod_timer ( & timer_data - > timer , jiffies + 1 ) ;
2006-05-15 09:44:17 -07:00
ret = count ;
2006-03-31 02:31:07 -08:00
}
return ret ;
}
2007-07-08 23:19:31 +01:00
static ssize_t led_delay_off_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-03-31 02:31:07 -08:00
{
2007-07-08 23:19:31 +01:00
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
2006-03-31 02:31:07 -08:00
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
sprintf ( buf , " %lu \n " , timer_data - > delay_off ) ;
return strlen ( buf ) + 1 ;
}
2007-07-08 23:19:31 +01:00
static ssize_t led_delay_off_store ( struct device * dev ,
struct device_attribute * attr , const char * buf , size_t size )
2006-03-31 02:31:07 -08:00
{
2007-07-08 23:19:31 +01:00
struct led_classdev * led_cdev = dev_get_drvdata ( dev ) ;
2006-03-31 02:31:07 -08:00
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
int ret = - EINVAL ;
char * after ;
unsigned long state = simple_strtoul ( buf , & after , 10 ) ;
2006-05-15 09:44:17 -07:00
size_t count = after - buf ;
if ( * after & & isspace ( * after ) )
count + + ;
2006-03-31 02:31:07 -08:00
2006-05-15 09:44:17 -07:00
if ( count = = size ) {
2006-03-31 02:31:07 -08:00
timer_data - > delay_off = state ;
mod_timer ( & timer_data - > timer , jiffies + 1 ) ;
2006-05-15 09:44:17 -07:00
ret = count ;
2006-03-31 02:31:07 -08:00
}
return ret ;
}
2007-07-08 23:19:31 +01:00
static DEVICE_ATTR ( delay_on , 0644 , led_delay_on_show , led_delay_on_store ) ;
static DEVICE_ATTR ( delay_off , 0644 , led_delay_off_show , led_delay_off_store ) ;
2006-03-31 02:31:07 -08:00
static void timer_trig_activate ( struct led_classdev * led_cdev )
{
struct timer_trig_data * timer_data ;
2006-10-17 00:10:20 -07:00
int rc ;
2006-03-31 02:31:07 -08:00
timer_data = kzalloc ( sizeof ( struct timer_trig_data ) , GFP_KERNEL ) ;
if ( ! timer_data )
return ;
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 ;
2007-07-08 23:19:31 +01:00
rc = device_create_file ( led_cdev - > dev , & dev_attr_delay_on ) ;
if ( rc )
goto err_out ;
rc = device_create_file ( led_cdev - > dev , & dev_attr_delay_off ) ;
if ( rc )
goto err_out_delayon ;
2006-10-17 00:10:20 -07:00
return ;
err_out_delayon :
2007-07-08 23:19:31 +01:00
device_remove_file ( led_cdev - > dev , & dev_attr_delay_on ) ;
2006-10-17 00:10:20 -07:00
err_out :
led_cdev - > trigger_data = NULL ;
kfree ( timer_data ) ;
2006-03-31 02:31:07 -08:00
}
static void timer_trig_deactivate ( struct led_classdev * led_cdev )
{
struct timer_trig_data * timer_data = led_cdev - > trigger_data ;
if ( timer_data ) {
2007-07-08 23:19:31 +01:00
device_remove_file ( led_cdev - > dev , & dev_attr_delay_on ) ;
device_remove_file ( led_cdev - > dev , & dev_attr_delay_off ) ;
2006-03-31 02:31:07 -08:00
del_timer_sync ( & timer_data - > timer ) ;
kfree ( timer_data ) ;
}
}
static struct led_trigger timer_led_trigger = {
. name = " timer " ,
. activate = timer_trig_activate ,
. deactivate = timer_trig_deactivate ,
} ;
static int __init timer_trig_init ( void )
{
return led_trigger_register ( & timer_led_trigger ) ;
}
static void __exit timer_trig_exit ( void )
{
led_trigger_unregister ( & timer_led_trigger ) ;
}
module_init ( timer_trig_init ) ;
module_exit ( timer_trig_exit ) ;
MODULE_AUTHOR ( " Richard Purdie <rpurdie@openedhand.com> " ) ;
MODULE_DESCRIPTION ( " Timer LED trigger " ) ;
MODULE_LICENSE ( " GPL " ) ;