linux/arch/sparc/kernel/led.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/module.h>
   3#include <linux/init.h>
   4#include <linux/proc_fs.h>
   5#include <linux/seq_file.h>
   6#include <linux/slab.h>
   7#include <linux/string.h>
   8#include <linux/jiffies.h>
   9#include <linux/timer.h>
  10#include <linux/uaccess.h>
  11
  12#include <asm/auxio.h>
  13
  14#define LED_MAX_LENGTH 8 /* maximum chars written to proc file */
  15
  16static inline void led_toggle(void)
  17{
  18        unsigned char val = get_auxio();
  19        unsigned char on, off;
  20
  21        if (val & AUXIO_LED) {
  22                on = 0;
  23                off = AUXIO_LED;
  24        } else {
  25                on = AUXIO_LED;
  26                off = 0;
  27        }
  28
  29        set_auxio(on, off);
  30}
  31
  32static struct timer_list led_blink_timer;
  33
  34static void led_blink(unsigned long timeout)
  35{
  36        led_toggle();
  37
  38        /* reschedule */
  39        if (!timeout) { /* blink according to load */
  40                led_blink_timer.expires = jiffies +
  41                        ((1 + (avenrun[0] >> FSHIFT)) * HZ);
  42                led_blink_timer.data = 0;
  43        } else { /* blink at user specified interval */
  44                led_blink_timer.expires = jiffies + (timeout * HZ);
  45                led_blink_timer.data = timeout;
  46        }
  47        add_timer(&led_blink_timer);
  48}
  49
  50static int led_proc_show(struct seq_file *m, void *v)
  51{
  52        if (get_auxio() & AUXIO_LED)
  53                seq_puts(m, "on\n");
  54        else
  55                seq_puts(m, "off\n");
  56        return 0;
  57}
  58
  59static int led_proc_open(struct inode *inode, struct file *file)
  60{
  61        return single_open(file, led_proc_show, NULL);
  62}
  63
  64static ssize_t led_proc_write(struct file *file, const char __user *buffer,
  65                              size_t count, loff_t *ppos)
  66{
  67        char *buf = NULL;
  68
  69        if (count > LED_MAX_LENGTH)
  70                count = LED_MAX_LENGTH;
  71
  72        buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL);
  73        if (!buf)
  74                return -ENOMEM;
  75
  76        if (copy_from_user(buf, buffer, count)) {
  77                kfree(buf);
  78                return -EFAULT;
  79        }
  80
  81        buf[count] = '\0';
  82
  83        /* work around \n when echo'ing into proc */
  84        if (buf[count - 1] == '\n')
  85                buf[count - 1] = '\0';
  86
  87        /* before we change anything we want to stop any running timers,
  88         * otherwise calls such as on will have no persistent effect
  89         */
  90        del_timer_sync(&led_blink_timer);
  91
  92        if (!strcmp(buf, "on")) {
  93                auxio_set_led(AUXIO_LED_ON);
  94        } else if (!strcmp(buf, "toggle")) {
  95                led_toggle();
  96        } else if ((*buf > '0') && (*buf <= '9')) {
  97                led_blink(simple_strtoul(buf, NULL, 10));
  98        } else if (!strcmp(buf, "load")) {
  99                led_blink(0);
 100        } else {
 101                auxio_set_led(AUXIO_LED_OFF);
 102        }
 103
 104        kfree(buf);
 105
 106        return count;
 107}
 108
 109static const struct file_operations led_proc_fops = {
 110        .owner          = THIS_MODULE,
 111        .open           = led_proc_open,
 112        .read           = seq_read,
 113        .llseek         = seq_lseek,
 114        .release        = single_release,
 115        .write          = led_proc_write,
 116};
 117
 118static struct proc_dir_entry *led;
 119
 120#define LED_VERSION     "0.1"
 121
 122static int __init led_init(void)
 123{
 124        init_timer(&led_blink_timer);
 125        led_blink_timer.function = led_blink;
 126
 127        led = proc_create("led", 0, NULL, &led_proc_fops);
 128        if (!led)
 129                return -ENOMEM;
 130
 131        printk(KERN_INFO
 132               "led: version %s, Lars Kotthoff <metalhead@metalhead.ws>\n",
 133               LED_VERSION);
 134
 135        return 0;
 136}
 137
 138static void __exit led_exit(void)
 139{
 140        remove_proc_entry("led", NULL);
 141        del_timer_sync(&led_blink_timer);
 142}
 143
 144module_init(led_init);
 145module_exit(led_exit);
 146
 147MODULE_AUTHOR("Lars Kotthoff <metalhead@metalhead.ws>");
 148MODULE_DESCRIPTION("Provides control of the front LED on SPARC systems.");
 149MODULE_LICENSE("GPL");
 150MODULE_VERSION(LED_VERSION);
 151