/* ir-register.c - handle IR scancode->keycode tables
 *
 * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */


#include <linux/input.h>
#include <linux/slab.h>
#include <media/ir-common.h>

#define IR_TAB_MIN_SIZE	32
#define IR_TAB_MAX_SIZE	1024

/**
 * ir_seek_table() - returns the element order on the table
 * @rc_tab:	the ir_scancode_table with the keymap to be used
 * @scancode:	the scancode that we're seeking
 *
 * This routine is used by the input routines when a key is pressed at the
 * IR. The scancode is received and needs to be converted into a keycode.
 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
 * corresponding keycode from the table.
 */
static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode)
{
	int rc;
	unsigned long flags;
	struct ir_scancode *keymap = rc_tab->scan;

	spin_lock_irqsave(&rc_tab->lock, flags);

	/* FIXME: replace it by a binary search */

	for (rc = 0; rc < rc_tab->size; rc++)
		if (keymap[rc].scancode == scancode)
			goto exit;

	/* Not found */
	rc = -EINVAL;

exit:
	spin_unlock_irqrestore(&rc_tab->lock, flags);
	return rc;
}

/**
 * ir_roundup_tablesize() - gets an optimum value for the table size
 * @n_elems:		minimum number of entries to store keycodes
 *
 * This routine is used to choose the keycode table size.
 *
 * In order to have some empty space for new keycodes,
 * and knowing in advance that kmalloc allocates only power of two
 * segments, it optimizes the allocated space to have some spare space
 * for those new keycodes by using the maximum number of entries that
 * will be effectively be allocated by kmalloc.
 * In order to reduce the quantity of table resizes, it has a minimum
 * table size of IR_TAB_MIN_SIZE.
 */
static int ir_roundup_tablesize(int n_elems)
{
	size_t size;

	if (n_elems < IR_TAB_MIN_SIZE)
		n_elems = IR_TAB_MIN_SIZE;

	/*
	 * As kmalloc only allocates sizes of power of two, get as
	 * much entries as possible for the allocated memory segment
	 */
	size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode));
	n_elems = size / sizeof(struct ir_scancode);

	return n_elems;
}

/**
 * ir_copy_table() - copies a keytable, discarding the unused entries
 * @destin:	destin table
 * @origin:	origin table
 *
 * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED
 * Also copies table size and table protocol.
 * NOTE: It shouldn't copy the lock field
 */

static int ir_copy_table(struct ir_scancode_table *destin,
		 const struct ir_scancode_table *origin)
{
	int i, j = 0;

	for (i = 0; i < origin->size; i++) {
		if (origin->scan[i].keycode == KEY_UNKNOWN ||
		   origin->scan[i].keycode == KEY_RESERVED)
			continue;

		memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode));
		j++;
	}
	destin->size = j;
	destin->ir_type = origin->ir_type;

	IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);

	return 0;
}

/**
 * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
 * @dev:	the struct input_dev device descriptor
 * @scancode:	the desired scancode
 * @keycode:	the keycode to be retorned.
 *
 * This routine is used to handle evdev EVIOCGKEY ioctl.
 * If the key is not found, returns -EINVAL, otherwise, returns 0.
 */
static int ir_getkeycode(struct input_dev *dev,
			 unsigned int scancode, unsigned int *keycode)
{
	int elem;
	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;

	elem = ir_seek_table(rc_tab, scancode);
	if (elem >= 0) {
		*keycode = rc_tab->scan[elem].keycode;
		return 0;
	}

	/*
	 * Scancode not found and table can't be expanded
	 */
	if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE)
		return -EINVAL;

	/*
	 * If is there extra space, returns KEY_RESERVED,
	 * otherwise, input core won't let ir_setkeycode to work
	 */
	*keycode = KEY_RESERVED;
	return 0;
}

/**
 * ir_is_resize_needed() - Check if the table needs rezise
 * @table:		keycode table that may need to resize
 * @n_elems:		minimum number of entries to store keycodes
 *
 * Considering that kmalloc uses power of two storage areas, this
 * routine detects if the real alloced size will change. If not, it
 * just returns without doing nothing. Otherwise, it will extend or
 * reduce the table size to meet the new needs.
 *
 * It returns 0 if no resize is needed, 1 otherwise.
 */
static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems)
{
	int cur_size = ir_roundup_tablesize(table->size);
	int new_size = ir_roundup_tablesize(n_elems);

	if (cur_size == new_size)
		return 0;

	/* Resize is needed */
	return 1;
}

/**
 * ir_delete_key() - remove a keycode from the table
 * @rc_tab:		keycode table
 * @elem:		element to be removed
 *
 */
static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem)
{
	unsigned long flags = 0;
	int newsize = rc_tab->size - 1;
	int resize = ir_is_resize_needed(rc_tab, newsize);
	struct ir_scancode *oldkeymap = rc_tab->scan;
	struct ir_scancode *newkeymap = NULL;

	if (resize)
		newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
				    sizeof(*newkeymap), GFP_ATOMIC);

	/* There's no memory for resize. Keep the old table */
	if (!resize || !newkeymap) {
		newkeymap = oldkeymap;

		/* We'll modify the live table. Lock it */
		spin_lock_irqsave(&rc_tab->lock, flags);
	}

	/*
	 * Copy the elements before the one that will be deleted
	 * if (!resize), both oldkeymap and newkeymap points
	 * to the same place, so, there's no need to copy
	 */
	if (resize && elem > 0)
		memcpy(newkeymap, oldkeymap,
		       elem * sizeof(*newkeymap));

	/*
	 * Copy the other elements overwriting the element to be removed
	 * This operation applies to both resize and non-resize case
	 */
	if (elem < newsize)
		memcpy(&newkeymap[elem], &oldkeymap[elem + 1],
		       (newsize - elem) * sizeof(*newkeymap));

	if (resize) {
		/*
		 * As the copy happened to a temporary table, only here
		 * it needs to lock while replacing the table pointers
		 * to use the new table
		 */
		spin_lock_irqsave(&rc_tab->lock, flags);
		rc_tab->size = newsize;
		rc_tab->scan = newkeymap;
		spin_unlock_irqrestore(&rc_tab->lock, flags);

		/* Frees the old keytable */
		kfree(oldkeymap);
	} else {
		rc_tab->size = newsize;
		spin_unlock_irqrestore(&rc_tab->lock, flags);
	}
}

/**
 * ir_insert_key() - insert a keycode at the table
 * @rc_tab:		keycode table
 * @scancode:	the desired scancode
 * @keycode:	the keycode to be retorned.
 *
 */
static int ir_insert_key(struct ir_scancode_table *rc_tab,
			  int scancode, int keycode)
{
	unsigned long flags;
	int elem = rc_tab->size;
	int newsize = rc_tab->size + 1;
	int resize = ir_is_resize_needed(rc_tab, newsize);
	struct ir_scancode *oldkeymap = rc_tab->scan;
	struct ir_scancode *newkeymap;

	if (resize) {
		newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
				    sizeof(*newkeymap), GFP_ATOMIC);
		if (!newkeymap)
			return -ENOMEM;

		memcpy(newkeymap, oldkeymap,
		       rc_tab->size * sizeof(*newkeymap));
	} else
		newkeymap  = oldkeymap;

	/* Stores the new code at the table */
	IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
		   rc_tab->size, scancode, keycode);

	spin_lock_irqsave(&rc_tab->lock, flags);
	rc_tab->size = newsize;
	if (resize) {
		rc_tab->scan = newkeymap;
		kfree(oldkeymap);
	}
	newkeymap[elem].scancode = scancode;
	newkeymap[elem].keycode  = keycode;
	spin_unlock_irqrestore(&rc_tab->lock, flags);

	return 0;
}

/**
 * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table
 * @dev:	the struct input_dev device descriptor
 * @scancode:	the desired scancode
 * @keycode:	the keycode to be retorned.
 *
 * This routine is used to handle evdev EVIOCSKEY ioctl.
 * There's one caveat here: how can we increase the size of the table?
 * If the key is not found, returns -EINVAL, otherwise, returns 0.
 */
static int ir_setkeycode(struct input_dev *dev,
			 unsigned int scancode, unsigned int keycode)
{
	int rc = 0;
	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
	struct ir_scancode *keymap = rc_tab->scan;
	unsigned long flags;

	/*
	 * Handle keycode table deletions
	 *
	 * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED,
	 * deal as a trial to remove an existing scancode attribution
	 * if table become too big, reduce it to save space
	 */
	if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) {
		rc = ir_seek_table(rc_tab, scancode);
		if (rc < 0)
			return 0;

		IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode);
		clear_bit(keymap[rc].keycode, dev->keybit);
		ir_delete_key(rc_tab, rc);

		return 0;
	}

	/*
	 * Handle keycode replacements
	 *
	 * If the scancode exists, just replace by the new value
	 */
	rc = ir_seek_table(rc_tab, scancode);
	if (rc >= 0) {
		IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
			rc, scancode, keycode);

		clear_bit(keymap[rc].keycode, dev->keybit);

		spin_lock_irqsave(&rc_tab->lock, flags);
		keymap[rc].keycode = keycode;
		spin_unlock_irqrestore(&rc_tab->lock, flags);

		set_bit(keycode, dev->keybit);

		return 0;
	}

	/*
	 * Handle new scancode inserts
	 *
	 * reallocate table if needed and insert a new keycode
	 */

	/* Avoid growing the table indefinitely */
	if (rc_tab->size + 1 > IR_TAB_MAX_SIZE)
		return -EINVAL;

	rc = ir_insert_key(rc_tab, scancode, keycode);
	if (rc < 0)
		return rc;
	set_bit(keycode, dev->keybit);

	return 0;
}

/**
 * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
 * @input_dev:	the struct input_dev descriptor of the device
 * @scancode:	the scancode that we're seeking
 *
 * This routine is used by the input routines when a key is pressed at the
 * IR. The scancode is received and needs to be converted into a keycode.
 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
 * corresponding keycode from the table.
 */
u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
{
	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
	struct ir_scancode *keymap = rc_tab->scan;
	int elem;

	elem = ir_seek_table(rc_tab, scancode);
	if (elem >= 0) {
		IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
			   dev->name, scancode, keymap[elem].keycode);

		return rc_tab->scan[elem].keycode;
	}

	printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n",
	       dev->name, scancode);

	/* Reports userspace that an unknown keycode were got */
	return KEY_RESERVED;
}
EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);

/**
 * ir_input_register() - sets the IR keycode table and add the handlers
 *			    for keymap table get/set
 * @input_dev:	the struct input_dev descriptor of the device
 * @rc_tab:	the struct ir_scancode_table table of scancode/keymap
 *
 * This routine is used to initialize the input infrastructure
 * to work with an IR.
 * It will register the input/evdev interface for the device and
 * register the syfs code for IR class
 */
int ir_input_register(struct input_dev *input_dev,
		      const struct ir_scancode_table *rc_tab,
		      const struct ir_dev_props *props)
{
	struct ir_input_dev *ir_dev;
	struct ir_scancode  *keymap    = rc_tab->scan;
	int i, rc;

	if (rc_tab->scan == NULL || !rc_tab->size)
		return -EINVAL;

	ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL);
	if (!ir_dev)
		return -ENOMEM;

	spin_lock_init(&ir_dev->rc_tab.lock);

	ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size);
	ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size *
				    sizeof(struct ir_scancode), GFP_KERNEL);
	if (!ir_dev->rc_tab.scan) {
		kfree(ir_dev);
		return -ENOMEM;
	}

	IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
		ir_dev->rc_tab.size,
		ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan));

	ir_copy_table(&ir_dev->rc_tab, rc_tab);
	ir_dev->props = props;

	/* set the bits for the keys */
	IR_dprintk(1, "key map size: %d\n", rc_tab->size);
	for (i = 0; i < rc_tab->size; i++) {
		IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n",
			i, keymap[i].keycode);
		set_bit(keymap[i].keycode, input_dev->keybit);
	}
	clear_bit(0, input_dev->keybit);

	set_bit(EV_KEY, input_dev->evbit);

	input_dev->getkeycode = ir_getkeycode;
	input_dev->setkeycode = ir_setkeycode;
	input_set_drvdata(input_dev, ir_dev);

	rc = input_register_device(input_dev);
	if (rc < 0)
		goto err;

	rc = ir_register_class(input_dev);
	if (rc < 0) {
		input_unregister_device(input_dev);
		goto err;
	}

	return 0;

err:
	kfree(rc_tab->scan);
	kfree(ir_dev);
	input_set_drvdata(input_dev, NULL);
	return rc;
}
EXPORT_SYMBOL_GPL(ir_input_register);

/**
 * ir_input_unregister() - unregisters IR and frees resources
 * @input_dev:	the struct input_dev descriptor of the device

 * This routine is used to free memory and de-register interfaces.
 */
void ir_input_unregister(struct input_dev *dev)
{
	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
	struct ir_scancode_table *rc_tab;

	if (!ir_dev)
		return;

	IR_dprintk(1, "Freed keycode table\n");

	rc_tab = &ir_dev->rc_tab;
	rc_tab->size = 0;
	kfree(rc_tab->scan);
	rc_tab->scan = NULL;

	ir_unregister_class(dev);

	kfree(ir_dev);
	input_unregister_device(dev);
}
EXPORT_SYMBOL_GPL(ir_input_unregister);

int ir_core_debug;    /* ir_debug level (0,1,2) */
EXPORT_SYMBOL_GPL(ir_core_debug);
module_param_named(debug, ir_core_debug, int, 0644);

MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_LICENSE("GPL");
