/*
 * LED support for the input layer
 *
 * Copyright 2010-2015 Samuel Thibault <samuel.thibault@ens-lyon.org>
 *
 * 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/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/leds.h>
#include <linux/input.h>

#if IS_ENABLED(CONFIG_VT)
#define VT_TRIGGER(_name)	.trigger = _name
#else
#define VT_TRIGGER(_name)	.trigger = NULL
#endif

static const struct {
	const char *name;
	const char *trigger;
} input_led_info[LED_CNT] = {
	[LED_NUML]	= { "numlock", VT_TRIGGER("kbd-numlock") },
	[LED_CAPSL]	= { "capslock", VT_TRIGGER("kbd-capslock") },
	[LED_SCROLLL]	= { "scrolllock", VT_TRIGGER("kbd-scrolllock") },
	[LED_COMPOSE]	= { "compose" },
	[LED_KANA]	= { "kana", VT_TRIGGER("kbd-kanalock") },
	[LED_SLEEP]	= { "sleep" } ,
	[LED_SUSPEND]	= { "suspend" },
	[LED_MUTE]	= { "mute" },
	[LED_MISC]	= { "misc" },
	[LED_MAIL]	= { "mail" },
	[LED_CHARGING]	= { "charging" },
};

struct input_led {
	struct led_classdev cdev;
	struct input_handle *handle;
	unsigned int code; /* One of LED_* constants */
};

struct input_leds {
	struct input_handle handle;
	unsigned int num_leds;
	struct input_led leds[];
};

static enum led_brightness input_leds_brightness_get(struct led_classdev *cdev)
{
	struct input_led *led = container_of(cdev, struct input_led, cdev);
	struct input_dev *input = led->handle->dev;

	return test_bit(led->code, input->led) ? cdev->max_brightness : 0;
}

static void input_leds_brightness_set(struct led_classdev *cdev,
				      enum led_brightness brightness)
{
	struct input_led *led = container_of(cdev, struct input_led, cdev);

	input_inject_event(led->handle, EV_LED, led->code, !!brightness);
}

static void input_leds_event(struct input_handle *handle, unsigned int type,
			     unsigned int code, int value)
{
}

static int input_leds_get_count(struct input_dev *dev)
{
	unsigned int led_code;
	int count = 0;

	for_each_set_bit(led_code, dev->ledbit, LED_CNT)
		if (input_led_info[led_code].name)
			count++;

	return count;
}

static int input_leds_connect(struct input_handler *handler,
			      struct input_dev *dev,
			      const struct input_device_id *id)
{
	struct input_leds *leds;
	unsigned int num_leds;
	unsigned int led_code;
	int led_no;
	int error;

	num_leds = input_leds_get_count(dev);
	if (!num_leds)
		return -ENXIO;

	leds = kzalloc(sizeof(*leds) + num_leds * sizeof(*leds->leds),
		       GFP_KERNEL);
	if (!leds)
		return -ENOMEM;

	leds->num_leds = num_leds;

	leds->handle.dev = dev;
	leds->handle.handler = handler;
	leds->handle.name = "leds";
	leds->handle.private = leds;

	error = input_register_handle(&leds->handle);
	if (error)
		goto err_free_mem;

	error = input_open_device(&leds->handle);
	if (error)
		goto err_unregister_handle;

	led_no = 0;
	for_each_set_bit(led_code, dev->ledbit, LED_CNT) {
		struct input_led *led = &leds->leds[led_no];

		led->handle = &leds->handle;
		led->code = led_code;

		if (!input_led_info[led_code].name)
			continue;

		led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s",
					   dev_name(&dev->dev),
					   input_led_info[led_code].name);
		if (!led->cdev.name) {
			error = -ENOMEM;
			goto err_unregister_leds;
		}

		led->cdev.max_brightness = 1;
		led->cdev.brightness_get = input_leds_brightness_get;
		led->cdev.brightness_set = input_leds_brightness_set;
		led->cdev.default_trigger = input_led_info[led_code].trigger;

		error = led_classdev_register(&dev->dev, &led->cdev);
		if (error) {
			dev_err(&dev->dev, "failed to register LED %s: %d\n",
				led->cdev.name, error);
			kfree(led->cdev.name);
			goto err_unregister_leds;
		}

		led_no++;
	}

	return 0;

err_unregister_leds:
	while (--led_no >= 0) {
		struct input_led *led = &leds->leds[led_no];

		led_classdev_unregister(&led->cdev);
		kfree(led->cdev.name);
	}

	input_close_device(&leds->handle);

err_unregister_handle:
	input_unregister_handle(&leds->handle);

err_free_mem:
	kfree(leds);
	return error;
}

static void input_leds_disconnect(struct input_handle *handle)
{
	struct input_leds *leds = handle->private;
	int i;

	for (i = 0; i < leds->num_leds; i++) {
		struct input_led *led = &leds->leds[i];

		led_classdev_unregister(&led->cdev);
		kfree(led->cdev.name);
	}

	input_close_device(handle);
	input_unregister_handle(handle);

	kfree(leds);
}

static const struct input_device_id input_leds_ids[] = {
	{
		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
		.evbit = { BIT_MASK(EV_LED) },
	},
	{ },
};
MODULE_DEVICE_TABLE(input, input_leds_ids);

static struct input_handler input_leds_handler = {
	.event =	input_leds_event,
	.connect =	input_leds_connect,
	.disconnect =	input_leds_disconnect,
	.name =		"leds",
	.id_table =	input_leds_ids,
};

static int __init input_leds_init(void)
{
	return input_register_handler(&input_leds_handler);
}
module_init(input_leds_init);

static void __exit input_leds_exit(void)
{
	input_unregister_handler(&input_leds_handler);
}
module_exit(input_leds_exit);

MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>");
MODULE_AUTHOR("Dmitry Torokhov <dmitry.torokhov@gmail.com>");
MODULE_DESCRIPTION("Input -> LEDs Bridge");
MODULE_LICENSE("GPL v2");
