All pastes #991193 Raw Edit

Someone

public text v1 · immutable
#991193 ·published 2008-04-20 20:10 UTC
rendered paste body
/* linux/arch/arm/mach-msm/board-kaiser-keypad.c
 *
 * Copyright (C) 2007 Google, Inc.
 * Author: Marcin Baliniak <marcin@baliniak.pl> 
 * based on Brian Swetland <swetland@google.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/input.h>

#include <asm/gpio.h>
#include <asm/hardware.h>

#include <asm/arch/board.h>
#include <asm/arch/msm_iomap.h>

#include <asm/io.h>
#include <asm/delay.h>

#include <linux/gpio_event.h>

static unsigned int kaiser_row_gpios[] = {23, 30, 31, 32, 33, 34, 35, 78};

static unsigned int kaiser_col_gpios[] = { 36, 37, 38, 39, 40, 41, 42 };

#define KEYMAP_INDEX(row, col) ((row)*ARRAY_SIZE(kaiser_col_gpios) + (col))

static unsigned short kaiser_keymap[ARRAY_SIZE(kaiser_col_gpios) * ARRAY_SIZE(kaiser_row_gpios)] = {
	[KEYMAP_INDEX(0, 0)] = KEY_MENU,// (keyboard menu)
	[KEYMAP_INDEX(0, 1)] = KEY_OK,// (keyboard ok)
	[KEYMAP_INDEX(0, 2)] = KEY_TAB,//
	[KEYMAP_INDEX(0, 3)] = KEY_V,//
	[KEYMAP_INDEX(0, 4)] = KEY_SPACE,//
	[KEYMAP_INDEX(0, 5)] = KEY_DOT,//
	[KEYMAP_INDEX(0, 6)] = KEY_ENTER, //

	[KEYMAP_INDEX(1, 0)] = KEY_1,
	[KEYMAP_INDEX(1, 1)] = KEY_2,
	[KEYMAP_INDEX(1, 2)] = KEY_3,
	[KEYMAP_INDEX(1, 3)] = KEY_MENU,//
	[KEYMAP_INDEX(1, 4)] = KEY_1,   // hangup
	[KEYMAP_INDEX(1, 5)] = KEY_OK,//
	[KEYMAP_INDEX(1, 6)] = KEY_2,// call
	
	[KEYMAP_INDEX(2, 0)] = KEY_LEFTALT,// Fn
	[KEYMAP_INDEX(2, 1)] = KEY_X,//
	[KEYMAP_INDEX(2, 2)] = KEY_C,//
	[KEYMAP_INDEX(2, 3)] = KEY_G,//
	[KEYMAP_INDEX(2, 4)] = KEY_B,//
	[KEYMAP_INDEX(2, 5)] = KEY_M,//
	[KEYMAP_INDEX(2, 6)] = KEY_BACKSPACE,//

	[KEYMAP_INDEX(3, 0)] = KEY_RIGHTSHIFT,//
	[KEYMAP_INDEX(3, 1)] = KEY_Z,//
	[KEYMAP_INDEX(3, 2)] = KEY_F,//
	[KEYMAP_INDEX(3, 3)] = KEY_Y,//
	[KEYMAP_INDEX(3, 4)] = KEY_H,//
	[KEYMAP_INDEX(3, 5)] = KEY_N,//
	[KEYMAP_INDEX(3, 6)] = KEY_L,//

	[KEYMAP_INDEX(4, 0)] = KEY_A,//
	[KEYMAP_INDEX(4, 1)] = KEY_S,//
	[KEYMAP_INDEX(4, 2)] = KEY_D,//
	[KEYMAP_INDEX(4, 3)] = KEY_T,//
	[KEYMAP_INDEX(4, 4)] = KEY_J,//
	[KEYMAP_INDEX(4, 5)] = KEY_K,//
	[KEYMAP_INDEX(4, 6)] = KEY_P,//

	[KEYMAP_INDEX(5, 0)] = KEY_Q,//
	[KEYMAP_INDEX(5, 1)] = KEY_W,//
	[KEYMAP_INDEX(5, 2)] = KEY_E,//
	[KEYMAP_INDEX(5, 3)] = KEY_R,//
	[KEYMAP_INDEX(5, 4)] = KEY_U,//
	[KEYMAP_INDEX(5, 5)] = KEY_I,//
	[KEYMAP_INDEX(5, 6)] = KEY_O, //
//dummy mapping for test only
	[KEYMAP_INDEX(6, 0)] = KEY_4,//
	[KEYMAP_INDEX(6, 1)] = KEY_5,//
	[KEYMAP_INDEX(6, 2)] = KEY_6,//
	[KEYMAP_INDEX(6, 3)] = KEY_7,//
	[KEYMAP_INDEX(6, 4)] = KEY_8,//
	[KEYMAP_INDEX(6, 5)] = KEY_9,//
	[KEYMAP_INDEX(6, 6)] = KEY_0,//
	
	[KEYMAP_INDEX(7, 0)] = KEY_4,//
	[KEYMAP_INDEX(7, 1)] = KEY_5,//
	[KEYMAP_INDEX(7, 2)] = KEY_6,//
	[KEYMAP_INDEX(7, 3)] = KEY_7,//
	[KEYMAP_INDEX(7, 4)] = KEY_8,//
	[KEYMAP_INDEX(7, 5)] = KEY_9,//
	[KEYMAP_INDEX(7, 6)] = KEY_0,//
				  
};

#define KEY_SHIFT 0x10000

static unsigned int kaiser_keymap_plus_fn[ARRAY_SIZE(kaiser_col_gpios) * ARRAY_SIZE(kaiser_row_gpios)] = {
	[KEYMAP_INDEX(0, 0)] = KEY_SEMICOLON,// ;
	[KEYMAP_INDEX(0, 1)] = KEY_WLAN,//
	[KEYMAP_INDEX(0, 2)] = KEY_TAB,//
	[KEYMAP_INDEX(0, 3)] = KEY_SHIFT | KEY_8,// *
	[KEYMAP_INDEX(0, 4)] = KEY_SPACE,
	[KEYMAP_INDEX(0, 5)] = KEY_0,//
	[KEYMAP_INDEX(0, 6)] = KEY_ENTER,

	[KEYMAP_INDEX(1, 0)] = KEY_1,
	[KEYMAP_INDEX(1, 1)] = KEY_2,
	[KEYMAP_INDEX(1, 2)] = KEY_3,
	[KEYMAP_INDEX(1, 3)] = KEY_MENU,//
	[KEYMAP_INDEX(1, 4)] = KEY_E,   // hangup
	[KEYMAP_INDEX(1, 5)] = KEY_OK,// 
	[KEYMAP_INDEX(1, 6)] = KEY_C,// call
	
	[KEYMAP_INDEX(2, 0)] = KEY_LEFTALT,// Fn
	[KEYMAP_INDEX(2, 1)] = KEY_SHIFT | KEY_7,// *
	[KEYMAP_INDEX(2, 2)] = KEY_SHIFT | KEY_SEMICOLON,// :
	[KEYMAP_INDEX(2, 3)] = KEY_SHIFT | KEY_EQUAL,// =
	[KEYMAP_INDEX(2, 4)] = KEY_7,//
	[KEYMAP_INDEX(2, 5)] = KEY_9,//
	[KEYMAP_INDEX(2, 6)] = KEY_DELETE,//

	[KEYMAP_INDEX(3, 0)] = KEY_CAPSLOCK,//
	[KEYMAP_INDEX(3, 1)] = KEY_APOSTROPHE,// '
	[KEYMAP_INDEX(3, 2)] = KEY_MINUS,// -
	[KEYMAP_INDEX(3, 3)] = KEY_1,//
	[KEYMAP_INDEX(3, 4)] = KEY_4,//
	[KEYMAP_INDEX(3, 5)] = KEY_8,//
	[KEYMAP_INDEX(3, 6)] = KEY_EQUAL,//

	[KEYMAP_INDEX(4, 0)] = KEY_SHIFT | KEY_MINUS,// _
	[KEYMAP_INDEX(4, 1)] = KEY_SHIFT | KEY_APOSTROPHE,// "
	[KEYMAP_INDEX(4, 2)] = KEY_SHIFT | KEY_5,// %
	[KEYMAP_INDEX(4, 3)] = KEY_SHIFT | KEY_3,// #
	[KEYMAP_INDEX(4, 4)] = KEY_5,//
	[KEYMAP_INDEX(4, 5)] = KEY_6,//
	[KEYMAP_INDEX(4, 6)] = KEY_SHIFT | KEY_0,// )

	[KEYMAP_INDEX(5, 0)] = KEY_SHIFT | KEY_2,// @
	[KEYMAP_INDEX(5, 1)] = KEY_SHIFT | KEY_1,// !
	[KEYMAP_INDEX(5, 2)] = KEY_SHIFT | KEY_BACKSLASH,// ?
	[KEYMAP_INDEX(5, 3)] = KEY_BACKSLASH,//
	[KEYMAP_INDEX(5, 4)] = KEY_2,//
	[KEYMAP_INDEX(5, 5)] = KEY_3,//
	[KEYMAP_INDEX(5, 6)] = KEY_SHIFT | KEY_9,// (
//dummy mapping for test only
	[KEYMAP_INDEX(6, 0)] = KEY_4,//
	[KEYMAP_INDEX(6, 1)] = KEY_5,//
	[KEYMAP_INDEX(6, 2)] = KEY_6,//
	[KEYMAP_INDEX(6, 3)] = KEY_7,//
	[KEYMAP_INDEX(6, 4)] = KEY_8,//
	[KEYMAP_INDEX(6, 5)] = KEY_9,//
	[KEYMAP_INDEX(6, 6)] = KEY_0,//
};

int Fn_pressed=0;
int Capslock_pressed=0;

void kaiser_key_event(struct input_dev *input_dev, int key_index, int pressed)
{
	unsigned short key;
	
	if (pressed == 0)
		return;
	
	//if we relese Fn key, keymapping need to be change
	if (key_index == KEYMAP_INDEX(2, 0))
	{
		Fn_pressed++;
		if (Fn_pressed > 2)
			Fn_pressed=0;
		Capslock_pressed =0;
		return;
	}
	
		//if we relese Fn key, keymapping need to be change
	if (key_index == KEYMAP_INDEX(3, 0))
	{
		Capslock_pressed++;
		if (Capslock_pressed > 2)
			Capslock_pressed=0;
		Fn_pressed = 0;
		return;
	}
	
	if (Fn_pressed)
	{
		if (Fn_pressed == 1)
			Fn_pressed=0;
		key = (kaiser_keymap_plus_fn[key_index] & 0xffff);
		
		if (kaiser_keymap_plus_fn[key_index] & KEY_SHIFT)
			input_report_key(input_dev, KEY_RIGHTSHIFT, 1);
		
		printk("\nSHIFT:0x%X, %d\n",kaiser_keymap_plus_fn[key_index],key_index);
		input_report_key(input_dev, key, 1);
		input_report_key(input_dev, key, 0);
		
		if (kaiser_keymap_plus_fn[key_index] & KEY_SHIFT)
			input_report_key(input_dev, KEY_RIGHTSHIFT, 0);
		
		input_sync(input_dev);
		return;	
	}
	
	if (Capslock_pressed)
	{
		if (Capslock_pressed == 1)
			Capslock_pressed=0;

		input_report_key(input_dev, KEY_RIGHTSHIFT, 1);
		
		input_report_key(input_dev, kaiser_keymap[key_index], 1);
		input_report_key(input_dev, kaiser_keymap[key_index], 0);
		
		input_report_key(input_dev, KEY_RIGHTSHIFT, 0);
		
		input_sync(input_dev);
		return;	
	}	
	
	
	input_report_key(input_dev,kaiser_keymap[key_index],1);
	input_report_key(input_dev,kaiser_keymap[key_index],0);
	input_sync(input_dev);

}

static struct gpio_event_matrix_info kaiser_matrix_info = {
	.info.func	= gpio_event_matrix_func,
 	.info.report_key_event = kaiser_key_event,
	.keymap		= kaiser_keymap,
	.output_gpios	= kaiser_row_gpios,
	.input_gpios	= kaiser_col_gpios,
	.noutputs	= ARRAY_SIZE(kaiser_row_gpios),
	.ninputs	= ARRAY_SIZE(kaiser_col_gpios),
	.settle_time.tv.nsec = 0,
	.poll_time.tv.nsec = 20 * NSEC_PER_MSEC,
	.flags		= GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE | GPIOKPF_PRINT_UNMAPPED_KEYS
};

struct gpio_event_info *kaiser_keypad_info[] = {
	&kaiser_matrix_info.info
};

static struct gpio_event_platform_data kaiser_keypad_data = {
	.name		= "kaiser_keypad",
	.info		= kaiser_keypad_info,
	.info_count	= ARRAY_SIZE(kaiser_keypad_info)
};

static struct platform_device kaiser_keypad_device = {
	.name	= GPIO_EVENT_DEV_NAME,
	.id	= -1,
	.dev	= {
		.platform_data	= &kaiser_keypad_data,
	},
};

void kaiser_init_keypad(void)
{
	platform_device_register(&kaiser_keypad_device);
}