?? scankbd.c
字號:
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include<linux/config.h>
#include<linux/module.h>
#include<linux/moduleparam.h>
#include<linux/init.h>
#include <linux/input.h>
#include<linux/kernel.h>
#include<linux/types.h>
#include<linux/interrupt.h>
#include<asm/io.h>
#include<asm/arch/regmap.h>
#include<asm/arch/regs_syscon.h>
#define KEYREG_KEY1_MASK 0x0000003F
#define KEYREG_KEY1_SHIFT 0
#define KEYREG_KEY2_MASK 0x00000Fc0
#define KEYREG_KEY2_SHIFT 6
#define KEYREG_KEY1ROW_MASK 0x00000007
#define KEYREG_KEY1ROW_SHIFT 0
#define KEYREG_KEY1COL_MASK 0x00000038
#define KEYREG_KEY1COL_SHIFT 3
#define KEYREG_KEY2ROW_MASK 0x000001c0
#define KEYREG_KEY2ROW_SHIFT 6
#define KEYREG_KEY2COL_MASK 0x00000E00
#define KEYREG_KEY2COL_SHIFT 9
#define KEYREG_1KEY 0x00001000
#define KEYREG_2KEYS 0x00002000
#define KEYREG_INT 0x00004000
#define KEYREG_K 0x00008000
#define SCANINIT_DIS3KY 0x00008000
MODULE_LICENSE("Dual BSD/GPL");
#define DEBUG
#define STANDARD_EP93XX_SCANKBD //this is for standard scan kbd
//#define HNAC_EP93XX_SCANKBD
#define DOWN 1
#define UP 0
#define EP93XX_SCAN_TABLE_SIZE 64
static unsigned int const Ep93xxScanCodeToVKeyTable[EP93XX_SCAN_TABLE_SIZE+1] =
{
KEY_RESERVED,
KEY_A,
KEY_B,
KEY_C,
KEY_D,
KEY_E,
KEY_F,
KEY_G,
KEY_H,
KEY_I,
KEY_J,
KEY_K,
KEY_L,
KEY_M,
KEY_N
};
static struct input_dev ep93xxscankbd;
static unsigned char *name = "Cirrus Ep93xx Scan Keyboard Driver";
void report_key(unsigned int code, unsigned int down)
{
#ifdef DEBUG
unsigned char string[2][5] ={"UP", "DOWN"};
printk("keyvalue = %d, %s\n", code, string[down]);
#endif
input_report_key(&ep93xxscankbd, Ep93xxScanCodeToVKeyTable[code], down);
input_sync(&ep93xxscankbd);
}
irqreturn_t ep93xx_scan_kbd_irq( int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int uiCurrentKeyStat, uiKey1, uiKey2;
static unsigned int uiLastKeyStat = 0, uiLastKey1 = 0, uiLastKey2 = 0;
#ifdef DEBUG
printk("Enter ep93xx_scan_kbd_irq_handler()\n");
#endif
uiCurrentKeyStat = inl(KEY_REG) &
(KEYREG_KEY1COL_MASK | KEYREG_KEY1ROW_MASK |
KEYREG_KEY2COL_MASK | KEYREG_KEY2ROW_MASK |
KEYREG_1KEY | KEYREG_2KEYS);
#ifdef DEBUG
if(uiCurrentKeyStat == uiLastKeyStat)
{
printk("ep93xx_scan_kbd: spurious interrupts, stat=0x%8X\n", uiCurrentKeyStat);
}
else
{
printk("ep93xx_scan_kbd: new interrupt, stat=0x%8X\n", uiCurrentKeyStat);
}
#endif
if(uiCurrentKeyStat & KEYREG_1KEY)
{
uiKey1 = ((uiCurrentKeyStat & (KEYREG_KEY1COL_MASK | KEYREG_KEY1ROW_MASK)) >> KEYREG_KEY1_SHIFT) + 1;
}
else
{
uiKey1 = 0;
}
#ifdef DEBUG
printk("key1 : %d\n", uiKey1);
#endif
if(uiCurrentKeyStat & KEYREG_2KEYS)
{
uiKey2 = ((uiCurrentKeyStat & (KEYREG_KEY2COL_MASK | KEYREG_KEY2ROW_MASK)) >> KEYREG_KEY2_SHIFT) + 1;
}
else
{
uiKey2 = 0;
}
#ifdef DEBUG
printk("key2 : %d\n", uiKey2);
#endif
#ifdef HNAC_EP93XX_SCANKBD
if(!(uiLastKeyStat & (KEYREG_1KEY | KEYREG_2KEYS)))
{ //no key is pressed in last time
if(uiCurrentKeyStat & KEYREG_1KEY)
{ //
report_key(uiKey1, DOWN);
}
uiLastKeyStat = uiCurrentKeyStat;
uiLastKey1 = uiKey1;
}
else
{ //have some keys are pressed in last time
if(!(uiCurrentKeyStat & (KEYREG_1KEY | KEYREG_2KEYS)))
{ //no key is pressed this time
if(uiLastKey1)
{
report_key(uiLastKey1, UP);
}
uiLastKeyStat = uiCurrentKeyStat;
}
else
{ //have some keys are pressed this time
}
}
#endif //#define HNAC_EP93XX_SCANKBD
#ifdef STANDARD_EP93XX_SCANKBD
if(!(uiLastKeyStat & (KEYREG_1KEY | KEYREG_2KEYS)))
{ //the last time, it is no key be pressed, this time, key1 and key2 are pressed
if(uiKey1)
{ //this time, the first key is pressed
report_key(uiKey1, DOWN);
}
if(uiKey2)
{ //this time, the first key is pressed
report_key(uiKey2, DOWN);
}
}
else if(uiLastKey1 == uiKey1)
{ //this time' key1 is also equal to the last time's key1, it is still down
if(uiKey2 != uiLastKey2)
{ //this time's key2 is no the last time's, it's mean this time's key2 is changed
if(uiLastKey2)
{ //the last time, key2 is pressed, and now it is released
report_key(uiLastKey2, UP);
}
if(uiKey2)
{ //this time, a new key2 is pressed
report_key(uiKey2, DOWN);
}
}
}
else if(uiKey1)
{ //this time, key1 is no equal to the last time's, it's mean key1 is changed
if(uiKey2 == uiLastKey1)
{ //last time's key1 is this time's key2, it's said that this time's key1 is new key be pressed, and last time's key2 is maybe released
if(uiLastKey2)
{ //last time's key2 is released
report_key(uiLastKey2, UP);
}
//this time's key1 is a new key be pressed
report_key(uiKey1, DOWN);
}
else
{ //the last time's key1 is released
report_key(uiLastKey1, UP);
if(uiKey1 == uiLastKey2)
{ //this time's key1 is equal to the last time's key2, it's said this time's key2 is a new key be pressed
if(uiKey2)
{
report_key(uiKey2, DOWN);
}
}
else
{ //this time's key1 is new key be pressed, and key2 meybe is new key????
if(uiKey2 != uiLastKey2)
{ //key1 and key2 are all new keys be pressed
if(uiLastKey2)
{
report_key(uiLastKey2, UP);
}
if(uiKey2)
{
report_key(uiKey2, DOWN);
}
}
report_key(uiKey1, DOWN);
}
}
}
else
{ //this time's key1 and key2 are not vailable, so last time's key1 and key2 are released
if(uiLastKey1)
{
report_key(uiLastKey1, UP);
}
if(uiLastKey2)
{
report_key(uiLastKey2, UP);
}
}
uiLastKeyStat = uiCurrentKeyStat;
uiLastKey1 = uiKey1;
uiLastKey2 = uiKey2;
#endif //#define STANDARD_EP93XX_SCANKBD
#ifdef DEBUG
printk("Leaving ep93xx_scan_kbd_irq_handler()\n\n\n\n");
#endif
// input_sync(&ep93xxscankbd);
return IRQ_HANDLED;
}
static __init int ep93xx_scan_kb_init(void)
{
unsigned long ulFlags;
unsigned int uiTemp;
int iFirstKey;
int i;
printk("%s\n", name);
save_flags(ulFlags);
cli();
uiTemp = inl(SYSCON_DEVCFG);
uiTemp &= ~(SYSCON_DEVCFG_KEYS | SYSCON_DEVCFG_GONK);
SysconSetLocked(SYSCON_DEVCFG, uiTemp);
outl( (0x00FC00FA | SCANINIT_DIS3KY), SCANINIT );
//TBD If too much capacitance on keyboard
//outl( (0x00FC0020 | SCBACK | SCDIS3KEY), SCANINIT );
uiTemp = inl(SYSCON_KTDIV) | SYSCON_KTDIV_KEN;
SysconSetLocked(SYSCON_KTDIV, uiTemp);
if (request_irq( IRQ_KEY, ep93xx_scan_kbd_irq, SA_INTERRUPT,
"ep93xx_scan_keyb", 0))
{
printk("EP93xx scan keyboard driver aborting"
" due to IRQ_KEY unavailable.\n");
restore_flags(ulFlags);
return -EBUSY;
}
else
{
printk("request_irq success\n");
}
iFirstKey = inl(KEY_REG);
restore_flags(ulFlags);
ep93xxscankbd.name = name;
ep93xxscankbd.evbit[0] = BIT(EV_KEY);
for(i=0; i<EP93XX_SCAN_TABLE_SIZE; i++){
set_bit(Ep93xxScanCodeToVKeyTable[i], ep93xxscankbd.keybit);
}
input_register_device(&ep93xxscankbd);
#ifdef DEBUG
printk("Leaving ep93xx_scan_kb_init()\n");
#endif
return 0;
}
static __exit void ep93xx_scan_kb_cleanup(void)
{
#ifdef DEBUG
printk("Enter ep93xx_scan_kb_cleanup()\n");
#endif
free_irq(IRQ_KEY, 0);
#ifdef DEBUG
printk("Leaving ep93xx_scan_kb_cleanup()\n");
#endif
}
module_init(ep93xx_scan_kb_init);
module_exit(ep93xx_scan_kb_cleanup);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -