在android系统PS2全键盘驱动(上)-使用linux的标准接口实现 中介绍了使用linux的标准接口实现PS2键盘驱动,由于我的PS2键盘是特殊定制的,有部分按键并不是按照第二套键盘扫描码来的,虽然使用linux提供的PS2驱动可以使用大部分的按键,但有部分按键无法使用。所以要使用linuxPS2键盘驱动的话有两种方式,一种是修改linux PS2驱动对扫描码处理部分的代码,一种是自己写PS2键盘的驱动。这里我选择第二种。实现过程如下:
a./home/ubuntu/G923/linux/drivers/input/keyboard/目录下添加imapx200_ps2_keyboard.c,imapx200_ps2_keyboard.h文件。
b./home/ubuntu/G923/linux/drivers/input/keyboard/Makefile文件中添加
obj-$(CONFIG_KEYBOARD_PS2KEYBOARD) += imapx200_ps2_keyboard.o
c./home/ubuntu/G923/linux/arch/arm/mach-imapx200/configs/keyboard_config文件添加
# ps2 keyboard
config KEYBOARD_PS2KEYBOARD
bool "ps2 keyboard"
config PS2KEYBOARD_LED_CAPSLOCK
string "ps2 keyboard capslock led control"
depends on KEYBOARD_PS2KEYBOARD
config PS2KEYBOARD_LED_NUMLOCK
string "ps2 keyboard numlock led control"
depends on KEYBOARD_PS2KEYBOARD
config PS2KEYBOARD_HALLONE
string "hall one gpio"
depends on KEYBOARD_PS2KEYBOARD
config PS2KEYBOARD_HALLTWO
string "hall two gpio"
depends on KEYBOARD_PS2KEYBOARD
d./home/ubuntu/G923/linux/arch/arm/mach-imapx200/cpu.c文件修改
//&imapx200_device_pic0,
&ps2keyboard_device,
//amba_device_register(&imap_ps2_device, &(imap_ps2_device.res));
/home/ubuntu/G923/linux/arch/arm/plat-imap/include/plat/devs.h文件添加
extern struct platform_device ps2keyboard_device;
e./home/ubuntu/G923/linux/arch/arm/mach-imapx200/devices.c文件添加
/************PS2 keyboard***************/
static struct resource ps2keyboard_resource[]={
[0] = {
.start = PIC0_BASE_REG_PA,
.end = PIC0_BASE_REG_PA + 0xfff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_PS2_0,
.end = IRQ_PS2_0,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device ps2keyboard_device = {
.name = "ps2keyboard",
.id = -1,
.num_resources = ARRAY_SIZE(ps2keyboard_resource),
.resource = ps2keyboard_resource,
};
EXPORT_SYMBOL(ps2keyboard_device);
f./home/ubuntu/G923/linux/drivers/soops/soops.c文件添加(这部分主要用来实现shift按键以及capslock功能,这部分功能还需要修改android文件系统)
#if defined(CONFIG_KEYBOARD_PS2KEYBOARD)
extern int ps2keyboard_get_caps_locking_status(void);
extern int ps2keyboard_get_key_shift_locking_status(void);
extern int ps2keyboard_get_key_alt_locking_status(void);
#endif
g.make menuconfig添加相关选项编译内核即可
附上驱动源码
imapx200_ps2_keyboard.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <plat/imapx.h>
#include <linux/delay.h>
#include <linux/amba/bus.h>
#include <linux/amba/kmi.h>
#include <linux/input.h>
#include <mach/irqs.h>
#include <mach/imapx_intr.h>
#include <mach/imapx_sysmgr.h>
#include "imapx200_ps2_keyboard.h"
#define KMI_BASE (ps2keyboard_dev0->base_reg)
//static int shift_pressing = 0;
//static int leftshift_pressing = 0;
//static int rightshift_pressing = 0;
//static int leftalt_pressing = 0;
//static int rightalt_pressing = 0;
static int shift_key_locking = 0;
static spinlock_t *shift_key_spinlock = NULL;
static int alt_key_locking = 0;
static spinlock_t *alt_key_spinlock = NULL;
static int caps_locking = 0;
static spinlock_t *caps_spinlock = NULL;
static int flags_numlock = 0;
static void ps2keyboard_tasklet_fuc(unsigned long);
static DECLARE_TASKLET_DISABLED(ps2keyboard_tasklet, ps2keyboard_tasklet_fuc, 0);
static DECLARE_TASKLET_DISABLED(hallone_tasklet, hallone_tasklet_fuc, 0);
//global ps2 keyborad scancode
static const struct ps2keyborad_scancode ps2keyborad_scancodes[]={
{MAKE_STATE,KEY_ESC,1,0x76,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_ESC,2,0xf0,0x76,0,0,0,0,0,0},
{MAKE_STATE,KEY_F1,1,0x05,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F1,2,0xf0,0x05,0,0,0,0,0,0},
{MAKE_STATE,KEY_F2,1,0x06,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F2,2,0xf0,0x06,0,0,0,0,0,0},
{MAKE_STATE,KEY_F3,1,0x04,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F3,2,0xf0,0x04,0,0,0,0,0,0},
{MAKE_STATE,KEY_F4,1,0x0c,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F4,2,0xf0,0x0c,0,0,0,0,0,0},
{MAKE_STATE,KEY_F5,1,0x03,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F5,2,0xf0,0x03,0,0,0,0,0,0},
{MAKE_STATE,KEY_F6,1,0x0b,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F6,2,0xf0,0x0b,0,0,0,0,0,0},
{MAKE_STATE,KEY_F7,1,0x83,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F7,2,0xf0,0x83,0,0,0,0,0,0},
{MAKE_STATE,KEY_F8,1,0x0a,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F8,2,0xf0,0x0a,0,0,0,0,0,0},
{MAKE_STATE,KEY_VOLUMEDOWN,1,0x1,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_VOLUMEDOWN,2,0xf0,0x1,0,0,0,0,0,0},
{MAKE_STATE,KEY_VOLUMEUP,1,0x9,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_VOLUMEUP,2,0xf0,0x9,0,0,0,0,0,0},
{MAKE_STATE,KEY_NUMLOCK,1,0x77,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_NUMLOCK,2,0xf0,0x77,0,0,0,0,0,0},
{MAKE_STATE,KEY_PRINT,4,0xe0,0x12,0xe0,0x7c,0,0,0,0}, //BASE
{BREAK_STATE,KEY_PRINT,6,0xe0,0xf0,0x7c,0xe0,0xf0,0x12,0,0},
{MAKE_STATE,KEY_PRINT,2,0xe0,0x7C,0,0,0,0,0,0}, //SHIFT/CTRL
{BREAK_STATE,KEY_PRINT,3,0xe0,0xf0,0x7c,0,0,0,0,0},
{MAKE_STATE,KEY_PRINT,1,0x84,0,0,0,0,0,0,0}, //ALT
{BREAK_STATE,KEY_PRINT,2,0xf0,0x84,0,0,0,0,0,0},
{MAKE_STATE,KEY_INSERT,2,0xe0,0x2c,0,0,0,0,0,0},
{BREAK_STATE,KEY_INSERT,3,0xe0,0xf0,0x2c,0,0,0,0,0},
{MAKE_STATE,KEY_DELETE,2,0xe0,0x71,0,0,0,0,0,0},//Base Case Shift+Num
{BREAK_STATE,KEY_DELETE,3,0xe0,0xf0,0x71,0,0,0,0,0},
{MAKE_STATE,KEY_DELETE,5,0xe0,0xf0,0x12,0xe0,0x71,0,0,0},//Left-Shift
{BREAK_STATE,KEY_DELETE,5,0xe0,0xf0,0x71,0xe0,0x12,0,0,0},
{MAKE_STATE,KEY_DELETE,5,0xe0,0xf0,0x59,0xe0,0x71,0,0,0}, //Right-Shift
{BREAK_STATE,KEY_DELETE,5,0xe0,0xf0,0x71,0xe0,0x59,0,0,0},
{MAKE_STATE,KEY_DELETE,4,0xe0,0x12,0xe0,0x71,0,0,0,0}, //Num Lock
{BREAK_STATE,KEY_DELETE,6,0xe0,0xf0,0x71,0xe0,0xf0,0x12,0,0},
{MAKE_STATE,KEY_GRAVE,1,0x0e,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_GRAVE,2,0xf0,0x0e,0,0,0,0,0,0},
{MAKE_STATE,KEY_1,1,0x16,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_1,2,0xf0,0x16,0,0,0,0,0,0},
{MAKE_STATE,KEY_2,1,0x1e,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_2,2,0xf0,0x1e,0,0,0,0,0,0},
{MAKE_STATE,KEY_3,1,0x26,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_3,2,0xf0,0x26,0,0,0,0,0,0},
{MAKE_STATE,KEY_4,1,0x25,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_4,2,0xf0,0x25,0,0,0,0,0,0},
{MAKE_STATE,KEY_5,1,0x2e,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_5,2,0xf0,0x2e,0,0,0,0,0,0},
{MAKE_STATE,KEY_6,1,0x36,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_6,2,0xf0,0x36,0,0,0,0,0,0},
{MAKE_STATE,KEY_KP7,1,0x6c,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_KP7,2,0xf0,0x6c,0,0,0,0,0,0},
{MAKE_STATE,KEY_7,1,0x3d,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_7,2,0xf0,0x3d,0,0,0,0,0,0},
{MAKE_STATE,KEY_KP8,1,0x75,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_KP8,2,0xf0,0x75,0,0,0,0,0,0},
{MAKE_STATE,KEY_8,1,0x3e,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_8,2,0xf0,0x3e,0,0,0,0,0,0},
{MAKE_STATE,KEY_KP9,1,0x7d,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_KP9,2,0xf0,0x7d,0,0,0,0,0,0},
{MAKE_STATE,KEY_9,1,0x46,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_9,2,0xf0,0x46,0,0,0,0,0,0},
{MAKE_STATE,KEY_0,1,0x7c,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_0,2,0xf0,0x7c,0,0,0,0,0,0},
{MAKE_STATE,KEY_0,1,0x45,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_0,2,0xf0,0x45,0,0,0,0,0,0},
{MAKE_STATE,KEY_MINUS,1,0x4e,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_MINUS,2,0xf0,0x4e,0,0,0,0,0,0},
{MAKE_STATE,KEY_BACKSPACE,1,0x66,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_BACKSPACE,2,0xf0,0x66,0,0,0,0,0,0},
{MAKE_STATE,KEY_TAB,1,0x0d,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_TAB,2,0xf0,0x0d,0,0,0,0,0,0},
{MAKE_STATE,KEY_Q,1,0x15,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_Q,2,0xf0,0x15,0,0,0,0,0,0},
{MAKE_STATE,KEY_W,1,0x1d,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_W,2,0xf0,0x1d,0,0,0,0,0,0},
{MAKE_STATE,KEY_E,1,0x24,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_E,2,0xf0,0x24,0,0,0,0,0,0},
{MAKE_STATE,KEY_R,1,0x2d,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_R,2,0xf0,0x2d,0,0,0,0,0,0},
{MAKE_STATE,KEY_T,1,0x2c,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_T,2,0xf0,0x2c,0,0,0,0,0,0},
{MAKE_STATE,KEY_Y,1,0x35,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_Y,2,0xf0,0x35,0,0,0,0,0,0},
{MAKE_STATE,KEY_U,1,0x3c,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_U,2,0xf0,0x3c,0,0,0,0,0,0},
{MAKE_STATE,KEY_I,1,0x43,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_I,2,0xf0,0x43,0,0,0,0,0,0},
{MAKE_STATE,KEY_O,1,0x44,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_O,2,0xf0,0x44,0,0,0,0,0,0},
{MAKE_STATE,KEY_P,1,0x4d,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_P,2,0xf0,0x4d,0,0,0,0,0,0},
{MAKE_STATE,KEY_EQUAL,1,0x55,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_EQUAL,2,0xf0,0x55,0,0,0,0,0,0},
{MAKE_STATE,KEY_BACKSPACE,1,0x5d,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_BACKSPACE,2,0xf0,0x5d,0,0,0,0,0,0},
{MAKE_STATE,KEY_CAPSLOCK,1,0x58,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_CAPSLOCK,2,0xf0,0x58,0,0,0,0,0,0},
{MAKE_STATE,KEY_A,1,0x1c,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_A,2,0xf0,0x1c,0,0,0,0,0,0},
{MAKE_STATE,KEY_S,1,0x1b,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_S,2,0xf0,0x1b,0,0,0,0,0,0},
{MAKE_STATE,KEY_D,1,0x23,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_D,2,0xf0,0x23,0,0,0,0,0,0},
{MAKE_STATE,KEY_F,1,0x2b,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_F,2,0xf0,0x2b,0,0,0,0,0,0},
{MAKE_STATE,KEY_G,1,0x34,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_G,2,0xf0,0x34,0,0,0,0,0,0},
{MAKE_STATE,KEY_H,1,0x33,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_H,2,0xf0,0x33,0,0,0,0,0,0},
{MAKE_STATE,KEY_J,1,0x3b,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_J,2,0xf0,0x3b,0,0,0,0,0,0},
{MAKE_STATE,KEY_K,1,0x42,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_K,2,0xf0,0x42,0,0,0,0,0,0},
{MAKE_STATE,KEY_L,1,0x4b,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_L,2,0xf0,0x4b,0,0,0,0,0,0},
{MAKE_STATE,KEY_SEMICOLON,1,0x4c,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_SEMICOLON,2,0xf0,0x4c,0,0,0,0,0,0},
{MAKE_STATE,KEY_ENTER,1,0x5a,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_ENTER,2,0xf0,0x5a,0,0,0,0,0,0},
{MAKE_STATE,KEY_ENTER,2,0xe0,0x5a,0,0,0,0,0,0},
{BREAK_STATE,KEY_ENTER,3,0xe0,0xf0,0x5a,0,0,0,0,0},
{MAKE_STATE,KEY_LEFTSHIFT,1,0x12,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_LEFTSHIFT,2,0xf0,0x12,0,0,0,0,0,0},
{MAKE_STATE,KEY_BACKSPACE,1,0x61,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_BACKSPACE,2,0xf0,0x61,0,0,0,0,0,0},
{MAKE_STATE,KEY_Z,1,0x1a,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_Z,2,0xf0,0x1a,0,0,0,0,0,0},
{MAKE_STATE,KEY_X,1,0x22,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_X,2,0xf0,0x22,0,0,0,0,0,0},
{MAKE_STATE,KEY_C,1,0x21,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_C,2,0xf0,0x21,0,0,0,0,0,0},
{MAKE_STATE,KEY_V,1,0x2a,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_V,2,0xf0,0x2a,0,0,0,0,0,0},
{MAKE_STATE,KEY_B,1,0x32,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_B,2,0xf0,0x32,0,0,0,0,0,0},
{MAKE_STATE,KEY_N,1,0x31,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_N,2,0xf0,0x31,0,0,0,0,0,0},
{MAKE_STATE,KEY_M,1,0x3a,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_M,2,0xf0,0x3a,0,0,0,0,0,0},
{MAKE_STATE,KEY_COMMA,1,0x41,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_COMMA,2,0xf0,0x41,0,0,0,0,0,0},
{MAKE_STATE,KEY_DOT,1,0x49,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_DOT,2,0xf0,0x49,0,0,0,0,0,0},
{MAKE_STATE,KEY_SLASH,2,0xe0,0x4a,0,0,0,0,0,0},//BASE
{BREAK_STATE,KEY_SLASH,3,0xe0,0xf0,0x4a,0,0,0,0,0},
{MAKE_STATE,KEY_SLASH,5,0xe0,0xf0,0x12,0xe0,0x4a,0,0,0},//Left-Shift
{BREAK_STATE,KEY_SLASH,5,0xe0,0xf0,0x4a,0xe0,0x12,0,0,0},
{MAKE_STATE,KEY_SLASH,5,0xe0,0xf0,0x59,0xe0,0x4a,0,0,0},//Right-Shift
{BREAK_STATE,KEY_SLASH,5,0xe0,0xf0,0x4a,0xe0,0x59,0,0,0},
{MAKE_STATE,KEY_UP,2,0xe0,0x75,0,0,0,0,0,0},
{BREAK_STATE,KEY_UP,3,0xe0,0xf0,0x75,0,0,0,0,0},
{MAKE_STATE,KEY_UP,5,0xe0,0xf0,0x12,0xe0,0x75,0,0,0},
{BREAK_STATE,KEY_UP,5,0xe0,0xf0,0x75,0xe0,0x12,0,0,0},
{MAKE_STATE,KEY_UP,5,0xe0,0xf0,0x59,0xe0,0x75,0,0,0},
{BREAK_STATE,KEY_UP,5,0xe0,0xf0,0x75,0xe0,0x59,0,0,0},
{MAKE_STATE,KEY_UP,4,0xe0,0x12,0xe0,0x75,0,0,0,0},
{BREAK_STATE,KEY_UP,6,0xe0,0xf0,0x75,0xe0,0xf0,0x12,0,0},
{MAKE_STATE,KEY_RIGHTSHIFT,1,0x59,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_RIGHTSHIFT,2,0xf0,0x59,0,0,0,0,0,0},
{MAKE_STATE,KEY_LEFTCTRL,1,0x14,0,0,0,0,0,0,0},
{BREAK_STATE,KEY_LEFTCTRL,2,0xf0,0x14,0,0,0,0,0,0},
{MAKE_STATE,KEY_F9,2,0xe0,0x1f,0,0,0,0,0,0}, //mp4
{BREAK_STATE,KEY_F9,3,0xe0,0xf0,0x1f,0,0,0,0,0},
{MAKE_STATE,KEY_LEFTALT,1,0x11,0,0,0,0,0,0,0},//alt
{BREAK_STATE,KEY_LEFTALT,2,0xf0,0x11,0,0,0,0,0,0},
{MAKE_STATE,KEY_F10,8,0xe1,0x14,0x77,0xe1,0xf0,0x14,0xf0,0x77}, //mp3
{BREAK_STATE,KEY_F10,8,0xe1,0x14,0x77,0xe1,0xf0,0x14,0xf0,0x77},
{MAKE_STATE,KEY_SPACE,1,0x29,0,0,0,0,0,0,0},//space
{BREAK_STATE,KEY_SPACE,2,0xf0,0x29,0,0,0,0,0,0},
{MAKE_STATE,KEY_F11,2,0xe0,0x2f,0,0,0,0,0,0},//输入法
{BREAK_STATE,KEY_F11,3,0xe0,0xf0,0x2f,0,0,0,0,0},
{MAKE_STATE,KEY_LEFTBRACE,1,0x54,0,0,0,0,0,0,0},//{
{BREAK_STATE,KEY_LEFTBRACE,2,0xf0,0x54,0,0,0,0,0,0},
{MAKE_STATE,KEY_RIGHTBRACE,1,0x5b,0,0,0,0,0,0,0},//}
{BREAK_STATE,KEY_RIGHTBRACE,2,0xf0,0x5b,0,0,0,0,0,0},
{MAKE_STATE,KEY_APOSTROPHE,1,0x52,0,0,0,0,0,0,0},//,
{BREAK_STATE,KEY_APOSTROPHE,2,0xf0,0x52,0,0,0,0,0,0},
{MAKE_STATE,KEY_LEFT,2,0xe0,0x6b,0,0,0,0,0,0},
{BREAK_STATE,KEY_LEFT,3,0xe0,0xf0,0x6b,0,0,0,0,0},
{MAKE_STATE,KEY_LEFT,5,0xe0,0xf0,0x12,0xe0,0x6b,0,0,0},
{BREAK_STATE,KEY_LEFT,5,0xe0,0xf0,0x6b,0xe0,0x12,0,0,0},
{MAKE_STATE,KEY_LEFT,5,0xe0,0xf0,0x59,0xe0,0x6b,0,0,0},
{BREAK_STATE,KEY_LEFT,5,0xe0,0xf0,0x6b,0xe0,0x59,0,0,0},
{MAKE_STATE,KEY_LEFT,4,0xe0,0x12,0xe0,0x6b,0,0,0,0},
{BREAK_STATE,KEY_LEFT,6,0xe0,0xf0,0x6b,0xe0,0xf0,0x12,0,0},
{MAKE_STATE,KEY_DOWN,2,0xe0,0x72,0,0,0,0,0,0},
{BREAK_STATE,KEY_DOWN,3,0xe0,0xf0,0x72,0,0,0,0,0},
{MAKE_STATE,KEY_DOWN,5,0xe0,0xf0,0x12,0xe0,0x72,0,0,0},
{BREAK_STATE,KEY_DOWN,5,0xe0,0xf0,0x72,0xe0,0x12,0,0,0},
{MAKE_STATE,KEY_DOWN,5,0xe0,0xf0,0x59,0xe0,0x72,0,0,0},
{BREAK_STATE,KEY_DOWN,5,0xe0,0xf0,0x72,0xe0,0x59,0,0,0},
{MAKE_STATE,KEY_DOWN,4,0xe0,0x12,0xe0,0x72,0,0,0,0},
{BREAK_STATE,KEY_DOWN,6,0xe0,0xf0,0x72,0xe0,0xf0,0x12,0,0},
{MAKE_STATE,KEY_RIGHT,2,0xe0,0x74,0,0,0,0,0,0},
{BREAK_STATE,KEY_RIGHT,3,0xe0,0xf0,0x74,0,0,0,0,0},
{MAKE_STATE,KEY_RIGHT,5,0xe0,0xf0,0x12,0xe0,0x74,0,0,0},
{BREAK_STATE,KEY_RIGHT,5,0xe0,0xf0,0x74,0xe0,0x12,0,0,0},
{MAKE_STATE,KEY_RIGHT,5,0xe0,0xf0,0x59,0xe0,0x74,0,0,0},
{BREAK_STATE,KEY_RIGHT,5,0xe0,0xf0,0x74,0xe0,0x59,0,0,0},
{MAKE_STATE,KEY_RIGHT,4,0xe0,0x12,0xe0,0x74,0,0,0,0},
{BREAK_STATE,KEY_RIGHT,6,0xe0,0xf0,0x74,0xe0,0xf0,0x12,0,0},
};
//struct ps2keyboard_dev ps2keyboard_dev0={
// .ps2kbdscancodelist=&ps2keyborad_scancodes[0];
// .ps2kbdcancodenum=ARRAY_SIZE(ps2keyborad_scancodes);
//}
/*
static int ps2keyboard_open(struct inode* inode, struct file* filp);
static int ps2keyboard_release(struct inode* inode, struct file* filp);
static int ps2keyboard_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg);
static ssize_t ps2keyboard_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);
static ssize_t ps2keyboard_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);
static struct file_operations ps2keyboard_fops = {
.owner = THIS_MODULE,
.open = ps2keyboard_open,
.release = ps2keyboard_release,
.read = ps2keyboard_read,
.write = ps2keyboard_write,
.ioctl = ps2keyboard_ioctl,
};
static int ps2keyboard_open(struct inode* inode, struct file* filp) {
struct ps2keyboard_dev * dev;
dev = container_of(inode->i_cdev, struct ps2keyboard_dev, input);
filp->private_data = dev;
return 0;
}
static int ps2keyboard_release(struct inode* inode, struct file* filp) {
struct ps2keyboard_dev* dev = filp->private_data;
return 0;
}
static ssize_t ps2keyboard_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {
ssize_t err = 0;
struct ps2keyboard_dev* dev = filp->private_data;
return err;
}
static ssize_t ps2keyboard_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {
struct ps2keyboard_dev* dev = filp->private_data;
ssize_t err = 0;
return err;
}
static int ps2keyboard_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ps2keyboard_dev* dev = filp->private_data;
return ioctlreturn;
}
*/
int ps2keyboard_get_caps_locking_status(void)
{
int status = 0;
spin_lock(caps_spinlock);
status = caps_locking;
printk("keyinput_get_caps_locking_status is %d\n",caps_locking);
spin_unlock(caps_spinlock);
return status;
}
EXPORT_SYMBOL(ps2keyboard_get_caps_locking_status);
int ps2keyboard_get_key_shift_locking_status(void)
{
int status = 0;
spin_lock(shift_key_spinlock);
status = shift_key_locking;
spin_unlock(shift_key_spinlock);
return status;
}
EXPORT_SYMBOL(ps2keyboard_get_key_shift_locking_status);
int ps2keyboard_get_key_alt_locking_status(void)
{
int status = 0;
spin_lock(alt_key_spinlock);
status = alt_key_locking;
spin_unlock(alt_key_spinlock);
return status;
}
EXPORT_SYMBOL(ps2keyboard_get_key_alt_locking_status);
//ps2 keyboard interrupt thread
static irqreturn_t ps2keyboard_isr(int irq, void *dev_id)
{
struct ps2keyboard_dev *ps2keyboard_dev0 = dev_id;
unsigned int status = readb(KMIIR);
int handled = IRQ_NONE;
unsigned char readdata;
ps2keyboard_dev0->pscancode=kmalloc(sizeof(struct scancode),GFP_KERNEL);
if(ps2keyboard_dev0->pscancode==NULL)
{
printk("ps2keyboard_isr error kmalloc\n");
handled = IRQ_HANDLED;
goto _return_;
}
printk("---------\n");
memset(ps2keyboard_dev0->pscancode,0,sizeof(struct scancode));
while (status & KMIIR_RXINTR) {
ps2keyboard_dev0->pscancode->scancode[ps2keyboard_dev0->pscancode->num]=readb(KMIDATA);
printk("%x\n",ps2keyboard_dev0->pscancode->scancode[ps2keyboard_dev0->pscancode->num]);
ps2keyboard_dev0->pscancode->num++;
status = readb(KMIIR);
handled = IRQ_HANDLED;
}
printk("n1=%d\n",ps2keyboard_dev0->pscancode->num);
//add key scancode to ps2keyboard_dev0list
list_add_tail(&ps2keyboard_dev0->pscancode->list, &ps2keyboard_dev0->keyscancode_list);
tasklet_schedule(&ps2keyboard_tasklet);
_return_:
return handled;
}
static void ps2keyboard_tasklet_fuc(unsigned long data)
{
int i,l;
struct scancode *pscancode;
struct ps2keyboard_dev *ps2keyboard_dev0 = (struct ps2keyboard_dev *) data;
printk("ps2keyboard_tasklet_fuc\n");
if(!list_empty(&ps2keyboard_dev0->keyscancode_list))
{
pscancode=list_first_entry(&ps2keyboard_dev0->keyscancode_list,struct scancode,list);
for(i=0;i<pscancode->num;i++)
printk("%x\n",pscancode->scancode[i]);
printk("n2=%d\n",pscancode->num);
for(i=0;i<ps2keyboard_dev0->ps2kbdcancodenum;i++)
{
/*
for(l=0;l<8;l++)
{
if(ps2keyboard_dev0->ps2kbdscancodelist[i].code[l]!=pscancode->scancode[l])
break;
}
if(l==8)
{
printk("i==%d\n",i);
break;
}*/
if(!memcmp(ps2keyboard_dev0->ps2kbdscancodelist[i].code,pscancode->scancode,8))
{
printk("i==%d\n",i);
if(KEY_LEFTALT==ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue||KEY_RIGHTALT==ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue){
spin_lock(alt_key_spinlock);
if (ps2keyboard_dev0->ps2kbdscancodelist[i].makeorbreak==MAKE_STATE ) {
alt_key_locking = 1;
} else if (alt_key_locking) {
alt_key_locking = 0;
}
spin_unlock(alt_key_spinlock);
}
else if(KEY_LEFTSHIFT==ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue||KEY_RIGHTSHIFT==ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue){
spin_lock(shift_key_spinlock);
if (ps2keyboard_dev0->ps2kbdscancodelist[i].makeorbreak==MAKE_STATE ) {
shift_key_locking = 1;
} else if (shift_key_locking) {
shift_key_locking = 0;
}
spin_unlock(shift_key_spinlock);
}
else if (KEY_CAPSLOCK==ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue&&ps2keyboard_dev0->ps2kbdscancodelist[i].makeorbreak==BREAK_STATE){
spin_lock(caps_spinlock);
if(caps_locking==1){
caps_locking = 0;
printk(KERN_ALERT "Capslock is disabled.\n");
} else {
caps_locking = 1;
printk(KERN_ALERT "Capslock is enabled.\n");
}
spin_unlock(caps_spinlock);
}
if(ps2keyboard_dev0->ps2kbdscancodelist[i].makeorbreak==MAKE_STATE)
input_event(ps2keyboard_dev0->input, EV_KEY, ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue, 1);
else
input_event(ps2keyboard_dev0->input, EV_KEY, ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue, 0);
break;
}
}
list_del_init(&pscancode->list);
kfree(pscancode);
}
//input_event(ps2keyboard_dev0->input, EV_KEY, KEY_1, 1);
//input_event(ps2keyboard_dev0->input, EV_KEY, KEY_1, 0);
/*
ps2keyboard_dev0->keyhead=ps2keyboard_dev0->keytail=0;
memset(ps2keyboard_dev0->keybuffer,0,MAX_KEY_NUM);
if(ps2keyboard_dev0->outindex!=ps2keyboard_dev0->inindex)
{
for(i=0;i<ps2keyboard_dev0->ps2kbdcancodenum;i++)
{
if(!memcmp(ps2keyboard_dev0->ps2kbdscancodelist[i].code,ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].scancode,ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].readdatalentg))
{
if(ps2keyboard_dev0->ps2kbdscancodelist[i].makeorbreak==MAKE_STATE)
{
//printk("\n");
for(l=0;l<ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].readdatalentg;l++)
printk("%x\n",ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].scancode[l]);
input_event(ps2keyboard_dev0->input, EV_KEY, ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue, 1);
}
else
{
//printk("\n");
input_event(ps2keyboard_dev0->input, EV_KEY, ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue, 0);
for(l=0;l<ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].readdatalentg;l++)
printk("%x\n",ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].scancode[l]);
}
memset(ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].scancode,0,8);
ps2keyboard_dev0->keybuffer[ps2keyboard_dev0->outindex].readdatalentg=0;
}
}
ps2keyboard_dev0->outindex=(ps2keyboard_dev0->outindex+1)%MAX_KEY_BUFFERNUM;
}
*/
}
static irqreturn_t hallone_isr(int irq, void *dev_id)
{
struct ps2keyboard_dev *ps2keyboard_dev0 = dev_id;
tasklet_schedule(&hallone_tasklet);
return IRQ_HANDLED;
}
static void hallone_tasklet_fuc(unsigned long data)
{
struct ps2keyboard_dev *ps2keyboard_dev0 = (struct ps2keyboard_dev *) data;
printk("---------------hallone_tasklet_fuc----------------\n");
input_event(ps2keyboard_dev0->input, EV_KEY, KEY_1, 1);
input_event(ps2keyboard_dev0->input, EV_KEY, KEY_1, 0);
}
static irqreturn_t halltwo_isr(int irq, void *dev_id)
{
struct ps2keyboard_dev *ps2keyboard_dev0 = dev_id;
int handled = IRQ_HANDLED;
printk("---------------irqreturn_t halltwo_isr----------------\n");
input_event(ps2keyboard_dev0->input, EV_KEY, KEY_2, 1);
input_event(ps2keyboard_dev0->input, EV_KEY, KEY_2, 0);
//input_sync(ps2keyboard_dev0->input);
_return_:
return handled;
}
static int ps2keyboard_probe(struct platform_device *pdev){
struct ps2keyboard_dev *ps2keyboard_dev0;
struct input_dev *input;
struct resource *res;
int i,error,ret;
printk("---------------ps2keyboard_probe----------------\n");
ps2keyboard_dev0 = kzalloc(sizeof(struct ps2keyboard_dev), GFP_KERNEL);
if (!ps2keyboard_dev0) {
dev_err(&pdev->dev, "No memory for ps2keyboard_dev0\n");
return -ENOMEM;
}
input = input_allocate_device();
if (!input) {
printk("ps2keyboard allocate input device failed.\n");
return -ENOMEM;
}
ps2keyboard_dev0->ps2kbdscancodelist=&ps2keyborad_scancodes[0];
ps2keyboard_dev0->ps2kbdcancodenum=ARRAY_SIZE(ps2keyborad_scancodes);
for(i=0;i<ps2keyboard_dev0->ps2kbdcancodenum;i+=2)
input_set_capability(input, EV_KEY, ps2keyboard_dev0->ps2kbdscancodelist[i].keyvalue);
input->name = "ps2keyboard";
input->phys = "ps2keyboard/input0";
input->dev.parent = &pdev->dev;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
ps2keyboard_dev0->input = input;
error = input_register_device(input);
if (error) {
printk("ps2keyboard: Unable to register input device, ""error: %d\n", error);
goto __fail_exit__;
}
ps2keyboard_dev0->gpio_capslock=__imapx_name_to_gpio(CONFIG_PS2KEYBOARD_LED_CAPSLOCK);
ps2keyboard_dev0->gpio_numlock=__imapx_name_to_gpio(CONFIG_PS2KEYBOARD_LED_NUMLOCK);
ps2keyboard_dev0->gpio_hallone=__imapx_name_to_gpio(CONFIG_PS2KEYBOARD_HALLONE);
ps2keyboard_dev0->gpio_halltwo=__imapx_name_to_gpio(CONFIG_PS2KEYBOARD_HALLTWO);
ps2keyboard_dev0->gpio_halloneirq= imapx_gpio_to_irq(ps2keyboard_dev0->gpio_hallone);
ps2keyboard_dev0->gpio_halltwoirq= imapx_gpio_to_irq(ps2keyboard_dev0->gpio_halltwo);
imapx_gpio_setcfg(ps2keyboard_dev0->gpio_hallone, IG_INPUT, IG_NORMAL);
imapx_gpio_setirq(ps2keyboard_dev0->gpio_hallone, FILTER_MAX, IG_FALL, 1);
imapx_gpio_setcfg(ps2keyboard_dev0->gpio_halltwo, IG_INPUT, IG_NORMAL);
imapx_gpio_setirq(ps2keyboard_dev0->gpio_halltwo, FILTER_MAX, IG_FALL, 1);
ret = request_irq(ps2keyboard_dev0->gpio_halloneirq, hallone_isr, IRQF_DISABLED,dev_name(&pdev->dev), ps2keyboard_dev0);
if (ret != 0) {
dev_err(&pdev->dev, "cannot claim hallone IRQ %d\n", ps2keyboard_dev0->irq);
goto _err_iomap_;
}
//ret = request_irq(ps2keyboard_dev0->gpio_halltwoirq, halltwo_isr, IRQF_DISABLED,dev_name(&pdev->dev), ps2keyboard_dev0);
//if (ret != 0) {
// dev_err(&pdev->dev, "cannot claim halltwo IRQ %d\n", ps2keyboard_dev0->irq);
// goto _err_iomap_;
//}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "cannot find IO resource\n");
ret = -ENOENT;
goto __fail_exit__;
}
ps2keyboard_dev0->ioarea = request_mem_region(res->start, resource_size(res),pdev->name);
if (ps2keyboard_dev0->ioarea == NULL) {
dev_err(&pdev->dev, "cannot request IO\n");
ret = -ENXIO;
goto __fail_exit__;
}
ps2keyboard_dev0->base_reg = ioremap(res->start, resource_size(res));
if (ps2keyboard_dev0->base_reg == NULL) {
dev_err(&pdev->dev, "cannot map IO\n");
ret = -ENXIO;
goto _err_ioarea_;
}
printk("registers %p (%p, %p)\n",ps2keyboard_dev0->base_reg,ps2keyboard_dev0->ioarea, res);
ps2keyboard_dev0->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
dev_err(&pdev->dev, "cannot find IRQ\n");
goto _err_iomap_;
}
//ps2keyboard_dev0->inindex=ps2keyboard_dev0->outindex=0;
//for(i=0;i<MAX_KEY_BUFFERNUM;i++)
//{
// memset(ps2keyboard_dev0->keybuffer[i].scancode,0,8);
// ps2keyboard_dev0->keybuffer[i].readdatalentg=0;
//}
//init list_head list
INIT_LIST_HEAD(&ps2keyboard_dev0->keyscancode_list);
ret = request_irq(ps2keyboard_dev0->irq, ps2keyboard_isr, IRQF_DISABLED,
dev_name(&pdev->dev), ps2keyboard_dev0);
if (ret != 0) {
dev_err(&pdev->dev, "cannot claim IRQ %d\n", ps2keyboard_dev0->irq);
goto _err_iomap_;
}
writeb(0xF, KMICLKDIV);
writeb(KMICR_EN, KMICR);
imapx_gpio_setcfg(IMAPX_GPC_RANGE(4, 7), IG_CTRL0, IG_NORMAL);
writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
platform_set_drvdata(pdev, ps2keyboard_dev0);
tasklet_enable(&ps2keyboard_tasklet);
ps2keyboard_tasklet.data = (unsigned long) ps2keyboard_dev0;
tasklet_enable(&hallone_tasklet);
hallone_tasklet.data = (unsigned long) ps2keyboard_dev0;
if (caps_spinlock == NULL) {
caps_spinlock = (spinlock_t *)kmalloc(sizeof(spinlock_t), GFP_KERNEL);
if (caps_spinlock == NULL) {
printk("ps2keyboard_probe:kmalloc() for capslock key spinlock error.\n");
goto _err_iomap_;
}
spin_lock_init(caps_spinlock);
}
if (shift_key_spinlock ==NULL) {
shift_key_spinlock = (spinlock_t *)kmalloc(sizeof(spinlock_t), GFP_KERNEL);
if (shift_key_spinlock == NULL) {
printk(KERN_ERR "ps2keyboard_probe:kmalloc() for shift key spinlock error.\n");
goto _err_iomap_;
}
spin_lock_init(shift_key_spinlock);
}
if (alt_key_spinlock ==NULL){
alt_key_spinlock = (spinlock_t *)kmalloc(sizeof(spinlock_t), GFP_KERNEL);
if (alt_key_spinlock == NULL) {
printk(KERN_ERR "ps2keyboard_probe:kmalloc() for alt key spinlock error.\n");
goto _err_iomap_;
}
spin_lock_init(alt_key_spinlock);
}
return 0;
_err_iomap_:
iounmap(ps2keyboard_dev0->base_reg);
_err_ioarea_:
release_resource(ps2keyboard_dev0->ioarea);
kfree(ps2keyboard_dev0->ioarea);
__fail_exit__:
input_free_device(input);
return ret;
}
static int __devexit ps2keyboard_remove(struct platform_device *pdev){
struct ps2keyboard_dev *ps2keyboard_dev0=platform_get_drvdata(pdev);
input_unregister_device(ps2keyboard_dev0->input);
free_irq(ps2keyboard_dev0->irq, ps2keyboard_dev0);
free_irq(ps2keyboard_dev0->gpio_halloneirq, ps2keyboard_dev0);
free_irq(ps2keyboard_dev0->gpio_halltwoirq, ps2keyboard_dev0);
iounmap(ps2keyboard_dev0->base_reg);
release_resource(ps2keyboard_dev0->ioarea);
kfree(ps2keyboard_dev0->ioarea);
tasklet_disable(&ps2keyboard_tasklet);
tasklet_kill(&ps2keyboard_tasklet);
tasklet_disable(&hallone_tasklet);
tasklet_kill(&hallone_tasklet);
return 0;
}
#ifdef CONFIG_PM
static int ps2keyboard_suspend(struct platform_device *pdev, pm_message_t state)
{
struct ps2keyboard_dev *ps2keyboard_dev0=platform_get_drvdata(pdev);
return 0;
}
static int ps2keyboard_resume(struct platform_device *pdev)
{
struct ps2keyboard_dev *ps2keyboard_dev0=platform_get_drvdata(pdev);
return 0;
}
#else
#define ps2keyboard_suspend NULL
#define ps2keyboard_resume NULL
#endif
static struct platform_driver ps2keyboard_driver = {
.probe = ps2keyboard_probe,
.remove = __devexit_p(ps2keyboard_remove),
.suspend = ps2keyboard_suspend,
.resume = ps2keyboard_resume,
.driver = {
.name = "ps2keyboard",
.owner = THIS_MODULE,
},
};
static int __init ps2keyboard_init(void){
printk("---------------ps2keyboard_init----------------\n");
return platform_driver_register(&ps2keyboard_driver);
}
static void __exit ps2keyboard_exit(void) {
printk("---------------ps2keyboard_exit----------------\n");
platform_driver_unregister(&ps2keyboard_driver);
}
module_init(ps2keyboard_init);
module_exit(ps2keyboard_exit);
MODULE_DESCRIPTION("PS2Keyboard's Android Driver");
MODULE_LICENSE("GPL");
imapx200_ps2_keyboard.h
#ifndef _PS2KEYBOARD_FOR_ANDROID_H_
#define _PS2KEYBOARD_FOR_ANDROID_H_
#include <linux/cdev.h>
#include <linux/semaphore.h>
#include <linux/ioctl.h>
#define ATMELCRYPTIC_MAGIC 'k'
#define WRITE_MTZ _IOW(ATMELCRYPTIC_MAGIC,0,struct ps2keyboard_inout_data)
#define READ_MTZ _IOWR(ATMELCRYPTIC_MAGIC,1,struct ps2keyboard_inout_data)
#define ATMELCRYPTIC_MAXNR 3
//ps2 keyboard press state
#define MAKE_STATE 0
#define BREAK_STATE 1
//ps2 keyboard scan code structure
#define MAX_KEY_NUM 200
#define MAX_KEY_BUFFERNUM 10
struct ps2keyborad_scancode
{
unsigned char makeorbreak;
unsigned char keyvalue;
unsigned char len;
unsigned char code[8];
};
struct scancode{
//scancode
unsigned char scancode[8];
//scancode length
int num;
struct list_head list;
};
//ps2 keyboard driver structure
struct ps2keyboard_dev {
//PS2 keyborad scan code list
struct ps2keyborad_scancode *ps2kbdscancodelist;
//GPIO base address
void __iomem *base_reg;
//mem space
struct resource *ioarea;
//PS2 keyborad scan code number
int ps2kbdcancodenum;
//PS2 keyborad capslock led control gpio
unsigned int gpio_capslock;
//PS2 keyborad num led control gpio
unsigned int gpio_numlock;
//hall interrupt gpio1
unsigned int gpio_hallone;
unsigned int gpio_halloneirq;
//hall interrupt gpio2
unsigned int gpio_halltwo;
unsigned int gpio_halltwoirq;
//ps2 keyboard interrupt number
unsigned int irq;
struct input_dev *input;
struct list_head keyscancode_list;
//struct scancode keybuffer[MAX_KEY_BUFFERNUM];
//int inindex,outindex;
struct scancode *pscancode;
};
#endif
------------------------------------------------------------------------------------
QQ:229425962
------------------------------------------------------------------------------------