/*
 * LED Triggers Core
 *
 * 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>
#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/leds.h>
#include "leds.h"

/*
 * Nests outside led_cdev->trigger_lock
 */
static DEFINE_RWLOCK(triggers_list_lock);
static LIST_HEAD(trigger_list);

ssize_t led_trigger_store(struct class_device *dev, const char *buf,
			size_t count)
{
	struct led_classdev *led_cdev = class_get_devdata(dev);
	char trigger_name[TRIG_NAME_MAX];
	struct led_trigger *trig;
	size_t len;

	trigger_name[sizeof(trigger_name) - 1] = '\0';
	strncpy(trigger_name, buf, sizeof(trigger_name) - 1);
	len = strlen(trigger_name);

	if (len && trigger_name[len - 1] == '\n')
		trigger_name[len - 1] = '\0';

	if (!strcmp(trigger_name, "none")) {
		write_lock(&led_cdev->trigger_lock);
		led_trigger_set(led_cdev, NULL);
		write_unlock(&led_cdev->trigger_lock);
		return count;
	}

	read_lock(&triggers_list_lock);
	list_for_each_entry(trig, &trigger_list, next_trig) {
		if (!strcmp(trigger_name, trig->name)) {
			write_lock(&led_cdev->trigger_lock);
			led_trigger_set(led_cdev, trig);
			write_unlock(&led_cdev->trigger_lock);

			read_unlock(&triggers_list_lock);
			return count;
		}
	}
	read_unlock(&triggers_list_lock);

	return -EINVAL;
}


ssize_t led_trigger_show(struct class_device *dev, char *buf)
{
	struct led_classdev *led_cdev = class_get_devdata(dev);
	struct led_trigger *trig;
	int len = 0;

	read_lock(&triggers_list_lock);
	read_lock(&led_cdev->trigger_lock);

	if (!led_cdev->trigger)
		len += sprintf(buf+len, "[none] ");
	else
		len += sprintf(buf+len, "none ");

	list_for_each_entry(trig, &trigger_list, next_trig) {
		if (led_cdev->trigger && !strcmp(led_cdev->trigger->name,
							trig->name))
			len += sprintf(buf+len, "[%s] ", trig->name);
		else
			len += sprintf(buf+len, "%s ", trig->name);
	}
	read_unlock(&led_cdev->trigger_lock);
	read_unlock(&triggers_list_lock);

	len += sprintf(len+buf, "\n");
	return len;
}

void led_trigger_event(struct led_trigger *trigger,
			enum led_brightness brightness)
{
	struct list_head *entry;

	if (!trigger)
		return;

	read_lock(&trigger->leddev_list_lock);
	list_for_each(entry, &trigger->led_cdevs) {
		struct led_classdev *led_cdev;

		led_cdev = list_entry(entry, struct led_classdev, trig_list);
		led_set_brightness(led_cdev, brightness);
	}
	read_unlock(&trigger->leddev_list_lock);
}

/* Caller must ensure led_cdev->trigger_lock held */
void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
{
	unsigned long flags;

	/* Remove any existing trigger */
	if (led_cdev->trigger) {
		write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
		list_del(&led_cdev->trig_list);
		write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
		if (led_cdev->trigger->deactivate)
			led_cdev->trigger->deactivate(led_cdev);
	}
	if (trigger) {
		write_lock_irqsave(&trigger->leddev_list_lock, flags);
		list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
		write_unlock_irqrestore(&trigger->leddev_list_lock, flags);
		if (trigger->activate)
			trigger->activate(led_cdev);
	}
	led_cdev->trigger = trigger;
}

void led_trigger_set_default(struct led_classdev *led_cdev)
{
	struct led_trigger *trig;

	if (!led_cdev->default_trigger)
		return;

	read_lock(&triggers_list_lock);
	write_lock(&led_cdev->trigger_lock);
	list_for_each_entry(trig, &trigger_list, next_trig) {
		if (!strcmp(led_cdev->default_trigger, trig->name))
			led_trigger_set(led_cdev, trig);
	}
	write_unlock(&led_cdev->trigger_lock);
	read_unlock(&triggers_list_lock);
}

int led_trigger_register(struct led_trigger *trigger)
{
	struct led_classdev *led_cdev;

	rwlock_init(&trigger->leddev_list_lock);
	INIT_LIST_HEAD(&trigger->led_cdevs);

	/* Add to the list of led triggers */
	write_lock(&triggers_list_lock);
	list_add_tail(&trigger->next_trig, &trigger_list);
	write_unlock(&triggers_list_lock);

	/* Register with any LEDs that have this as a default trigger */
	read_lock(&leds_list_lock);
	list_for_each_entry(led_cdev, &leds_list, node) {
		write_lock(&led_cdev->trigger_lock);
		if (!led_cdev->trigger && led_cdev->default_trigger &&
			    !strcmp(led_cdev->default_trigger, trigger->name))
			led_trigger_set(led_cdev, trigger);
		write_unlock(&led_cdev->trigger_lock);
	}
	read_unlock(&leds_list_lock);

	return 0;
}

void led_trigger_register_simple(const char *name, struct led_trigger **tp)
{
	struct led_trigger *trigger;

	trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);

	if (trigger) {
		trigger->name = name;
		led_trigger_register(trigger);
	}
	*tp = trigger;
}

void led_trigger_unregister(struct led_trigger *trigger)
{
	struct led_classdev *led_cdev;

	/* Remove from the list of led triggers */
	write_lock(&triggers_list_lock);
	list_del(&trigger->next_trig);
	write_unlock(&triggers_list_lock);

	/* Remove anyone actively using this trigger */
	read_lock(&leds_list_lock);
	list_for_each_entry(led_cdev, &leds_list, node) {
		write_lock(&led_cdev->trigger_lock);
		if (led_cdev->trigger == trigger)
			led_trigger_set(led_cdev, NULL);
		write_unlock(&led_cdev->trigger_lock);
	}
	read_unlock(&leds_list_lock);
}

void led_trigger_unregister_simple(struct led_trigger *trigger)
{
	led_trigger_unregister(trigger);
	kfree(trigger);
}

/* Used by LED Class */
EXPORT_SYMBOL_GPL(led_trigger_set);
EXPORT_SYMBOL_GPL(led_trigger_set_default);
EXPORT_SYMBOL_GPL(led_trigger_show);
EXPORT_SYMBOL_GPL(led_trigger_store);

/* LED Trigger Interface */
EXPORT_SYMBOL_GPL(led_trigger_register);
EXPORT_SYMBOL_GPL(led_trigger_unregister);

/* Simple LED Tigger Interface */
EXPORT_SYMBOL_GPL(led_trigger_register_simple);
EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
EXPORT_SYMBOL_GPL(led_trigger_event);

MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LED Triggers Core");
