/*
 * Manage Keyboard Matrices
 *
 * Copyright (c) 2012 The Chromium OS Authors.
 * (C) Copyright 2004 DENX Software Engineering, Wolfgang Denk, wd@denx.de
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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; either version 2 of
 * the License, or (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <fdtdec.h>
#include <key_matrix.h>
#include <malloc.h>
#include <linux/input.h>

/**
 * Determine if the current keypress configuration can cause key ghosting
 *
 * We figure this out by seeing if we have two or more keys in the same
 * column, as well as two or more keys in the same row.
 *
 * @param config	Keyboard matrix config
 * @param keys		List of keys to check
 * @param valid		Number of valid keypresses to check
 * @return 0 if no ghosting is possible, 1 if it is
 */
static int has_ghosting(struct key_matrix *config, struct key_matrix_key *keys,
			int valid)
{
	int key_in_same_col = 0, key_in_same_row = 0;
	int i, j;

	if (!config->ghost_filter || valid < 3)
		return 0;

	for (i = 0; i < valid; i++) {
		/*
		 * Find 2 keys such that one key is in the same row
		 * and the other is in the same column as the i-th key.
		 */
		for (j = i + 1; j < valid; j++) {
			if (keys[j].col == keys[i].col)
				key_in_same_col = 1;
			if (keys[j].row == keys[i].row)
				key_in_same_row = 1;
		}
	}

	if (key_in_same_col && key_in_same_row)
		return 1;
	else
		return 0;
}

int key_matrix_decode(struct key_matrix *config, struct key_matrix_key keys[],
		      int num_keys, int keycode[], int max_keycodes)
{
	const u8 *keymap;
	int valid, upto;
	int pos;

	debug("%s: num_keys = %d\n", __func__, num_keys);
	keymap = config->plain_keycode;
	for (valid = upto = 0; upto < num_keys; upto++) {
		struct key_matrix_key *key = &keys[upto];

		debug("  valid=%d, row=%d, col=%d\n", key->valid, key->row,
		      key->col);
		if (!key->valid)
			continue;
		pos = key->row * config->num_cols + key->col;
		if (config->fn_keycode && pos == config->fn_pos)
			keymap = config->fn_keycode;

		/* Convert the (row, col) values into a keycode */
		if (valid < max_keycodes)
			keycode[valid++] = keymap[pos];
		debug("    keycode=%d\n", keymap[pos]);
	}

	/* For a ghost key config, ignore the keypresses for this iteration. */
	if (has_ghosting(config, keys, valid)) {
		valid = 0;
		debug("    ghosting detected!\n");
	}
	debug("  %d valid keycodes found\n", valid);

	return valid;
}

/**
 * Create a new keycode map from some provided data
 *
 * This decodes a keycode map in the format used by the fdt, which is one
 * word per entry, with the row, col and keycode encoded in that word.
 *
 * We create a (row x col) size byte array with each entry containing the
 * keycode for that (row, col). We also search for map_keycode and return
 * its position if found (this is used for finding the Fn key).
 *
 * @param config        Key matrix dimensions structure
 * @param data          Keycode data
 * @param len           Number of entries in keycode table
 * @param map_keycode   Key code to find in the map
 * @param pos           Returns position of map_keycode, if found, else -1
 * @return map  Pointer to allocated map
 */
static uchar *create_keymap(struct key_matrix *config, u32 *data, int len,
			    int map_keycode, int *pos)
{
	uchar *map;

	if (pos)
		*pos = -1;
	map = (uchar *)calloc(1, config->key_count);
	if (!map) {
		debug("%s: failed to malloc %d bytes\n", __func__,
			config->key_count);
		return NULL;
	}

	for (; len >= sizeof(u32); data++, len -= 4) {
		u32 tmp = fdt32_to_cpu(*data);
		int key_code, row, col;
		int entry;

		row = (tmp >> 24) & 0xff;
		col = (tmp >> 16) & 0xff;
		key_code = tmp & 0xffff;
		entry = row * config->num_cols + col;
		map[entry] = key_code;
		debug("   map %d, %d: pos=%d, keycode=%d\n", row, col,
		      entry, key_code);
		if (pos && map_keycode == key_code)
			*pos = entry;
	}

	return map;
}

int key_matrix_decode_fdt(struct key_matrix *config, const void *blob,
			  int node)
{
	const struct fdt_property *prop;
	const char prefix[] = "linux,";
	int plen = sizeof(prefix) - 1;
	int offset;

	/* Check each property name for ones that we understand */
	for (offset = fdt_first_property_offset(blob, node);
		      offset > 0;
		      offset = fdt_next_property_offset(blob, offset)) {
		const char *name;
		int len;

		prop = fdt_get_property_by_offset(blob, offset, NULL);
		name = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
		len = strlen(name);

		/* Name needs to match "1,<type>keymap" */
		debug("%s: property '%s'\n", __func__, name);
		if (strncmp(name, prefix, plen) ||
				len < plen + 6 ||
				strcmp(name + len - 6, "keymap"))
			continue;

		len -= plen + 6;
		if (len == 0) {
			config->plain_keycode = create_keymap(config,
				(u32 *)prop->data, fdt32_to_cpu(prop->len),
				KEY_FN, &config->fn_pos);
		} else if (0 == strncmp(name + plen, "fn-", len)) {
			config->fn_keycode = create_keymap(config,
				(u32 *)prop->data, fdt32_to_cpu(prop->len),
				-1, NULL);
		} else {
			debug("%s: unrecognised property '%s'\n", __func__,
			      name);
		}
	}
	debug("%s: Decoded key maps %p, %p from fdt\n", __func__,
	      config->plain_keycode, config->fn_keycode);

	if (!config->plain_keycode) {
		debug("%s: cannot find keycode-plain map\n", __func__);
		return -1;
	}

	return 0;
}

int key_matrix_init(struct key_matrix *config, int rows, int cols,
		    int ghost_filter)
{
	memset(config, '\0', sizeof(*config));
	config->num_rows = rows;
	config->num_cols = cols;
	config->key_count = rows * cols;
	config->ghost_filter = ghost_filter;
	assert(config->key_count > 0);

	return 0;
}
