~mil/ppbbq10

f1460b04ace49f6aa0d3ef27006c0bacab0c5c0b — arturo182 5 years ago aac6567
Change the key mapping to a static array and add keymap

The keymap can be loaded using the `loadkeys` command.
2 files changed, 106 insertions(+), 238 deletions(-)

A bbq10kbd.map
M bbq10pmod.c
A bbq10kbd.map => bbq10kbd.map +32 -0
@@ 0,0 1,32 @@
    keycode 11 = asciitilde
alt keycode 11 = zero
alt keycode 16 = numbersign
alt keycode 17 = one
alt keycode 18 = two
alt keycode 19 = three
alt keycode 20 = parenleft
alt keycode 21 = parenright
alt keycode 22 = underscore
alt keycode 23 = minus
alt keycode 24 = plus
alt keycode 25 = at
alt keycode 28 = bar
alt keycode 30 = asterisk
alt keycode 31 = four
alt keycode 32 = five
alt keycode 33 = six
alt keycode 34 = slash
alt keycode 35 = colon
alt keycode 36 = semicolon
alt keycode 37 = apostrophe
alt keycode 38 = quotedbl
    keycode 41 = dollar
alt keycode 41 = grave
alt keycode 44 = seven
alt keycode 45 = eight
alt keycode 46 = nine
alt keycode 47 = question
alt keycode 48 = exclam
alt keycode 49 = comma
alt keycode 50 = period
alt keycode 57 = Tab

M bbq10pmod.c => bbq10pmod.c +74 -238
@@ 8,7 8,6 @@
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/input/sparse-keymap.h>

//#define DEBUG



@@ 48,227 47,62 @@
#define STATE_PRESS		1
#define STATE_IDLE		0

#define NUM_KEYCODES	256

static unsigned short keycodes[NUM_KEYCODES] = {
	[0x01] = KEY_UP,
	[0x02] = KEY_DOWN,
	[0x03] = KEY_LEFT,
	[0x04] = KEY_RIGHT,
	[0x05] = KEY_ENTER,
	[0x06] = KEY_MENU,
	[0x07] = KEY_BACK,

	[17] = KEY_LEFTALT,
	[18] = KEY_LEFTSHIFT,
	[19] = KEY_LEFTCTRL,

	['A'] = KEY_A,
	['B'] = KEY_B,
	['C'] = KEY_C,
	['D'] = KEY_D,
	['E'] = KEY_E,
	['F'] = KEY_F,
	['G'] = KEY_G,
	['H'] = KEY_H,
	['I'] = KEY_I,
	['J'] = KEY_J,
	['K'] = KEY_K,
	['L'] = KEY_L,
	['M'] = KEY_M,
	['N'] = KEY_N,
	['O'] = KEY_O,
	['P'] = KEY_P,
	['Q'] = KEY_Q,
	['R'] = KEY_R,
	['S'] = KEY_S,
	['T'] = KEY_T,
	['U'] = KEY_U,
	['W'] = KEY_W,
	['V'] = KEY_V,
	['X'] = KEY_X,
	['Y'] = KEY_Y,
	['Z'] = KEY_Z,

	[' '] = KEY_SPACE,
	['~'] = KEY_0,
	['$'] = KEY_GRAVE,

	['\b'] = KEY_BACKSPACE,
	['\n'] = KEY_ENTER,
};

struct bbq10pmod_data {
	unsigned short keycode[NUM_KEYCODES];
	struct i2c_client *client;
	struct input_dev *input;
};

static const struct key_entry bbq10pmod_keys[] = {
	{ KE_KEY, 0x01, { KEY_UP } },
	{ KE_KEY, 0x02, { KEY_DOWN } },
	{ KE_KEY, 0x03, { KEY_LEFT } },
	{ KE_KEY, 0x04, { KEY_RIGHT } },
	{ KE_KEY, 0x05, { KEY_ENTER } },
	{ KE_KEY, 0x06, { KEY_MENU } },
	{ KE_KEY, 0x07, { KEY_BACK } },

	{ KE_KEY, 17, { KEY_LEFTALT } },
	{ KE_KEY, 18, { KEY_LEFTSHIFT } },
	{ KE_KEY, 19, { KEY_LEFTCTRL } },

	{ KE_KEY, 'A', { KEY_A } },
	{ KE_KEY, 'B', { KEY_B } },
	{ KE_KEY, 'C', { KEY_C } },
	{ KE_KEY, 'D', { KEY_D } },
	{ KE_KEY, 'E', { KEY_E } },
	{ KE_KEY, 'F', { KEY_F } },
	{ KE_KEY, 'G', { KEY_G } },
	{ KE_KEY, 'H', { KEY_H } },
	{ KE_KEY, 'I', { KEY_I } },
	{ KE_KEY, 'J', { KEY_J } },
	{ KE_KEY, 'K', { KEY_K } },
	{ KE_KEY, 'L', { KEY_L } },
	{ KE_KEY, 'M', { KEY_M } },
	{ KE_KEY, 'N', { KEY_N } },
	{ KE_KEY, 'O', { KEY_O } },
	{ KE_KEY, 'P', { KEY_P } },
	{ KE_KEY, 'Q', { KEY_Q } },
	{ KE_KEY, 'R', { KEY_R } },
	{ KE_KEY, 'S', { KEY_S } },
	{ KE_KEY, 'T', { KEY_T } },
	{ KE_KEY, 'U', { KEY_U } },
	{ KE_KEY, 'W', { KEY_W } },
	{ KE_KEY, 'V', { KEY_V } },
	{ KE_KEY, 'X', { KEY_X } },
	{ KE_KEY, 'Y', { KEY_Y } },
	{ KE_KEY, 'Z', { KEY_Z } },
	{ KE_KEY, '\b', { KEY_BACKSPACE } },
	{ KE_KEY, ' ', { KEY_SPACE } },
	{ KE_KEY, '\n', { KEY_ENTER } },
	{ KE_KEY, '~', { KEY_GRAVE } },

	{ KE_KEY, 254, { KEY_NUMLOCK } },
	{ KE_KEY, 255, { KEY_CAPSLOCK } },
};

static unsigned int sparse_keymap_get_key_index(struct input_dev *dev,
						const struct key_entry *k)
{
	struct key_entry *key;
	unsigned int idx = 0;

	for (key = dev->keycode; key->type != KE_END; key++) {
		if (key->type == KE_KEY) {
			if (key == k)
				break;
			idx++;
		}
	}

	return idx;
}

static struct key_entry *sparse_keymap_entry_by_index(struct input_dev *dev,
						      unsigned int index)
{
	struct key_entry *key;
	unsigned int key_cnt = 0;

	for (key = dev->keycode; key->type != KE_END; key++)
		if (key->type == KE_KEY)
			if (key_cnt++ == index)
				return key;

	return NULL;
}

struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
						    unsigned int code)
{
	struct key_entry *key;

	for (key = dev->keycode; key->type != KE_END; key++)
		if (code == key->code)
			return key;

	return NULL;
}

struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
						   unsigned int keycode)
{
	struct key_entry *key;

	for (key = dev->keycode; key->type != KE_END; key++)
		if (key->type == KE_KEY && keycode == key->keycode)
			return key;

	return NULL;
}

static struct key_entry *sparse_keymap_locate(struct input_dev *dev,
					const struct input_keymap_entry *ke)
{
	struct key_entry *key;
	unsigned int scancode;

	if (ke->flags & INPUT_KEYMAP_BY_INDEX)
		key = sparse_keymap_entry_by_index(dev, ke->index);
	else if (input_scancode_to_scalar(ke, &scancode) == 0)
		key = sparse_keymap_entry_from_scancode(dev, scancode);
	else
		key = NULL;

	return key;
}

static int sparse_keymap_getkeycode(struct input_dev *dev,
				    struct input_keymap_entry *ke)
{
	const struct key_entry *key;

	if (dev->keycode) {
		key = sparse_keymap_locate(dev, ke);
		if (key && key->type == KE_KEY) {
			ke->keycode = key->keycode;
			if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
				ke->index =
					sparse_keymap_get_key_index(dev, key);
			ke->len = sizeof(key->code);
			memcpy(ke->scancode, &key->code, sizeof(key->code));
			return 0;
		}
	}

	return -EINVAL;
}

static int sparse_keymap_setkeycode(struct input_dev *dev,
				    const struct input_keymap_entry *ke,
				    unsigned int *old_keycode)
{
	struct key_entry *key;

	if (dev->keycode) {
		key = sparse_keymap_locate(dev, ke);
		if (key && key->type == KE_KEY) {
			*old_keycode = key->keycode;
			key->keycode = ke->keycode;
			set_bit(ke->keycode, dev->keybit);
			if (!sparse_keymap_entry_from_keycode(dev, *old_keycode))
				clear_bit(*old_keycode, dev->keybit);
			return 0;
		}
	}

	return -EINVAL;
}

int sparse_keymap_setup(struct input_dev *dev,
			const struct key_entry *keymap,
			int (*setup)(struct input_dev *, struct key_entry *))
{
	size_t map_size = 1; /* to account for the last KE_END entry */
	const struct key_entry *e;
	struct key_entry *map, *entry;
	int i;
	int error;

	for (e = keymap; e->type != KE_END; e++)
		map_size++;

	map = devm_kmemdup(&dev->dev, keymap, map_size * sizeof(*map),
			   GFP_KERNEL);
	if (!map)
		return -ENOMEM;

	for (i = 0; i < map_size; i++) {
		entry = &map[i];

		if (setup) {
			error = setup(dev, entry);
			if (error)
				return error;
		}

		switch (entry->type) {
		case KE_KEY:
			__set_bit(EV_KEY, dev->evbit);
			__set_bit(entry->keycode, dev->keybit);
			break;

		case KE_SW:
		case KE_VSW:
			__set_bit(EV_SW, dev->evbit);
			__set_bit(entry->sw.code, dev->swbit);
			break;
		}
	}

	if (test_bit(EV_KEY, dev->evbit)) {
		__set_bit(KEY_UNKNOWN, dev->keybit);
		__set_bit(EV_MSC, dev->evbit);
		__set_bit(MSC_SCAN, dev->mscbit);
	}

	dev->keycode = map;
	dev->keycodemax = map_size;
	dev->getkeycode = sparse_keymap_getkeycode;
	dev->setkeycode = sparse_keymap_setkeycode;

	return 0;
}

static int bbq10pmod_write_reg(struct bbq10pmod_data *drv_data, u8 reg)
{
	struct i2c_client *client = drv_data->client;


@@ 349,8 183,8 @@ static void bbq10pmod_update_locks(struct bbq10pmod_data *drv_data)

	pr_warn("%s status: 0x%02X\n", __func__, data);

	input_report_key(input, KEY_NUMLOCK, data & _KEY_NUMLOCK);
	input_report_key(input, KEY_CAPSLOCK, data & _KEY_CAPSLOCK);
	//input_report_key(input, KEY_NUMLOCK, data & _KEY_NUMLOCK);
	//input_report_key(input, KEY_CAPSLOCK, data & _KEY_CAPSLOCK);

	input_sync(input);
}


@@ 359,7 193,6 @@ static void bbq10pmod_read_fifo(struct bbq10pmod_data *drv_data)
{
	struct input_dev *input = drv_data->input;
	struct i2c_client *client = drv_data->client;
	const struct key_entry *ke;
	unsigned int keycode;
	u8 data[2];
	u8 count;


@@ 389,18 222,15 @@ static void bbq10pmod_read_fifo(struct bbq10pmod_data *drv_data)

		count -= 1;

		if (data[1] != 0 && data[1] != 0xFF && (data[0] == STATE_PRESS || data[0] == STATE_RELEASE)) {
			ke = sparse_keymap_entry_from_scancode(input, data[1]);
			keycode = ke ? ke->keycode : KEY_UNKNOWN;

			pr_debug("%s input data 0x%04x--> keycode %d\n",
				__func__, data[1], keycode);

			if (keycode == KEY_UNKNOWN)
				pr_warn("%s input data 0x%04x --> unknown\n",
					__func__, data[1]);
		if (data[0] == STATE_PRESS || data[0] == STATE_RELEASE) {
			input_event(input, EV_MSC, MSC_SCAN, data[1]);

			input_report_key(input, keycode, data[0] == STATE_PRESS);
			keycode = drv_data->keycode[data[1]];
			if (keycode == KEY_UNKNOWN) {
				pr_warn("%s code 0x%02X UNKNOWN\n", __func__, data[1]);
			} else {
				input_report_key(input, keycode, data[0] == STATE_PRESS);
			}
		}
	}



@@ 423,7 253,7 @@ static irqreturn_t bbq10pmod_irq_handler(int irq, void *dev_id)
		return IRQ_NONE;
	}

	pr_warn("int: 0x%02x\n", reg);
	pr_debug("int: 0x%02x\n", reg);

	if (reg == 0x00)
		return IRQ_NONE;


@@ 452,6 282,7 @@ static int bbq10pmod_probe(struct i2c_client *client, const struct i2c_device_id
	struct bbq10pmod_data *drv_data;
	struct input_dev *input;
	int error;
	int i;
	u8 reg;

	drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);


@@ 459,6 290,7 @@ static int bbq10pmod_probe(struct i2c_client *client, const struct i2c_device_id
		return -ENOMEM;

	drv_data->client = client;
	memcpy(drv_data->keycode, keycodes, sizeof(drv_data->keycode));

	error = bbq10pmod_write_reg(drv_data, REG_RST);
	if (error)


@@ 494,15 326,19 @@ static int bbq10pmod_probe(struct i2c_client *client, const struct i2c_device_id
	input->id.vendor  = 0x0001;
	input->id.product = 0x0001;
	input->id.version = 0x0001;
	input->keycode = drv_data->keycode;
	input->keycodesize = sizeof(drv_data->keycode[0]);
	input->keycodemax = ARRAY_SIZE(drv_data->keycode);

	//if (device_property_read_bool(dev, "keypad,autorepeat"))
	//	__set_bit(EV_REP, input->evbit);
	for (i = 0; i < NUM_KEYCODES; i++)
		__set_bit(drv_data->keycode[i], input->keybit);

	//input_set_capability(input, EV_MSC, MSC_SCAN);
	__clear_bit(KEY_RESERVED, input->keybit);

	error = sparse_keymap_setup(input, bbq10pmod_keys, NULL);
	if (error)
		return error;
	__set_bit(EV_REP, input->evbit);
	__set_bit(EV_KEY, input->evbit);

	input_set_capability(input, EV_MSC, MSC_SCAN);

	error = devm_request_threaded_irq(dev, client->irq,
										NULL, bbq10pmod_irq_handler,