diff options
Diffstat (limited to 'drivers/leds/led-class-3g.c')
-rw-r--r-- | drivers/leds/led-class-3g.c | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/drivers/leds/led-class-3g.c b/drivers/leds/led-class-3g.c new file mode 100644 index 00000000000..c0c1c11cbdb --- /dev/null +++ b/drivers/leds/led-class-3g.c @@ -0,0 +1,281 @@ +/* + * LED Class Core + * + * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> + * Copyright (C) 2005-2007 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> +#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/err.h> +#include <linux/ctype.h> +#include <linux/leds.h> +#include "leds.h" + +static struct class *leds_class; + +static void led_update_color(struct led_classdev *led_cdev) +{ + if (led_cdev->color_get) + led_cdev->color = led_cdev->color_get(led_cdev); +} + +static ssize_t led_color_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + unsigned long state = 9; + + switch (buf[0]) { + case 'r': /* red */ + state = 1; + break; + case 'g': /* green */ + state = 2; + break; + case 'b': /* blue */ + state = 3; + break; + case 'y': /* yellow */ + state = 4; + break; + case 'w': /* white */ + state = 5; + break; + case 'o': /* off */ + state = 0; + break; + default: + break; + } + + led_set_color(led_cdev, state); + + return (ssize_t)size; +} + +static ssize_t led_color_show(struct device *dev, + struct device_attribute *attr, char *buf) { + + struct led_classdev *led_cdev = dev_get_drvdata(dev); + char * readbuf[] = {"off", "red", "green", "blue", "yellow", "white"} ; + /* no lock needed for this */ + led_update_color(led_cdev); + + return sprintf(buf, "%s\n", readbuf[led_cdev->color]); +} + +static ssize_t led_blink_show(struct device *dev, struct device_attribute *attr, + char *buf) { + char *blinkStr = "no"; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + if( led_cdev->blink == 0 ){ + blinkStr = "no"; + } + else if (led_cdev->blink == 1 ){ + blinkStr = "yes"; + } + return sprintf(buf, "%s\n", blinkStr); +} + +static ssize_t led_blink_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) { + int val = 0; + struct led_classdev * led_cdev = dev_get_drvdata(dev); + + if( buf[0] == 'y' ) { + val = 1; + } + else if( buf[0] == 'n' ) { + val = 0; + } + else if( buf[0] == 'f' ) { + val = 2; + } + led_set_blink( led_cdev, val ); + + return (ssize_t)size; +} + +static ssize_t led_max_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", led_cdev->max_brightness); +} + +/*static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store);*/ +static DEVICE_ATTR(color, 0644, led_color_show, led_color_store); +static DEVICE_ATTR(blink, 0644, led_blink_show, led_blink_store); +static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL); +#ifdef CONFIG_LEDS_TRIGGERS +static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); +#endif + +/** + * led_classdev_suspend - suspend an led_classdev. + * @led_cdev: the led_classdev to suspend. + */ +void led_classdev_suspend(struct led_classdev *led_cdev) +{ + led_cdev->flags |= LED_SUSPENDED; + led_cdev->color_set(led_cdev, 0); +} +EXPORT_SYMBOL_GPL(led_classdev_suspend); + +/** + * led_classdev_resume - resume an led_classdev. + * @led_cdev: the led_classdev to resume. + */ +void led_classdev_resume(struct led_classdev *led_cdev) +{ + led_cdev->color_set(led_cdev, led_cdev->color); + led_cdev->flags &= ~LED_SUSPENDED; +} +EXPORT_SYMBOL_GPL(led_classdev_resume); + +static int led_suspend(struct device *dev, pm_message_t state) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + if (led_cdev->flags & LED_CORE_SUSPENDRESUME) + led_classdev_suspend(led_cdev); + + return 0; +} + +static int led_resume(struct device *dev) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + if (led_cdev->flags & LED_CORE_SUSPENDRESUME) + led_classdev_resume(led_cdev); + + return 0; +} + +/** + * led_classdev_register - register a new object of led_classdev class. + * @parent: The device to register. + * @led_cdev: the led_classdev structure for this device. + */ +int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) +{ + int rc; + + led_cdev->dev = device_create(leds_class, parent, 0, led_cdev, + "%s", led_cdev->name); + if (IS_ERR(led_cdev->dev)) + return PTR_ERR(led_cdev->dev); + + /* register the attributes */ + rc = device_create_file(led_cdev->dev, &dev_attr_color); + if (rc) + goto err_out; + + rc = device_create_file(led_cdev->dev, &dev_attr_blink); + if (rc) + goto err_out; + +#ifdef CONFIG_LEDS_TRIGGERS + init_rwsem(&led_cdev->trigger_lock); +#endif + /* add to the list of leds */ + down_write(&leds_list_lock); + list_add_tail(&led_cdev->node, &leds_list); + up_write(&leds_list_lock); + + if (!led_cdev->max_brightness) + led_cdev->max_brightness = LED_FULL; + + rc = device_create_file(led_cdev->dev, &dev_attr_max_brightness); + if (rc) + goto err_out_attr_max; + + led_update_color(led_cdev); + +#ifdef CONFIG_LEDS_TRIGGERS + rc = device_create_file(led_cdev->dev, &dev_attr_trigger); + if (rc) + goto err_out_led_list; + + led_trigger_set_default(led_cdev); +#endif + + printk(KERN_INFO "Registered led device: %s\n", + led_cdev->name); + + return 0; + +#ifdef CONFIG_LEDS_TRIGGERS +err_out_led_list: + device_remove_file(led_cdev->dev, &dev_attr_max_brightness); +#endif +err_out_attr_max: + device_remove_file(led_cdev->dev, &dev_attr_color); + list_del(&led_cdev->node); +err_out: + device_unregister(led_cdev->dev); + return rc; +} +EXPORT_SYMBOL_GPL(led_classdev_register); + +/** + * led_classdev_unregister - unregisters a object of led_properties class. + * @led_cdev: the led device to unregister + * + * Unregisters a previously registered via led_classdev_register object. + */ +void led_classdev_unregister(struct led_classdev *led_cdev) +{ + device_remove_file(led_cdev->dev, &dev_attr_max_brightness); + device_remove_file(led_cdev->dev, &dev_attr_color); +#ifdef CONFIG_LEDS_TRIGGERS + device_remove_file(led_cdev->dev, &dev_attr_trigger); + down_write(&led_cdev->trigger_lock); + if (led_cdev->trigger) + led_trigger_set(led_cdev, NULL); + up_write(&led_cdev->trigger_lock); +#endif + + device_unregister(led_cdev->dev); + + down_write(&leds_list_lock); + list_del(&led_cdev->node); + up_write(&leds_list_lock); +} +EXPORT_SYMBOL_GPL(led_classdev_unregister); + +static int __init leds_init(void) +{ + leds_class = class_create(THIS_MODULE, "leds"); + if (IS_ERR(leds_class)) + return PTR_ERR(leds_class); + leds_class->suspend = led_suspend; + leds_class->resume = led_resume; + return 0; +} + +static void __exit leds_exit(void) +{ + class_destroy(leds_class); +} + +subsys_initcall(leds_init); +module_exit(leds_exit); + +MODULE_AUTHOR("John Lenz, Richard Purdie"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LED Class Interface"); |