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

📄 kpp.c

📁 freescale的关于Imax21的kbd程序,好用
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef __KERNEL__#  define __KERNEL__#endif#ifndef MODULE#  define MODULE#endif//<<<<<< Private Macro#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/poll.h>#include <asm/uaccess.h>        /* get_user,copy_to_user */#include <linux/miscdevice.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/string.h>#include <linux/init.h>#include <asm/bitops.h>#include <asm/io.h>#include <linux/errno.h>#include <linux/tqueue.h>#include <linux/wait.h>#include <asm/irq.h>#include <asm/arch/hardware.h>#include <asm/arch/irqs.h>#include <asm/arch/mx2.h>#include <linux/pm.h>#include "kpp.h"#define CONFIG_ARCH_MX2ADS#define MODULE_NAME "kpp"//#define DBMX_DEBUG 1#ifdef DBMX_DEBUG#define TRACE(fmt, args...) \	{ \		printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \		printk(fmt, ## args);\	}#else#define TRACE(fmt, args...)#endif#define FAILED(fmt, args...) \	{ \		printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \		printk(fmt, ## args);\	}#define INFO(fmt, args...) \	{ \		printk("\n"); \		printk(fmt, ## args);\	}//>>>>>> Private Macro#define KPP_MX2_MASK			0x3f3f //for MX2, it is 6*6 key matrix#define KPP_MX2_COL_NUM			6#define KPP_MX2_ROW_NUM			6#ifdef 	_reg_KPP_KPCR#undef	_reg_KPP_KPCR#endif#ifdef 	_reg_KPP_KPSR#undef	_reg_KPP_KPSR#endif#ifdef 	_reg_KPP_KDDR#undef	_reg_KPP_KDDR#endif#ifdef 	_reg_KPP_KPDR#undef	_reg_KPP_KPDR#endif#define KPP_BASE_ADDR 			0x10008000#define _reg_KPP_KPCR			(*((volatile unsigned short *)(IO_ADDRESS(KPP_BASE_ADDR+0x00))))	//  16bit kpp keypad control reg#define _reg_KPP_KPSR			(*((volatile unsigned short *)(IO_ADDRESS(KPP_BASE_ADDR+0x02))))	//  16bit kpp keypad status reg#define _reg_KPP_KDDR			(*((volatile unsigned short *)(IO_ADDRESS(KPP_BASE_ADDR+0x04))))	//  16bit kpp keypad data directon reg#define _reg_KPP_KPDR			(*((volatile unsigned short *)(IO_ADDRESS(KPP_BASE_ADDR+0x06))))	//  16bit kpp keypad data reg#define kpp_row_enable(mask)	(_reg_KPP_KPCR|(mask))#define kpp_col_enable(mask)	(_reg_KPP_KPCR|(mask<<8))#define KPP_KPPEN_BIT_MASK		0x0400 //kpp clock gating enable#define KPP_KRIE_BIT_MASK		0x0200 //kpp release interrupt enable#define KPP_KDIE_BIT_MASK		0x0100 //kpp depress interrupt enable#define KPP_KRSS_BIT_MASK		0x0008 //kpp release synchronizer set#define KPP_KDSC_BIT_MASK		0x0004 //kpp depress synchronizer clear#define KPP_KPKR_BIT_MASK		0x0002 //kpp key release#define KPP_KPKD_BIT_MASK		0x0001 //kpp key depress#define KPP_IRQ					21//<<<<<Private Function Declearation//>>>>>Private Function Declearation//<<<<<< Global Variablestatic int	g_kpp_major=0;//static struct proc_dir_entry * g_proc_dir;static devfs_handle_t g_devfs_handle;static u8 kpp_pressed=0;static struct timer_list kpp_timer;	static u8 kpp_timer_status;	wait_queue_head_t g_mx21_kpp_wait;spinlock_t kpp_lock;static u32 g_key_code[2];static u32 old_key_code[2];static u16 rptr, wptr;key_code_t * g_mx21_kpp_buffer;struct pm_dev *g_kpp_pm;static int g_kpp_status;#define KPP_OPEN_STATUS		0x0001#define KPP_SUSPEND_STATUS	0x0002//>>>>>> Global Variable#define NODATA() 		(rptr == wptr)#define BUFFLENTH		8#define BUFFSIZE		(BUFFLENTH*sizeof(key_code_t))#define NEXTITEM(i)		{i=(i==BUFFLENTH-1)?0:i+1;}#define GETNEXTIEM(i)	((i==BUFFLENTH-1)?0:i+1)#define DATASIZE()		((wptr<rptr)?(BUFFLENTH-rptr):(wptr-rptr))#define DEPRESSED		0xff#define RELEASED		0x0static int init_buf(void){	g_mx21_kpp_buffer = (key_code_t*) kmalloc(BUFFSIZE,GFP_KERNEL);		if(!g_mx21_kpp_buffer){		printk(KERN_ERR"no enough kernel memory for spi data buffer\n");		return -1;	}	rptr = wptr = 0;	return 1;}static void add_key_code(u32 low, u32 high, u32 flag){		if (GETNEXTIEM(wptr) == rptr)		return;	g_mx21_kpp_buffer[wptr].low = low;	g_mx21_kpp_buffer[wptr].high = high;	g_mx21_kpp_buffer[wptr].status = flag;	NEXTITEM(wptr);	// goto next wptr}static key_code_t* get_data(void){	key_code_t *data;		if(NODATA())		return NULL;	data = &(g_mx21_kpp_buffer[rptr]);	TRACE("*** Read - low: 0x%04x, high: 0x%04x, rptr: 0x%04x, wptr: 0x%04x\n", data->low, data->high, (int)rptr, (int)wptr);		NEXTITEM(rptr);	return data;}static void mx2ads_mask_irq(unsigned int irq){	_reg_AITC_INTENABLEL &= ~(1<<irq);}static void mx2ads_unmask_irq(unsigned int irq){	_reg_AITC_INTENABLEL |= (1<<irq);}//Configure KPP setting,			void kpp_hw_configure(){	u16 row,col;	row = KPP_MX2_MASK&0x00ff;	col = KPP_MX2_MASK&0xff00;		//GPIO portE3467 as alternate function, since the UART2 has some conflict to Keypad	_reg_GPIO_GIUS(GPIOE) &= ~0x000000d8;	_reg_GPIO_GPR(GPIOE) |= 0x000000d8;		//enable clk gate of kpp	_reg_CRM_PCCR1 |= 0x40000000;	_reg_KPP_KPSR |= KPP_KPPEN_BIT_MASK;		//enable key	_reg_KPP_KPCR |= row;	//clear kpp data register	_reg_KPP_KPDR &= ~(col|row);	//configure col as output opendrain	_reg_KPP_KPCR |= col;	_reg_KPP_KDDR |= col;	//configure row as input	_reg_KPP_KDDR &= ~row;	//Clear KPKD status flag and synchronizer chain	_reg_KPP_KPSR |= KPP_KDSC_BIT_MASK;	_reg_KPP_KPSR |= KPP_KPKD_BIT_MASK;	//Set KDIE control bit, clear the KRIE control bit	_reg_KPP_KPSR |= KPP_KDIE_BIT_MASK;	_reg_KPP_KPSR &= ~KPP_KRIE_BIT_MASK;}static void kpp_irq_enable(){	//clear key depress event	_reg_KPP_KPSR |= KPP_KPKD_BIT_MASK;	//clear key release event	_reg_KPP_KPSR |= KPP_KPKR_BIT_MASK;	//enable irq		mx2ads_unmask_irq(KPP_IRQ);	}//for col0, will have eight bit mask, though bit6,7 is not used by any key in current keyboardstatic void keycode_convert(u16 scancode, u32* p_key_code){	u16 tempcol,colnum;	u16 temprow;	u16 tmp;	int i;	u32 code[2];	tmp = 1;	tempcol = (scancode&KPP_MX2_MASK&0xff00)>>8;	temprow = ~(scancode&KPP_MX2_MASK&0x00ff);	code[0]=code[1]=0;	TRACE("scancode = 0x%x ,temprow = 0x%x \n",scancode,temprow);	if(tempcol & 0xf)//col0~3	{		for(i=0;i<4;i++)		{			if(tempcol & (1<<i))			{				colnum = i;				break;			}			}		for(i=0; i<6; i++)		{			if(temprow&(1<<i))				code[0] |= 1<<(colnum*8 + i);					}	}	if(tempcol & 0xf0)//col4~7	{		for(i=4;i<8;i++)		{			if(tempcol & (1<<i))			{				colnum = i-4;				break;			}			}		for(i=0; i<6; i++)		{			if(temprow&(1<<i))				code[1] |= 1<<(colnum*8 + i);					}	}	*p_key_code |= code[0];	p_key_code++;	*p_key_code |= code[1];//	TRACE("key_code[0] = 0x%x key_code[1] = 0x%x \n",code[0],code[1]);	}static void kpp_scan_matrix(){	u16 row,col;	u16 iCol,scanMask;	u16 keypressed;	old_key_code[0] = g_key_code[0];	old_key_code[1] = g_key_code[1];	g_key_code[0] = g_key_code[1] = 0;	row = KPP_MX2_MASK&0x00ff;	col = KPP_MX2_MASK&0xff00;	iCol=0;	scanMask=0;	kpp_pressed = 0;	for(iCol=0; iCol<KPP_MX2_COL_NUM; iCol++)	{		//write 1's to KPDR[15:8]		_reg_KPP_KPDR |= col;		//configure columns as totem-pole outputs		_reg_KPP_KPCR &= ~col;		//configure columns as open-drain		_reg_KPP_KPCR |= col;		//write a single column to 0,others to 1		scanMask = (1<<(iCol+8));		_reg_KPP_KPDR &= ~scanMask;		//sample row inputs and save data. 		keypressed = (_reg_KPP_KPDR&0x00ff)| scanMask;		if((_reg_KPP_KPDR&row)!=row)		{	kpp_pressed = 1;			keycode_convert(keypressed,g_key_code);		}		//restore the colmask		_reg_KPP_KPDR |= scanMask;	}	_reg_KPP_KPDR &= ~col;	TRACE("g_key_code[0] = 0x%x g_key_code[1]=0x%x \n",g_key_code[0],g_key_code[1]);	if((g_key_code[0] != old_key_code[0])||(g_key_code[1] != old_key_code[1]))	{		if(kpp_pressed == 1)			add_key_code(g_key_code[0], g_key_code[1], DEPRESSED);		else			add_key_code(g_key_code[0], g_key_code[1], RELEASED);			wake_up_interruptible(&g_mx21_kpp_wait);

⌨️ 快捷键说明

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