⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scankbd.c

📁 Ep9315 arm ep9315 按键扫描程序
💻 C
字号:
#ifndef __KERNEL__
#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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -