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

📄 s3c2440_kb.c

📁 键盘驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************** * s3c2440-ts.c * * keyboard driver for S3C2440 based PDA * * * History: * * ***********************************************************/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <asm/irq.h>#include <asm/arch/irq.h>#include <asm/arch/irqs.h>#include <asm/arch/clocks.h>#include <asm/hardware.h>#include <asm/arch/S3C2440.h>#define DEVICE_NAME	"s3c2440-kb" //键盘设备名static int kbMajor = 0; //默认的主设备号#define MAX_KB_BUF	10 //循环队列的尺寸	typedef struct {	unsigned int keyStatus;	int irq;//	int timeCount;	u_short buf[MAX_KB_BUF];		/* 循环队列*/	unsigned int head, tail;	/* 循环队列的读写指针*/	spinlock_t lock;			/*锁*/} KB_DEV;static KB_DEV kbdev;#define KEY_UP		0  //按键弹起#define KEY_DOWN	1	//按键按下#define NO_KEY_DOWN 2  //没有键按下#define EINT1_DOWN	0#define EINT3_DOWN	1#define EINT8_DOWN  2#define NO_EINT_DOWN 3/*循环队列操作*/#define BUF_HEAD	(kbdev.buf[kbdev.head])#define BUF_TAIL	(kbdev.buf[kbdev.tail])#define INCBUF(x) 	if((++x)==MAX_KB_BUF) x=0/*定时器设置*/#define KB_TIMER_DELAY  (HZ/50) /*HZ表示每秒产生的时钟滴答数,定时器超时为20ms*/#define REPEAT_START_DELAY  (HZ) /* 自动重复开始延时:1秒*/#define REPEAT_DELAY (HZ/2)		/*自动重复延时:0.5秒*/static struct timer_list kb_timer;static struct timer_list repeat_timer;spinlock_t repeat_lock;static int timeCount =1;static int TIME_OUT  =5;/*键盘矩阵*/static u_short keyboard_code_map[4][3]={											{1 , 2 , 3 },											{4 , 5 , 6 },											{7 , 8 , 9 },											{10, 11, 12}										}; //每个按键对应的键盘码static u_short pre_keyboard_code  = 0; //上次扫描得到的按键值static u_short curr_keyboard_code = 0;//当前扫描得到的按键值static u_short snap_keyboard_code[4][3]={											{0 , 0 , 0 },											{0 , 0 , 0 },											{0 , 0 , 0 },											{0,  0,  0}										}; //临时按键值#define DETECTION_THROLD	3static int requestIrq();static int s3c2440_kb_release(struct inode *inode, struct file *filp);/*----------------------------------------------------*  func: 初始化GPJCON寄存器,将GPJ9,GPJ10,GPJ11,GPJ12*        配置成output管腿*  ------------------------------------------------------*/static void init_gpjcon(){		//GPJ9,GPJ10,GPJ11,GPJ12------>output	GPJCON &= 0xFC03FFFF;	GPJCON |= 0x01540000;}/*----------------------------------------------------*  func:  向GPJ9,GPJ10,GPJ11,GPJ12输出value*  param: *        value: 输出值*  ------------------------------------------------------*///static inline void output_giop(int value )  //往所有行输出{	value &= 0x0000000F;	value <<= 9;	GPJDAT &= 0xE1FF;	GPJDAT |= value;	udelay(2);}/*----------------------------------------------------*  func:  判断eint当前是否是低电平*  param: *        irq: 当前引发中断的eint的irq号*  return: *           EINT1_DOWN: eint1上是低电平*           EINT3_DOWN: eint3上是低电平*           EINT8_DOWN: eint8上是低电平*			NO_EINT_DOWN:eint上不是低电平------------------------------------------------------*/int get_eint_value(int irq){	u_int IOValue;	IOValue = GPFDAT ;		if( (irq == 1) && (( IOValue & 0x00000002)==0)    )              	{					return EINT1_DOWN;	}	if((irq ==3 ) && (( IOValue & 0x00000008)==0) )	{		return EINT3_DOWN;	}	IOValue = GPGDAT ;	if((irq ==36) && (( IOValue & 0x0000001)==0) )	{				 return EINT8_DOWN;	}	return NO_EINT_DOWN;}/*----------------------------------------------------*  func:  扫描键盘,判断哪一个键被按下*  param: *        x: 得到按键的行号*		 y: 得到按键的列号*  return: *           KEY_DOWN: 键盘上有键被按下*           NO_KEY_DOWN: 键盘上没有键被按下------------------------------------------------------*/static inline int scan_keyboard(int* x,int* y){	int matrix_row,matrix_col,matrix_col_status;	output_giop(0xF);  //往所有行输出1		//判断按键在哪一行	matrix_row=matrix_col=-1;	output_giop(0xE);//在第1行上输出1,其余行输出0	matrix_col_status = get_eint_value(kbdev.irq);	if(matrix_col_status != NO_EINT_DOWN)	{		matrix_row = 0;		matrix_col = matrix_col_status;		goto scanend;	}	output_giop(0xD);//在第2行上输出1,其余行输出0	matrix_col_status = get_eint_value(kbdev.irq);	if(matrix_col_status != NO_EINT_DOWN)	{		matrix_row=1;		matrix_col = matrix_col_status;		goto scanend;	}	output_giop(0xB);//在第3行上输出1,其余行输出0	matrix_col_status =get_eint_value(kbdev.irq);	if(matrix_col_status != NO_EINT_DOWN)	{		matrix_row=2;		matrix_col = matrix_col_status;		goto scanend;	}	output_giop(0x7);//在第4行上输出1,其余行输出0	matrix_col_status =get_eint_value(kbdev.irq);	if(matrix_col_status != NO_EINT_DOWN)	{		matrix_row=3;		matrix_col = matrix_col_status;		goto scanend;	}scanend:	output_giop(0);	if(matrix_row >=0 )	{		snap_keyboard_code[matrix_row][matrix_col_status]= snap_keyboard_code[matrix_row][matrix_col_status] + 1;		if(snap_keyboard_code[matrix_row][matrix_col]>=DETECTION_THROLD)		{			*x=matrix_row;			*y=matrix_col;			curr_keyboard_code = keyboard_code_map[matrix_row][matrix_col];			return KEY_DOWN;		}	}	return NO_KEY_DOWN;}/*----------------------------------------------------*  func:  判断本次按键是否与上次按键相同*  param: *        *  return: *           0: 相同*           1: 不同------------------------------------------------------*/static inline int key_changed(){		return (pre_keyboard_code == curr_keyboard_code)? 0 : 1;}/*----------------------------------------------------*  func:  将按键对应的键盘码保存到循环队列中*  param: *        keyValue: 按键的对应的键盘码*  return: *                   ------------------------------------------------------*/static inline void save_key_to_queue(u_short keyValue){	if (kbdev.keyStatus == KEY_DOWN)	{		BUF_HEAD = keyValue;		INCBUF(kbdev.head);		//wake_up_interruptible(&(kbdev.wq));	}}/*----------------------------------------------------*  func:  重复按键定时器处理程序,如果一直按住某键,          则将该键的键盘码定时存到循环队列中*  param: *        data: 无参数*  return: *                   ------------------------------------------------------*/static inline void repeat_timer_handler(unsigned long data){	spin_lock_irq(&(repeat_lock));	if(kbdev.keyStatus ==KEY_DOWN)	{		repeat_timer.expires = jiffies + REPEAT_DELAY;//设置自动重复延时		add_timer(&repeat_timer);//将定时器加入队列		if(pre_keyboard_code != 0)		{			//printk("repeat save keyvalue\n   %d",pre_keyboard_code);			save_key_to_queue(pre_keyboard_code);//将按键值存入循环队列		}	}	else//如果按键弹起	{		//del_timer(&repeat_timer);	//	printk("del repeat timer\n");	}	spin_unlock_irq(&(repeat_lock));}/*----------------------------------------------------*  func:  使能中断*  param: *  return: *                   ------------------------------------------------------*///使能中断static inline void enableIrq(){	//清除SRCPND寄存器中eint1 eint2 eint8相应位	SRCPND = 0x0000002A;	//使能中断	enable_irq(IRQ_EINT1);	enable_irq(IRQ_EINT3);	enable_irq(IRQ_EINT8);}/*----------------------------------------------------*  func:  键盘定时扫描程序,如果得到稳定键码,将键码存*		  入循环队列;如果没有,则延时20ms后继续扫描*  param: *        data: 无参数*  return: *                   ------------------------------------------------------*/static inline void kb_timer_handler(unsigned long data){	int x,y;	spin_lock_irq(&(kbdev.lock));	x = y = 0;			if(scan_keyboard(&x,&y) == KEY_DOWN)	{	//	printk("snap_keyboard_code=%d, %d, %d, %d\n", snap_keyboard_code[0][1],snap_keyboard_code[1][1],snap_keyboard_code[2][1],snap_keyboard_code[3][1]);		kbdev.keyStatus =KEY_DOWN;

⌨️ 快捷键说明

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