1/* 2 * LED Heartbeat Trigger 3 * 4 * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> 5 * 6 * Based on Richard Purdie's ledtrig-timer.c and some arch's 7 * CONFIG_HEARTBEAT code. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 */ 14#include <linux/module.h> 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/slab.h> 18#include <linux/timer.h> 19#include <linux/sched.h> 20#include <linux/leds.h> 21#include "leds.h" 22 23struct heartbeat_trig_data { 24 unsigned int phase; 25 unsigned int period; 26 struct timer_list timer; 27}; 28 29static void led_heartbeat_function(unsigned long data) 30{ 31 struct led_classdev *led_cdev = (struct led_classdev *) data; 32 struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; 33 unsigned long brightness = LED_OFF; 34 unsigned long delay = 0; 35 36 /* acts like an actual heart beat -- ie thump-thump-pause... */ 37 switch (heartbeat_data->phase) { 38 case 0: 39 /* 40 * The hyperbolic function below modifies the 41 * heartbeat period length in dependency of the 42 * current (1min) load. It goes through the points 43 * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300. 44 */ 45 heartbeat_data->period = 300 + 46 (6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT)); 47 heartbeat_data->period = 48 msecs_to_jiffies(heartbeat_data->period); 49 delay = msecs_to_jiffies(70); 50 heartbeat_data->phase++; 51 brightness = led_cdev->max_brightness; 52 break; 53 case 1: 54 delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); 55 heartbeat_data->phase++; 56 break; 57 case 2: 58 delay = msecs_to_jiffies(70); 59 heartbeat_data->phase++; 60 brightness = led_cdev->max_brightness; 61 break; 62 default: 63 delay = heartbeat_data->period - heartbeat_data->period / 4 - 64 msecs_to_jiffies(70); 65 heartbeat_data->phase = 0; 66 break; 67 } 68 69 led_set_brightness(led_cdev, brightness); 70 mod_timer(&heartbeat_data->timer, jiffies + delay); 71} 72 73static void heartbeat_trig_activate(struct led_classdev *led_cdev) 74{ 75 struct heartbeat_trig_data *heartbeat_data; 76 77 heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); 78 if (!heartbeat_data) 79 return; 80 81 led_cdev->trigger_data = heartbeat_data; 82 setup_timer(&heartbeat_data->timer, 83 led_heartbeat_function, (unsigned long) led_cdev); 84 heartbeat_data->phase = 0; 85 led_heartbeat_function(heartbeat_data->timer.data); 86} 87 88static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) 89{ 90 struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; 91 92 if (heartbeat_data) { 93 del_timer_sync(&heartbeat_data->timer); 94 kfree(heartbeat_data); 95 } 96} 97 98static struct led_trigger heartbeat_led_trigger = { 99 .name = "heartbeat", 100 .activate = heartbeat_trig_activate, 101 .deactivate = heartbeat_trig_deactivate, 102}; 103 104static int __init heartbeat_trig_init(void) 105{ 106 return led_trigger_register(&heartbeat_led_trigger); 107} 108 109static void __exit heartbeat_trig_exit(void) 110{ 111 led_trigger_unregister(&heartbeat_led_trigger); 112} 113 114module_init(heartbeat_trig_init); 115module_exit(heartbeat_trig_exit); 116 117MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); 118MODULE_DESCRIPTION("Heartbeat LED trigger"); 119MODULE_LICENSE("GPL"); 120