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

📄 s3c2410-kbd-final.c

📁 基于arm-s3c2410 按键驱动程序 基于arm-s3c2410 按键驱动程序
💻 C
字号:
//============================================================================////  File Name: s3c2410-kbd.c////////  (c) Copyright 05.08.2008 minghe. All rights reserved////////  This source code is xxx. proprietary and confidential////  information////////  Description:////      keyboard driver for s3c2410 base on kernel 2.6////////  Modification History:////============================================================================#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/devfs_fs_kernel.h>#include <asm/hardware.h>#include <asm/delay.h>#include <asm/uaccess.h>#include <asm/arch-s3c2410/regs-gpio.h>#include <linux/poll.h>#include <asm/io.h>#include <asm-arm/arch-s3c2410/irqs.h>#include <asm-arm/irq.h>#include <linux/interrupt.h>#include <linux/wait.h>#include <linux/timer.h>#define DEVICE_NAME "s3c2410-kbd"#define kbd_major 233#define KBDRAW_MINOR 0#define MAX_KBD_BUF 16#define BUF_HEAD (kbddev.buf[kbddev.head])#define BUF_TAIL (kbddev.buf[kbddev.tail])#define INCBUF(x, mod) ((++(x))&((mod) - 1))#define KBD_TIMER_DELAY (HZ/10)#define KBD_TIMER_DELAY1 (HZ/100)//#define key1_irq IRQ_EINT0//#define key2_irq IRQ_EINT13//#define key3_irq IRQ_EINT11//#define key4_irq IRQ_EINT19//#define key1 s3c2410_gpio_getpin(S3C2410_GPF0)//#define key2 s3c2410_gpio_getpin(S3C2410_GPG5)#define KEYSTATUS_DOWNX 1#define KEYSTATUS_DOWN 2#define KEYSTATUS_UP 3#define KEY_DOWN 128 #define rows 4#define columns 2//#define CONFIG_DEVFS_FS#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK( fmt, args... )	printk(DEVICE_NAME ": %s() %d " fmt, __FUNCTION__, __LINE__, ## args)#else#define DPRINTK( x... )#endiftypedef unsigned char KBD_RET;typedef struct{	unsigned int kbdStatus;	KBD_RET buf[MAX_KBD_BUF];	unsigned int head, tail;	wait_queue_head_t wq;} KBD_DEV;static KBD_DEV kbddev;static struct timer_list kbd_timer;static int key;static int cs[] = {S3C2410_GPB6, S3C2410_GPB7};static int rs[] = {S3C2410_GPF0, S3C2410_GPG5, S3C2410_GPG3, S3C2410_GPG11};static int key_irq[] = {IRQ_EINT0, IRQ_EINT13, IRQ_EINT11, IRQ_EINT19};static int rp_mod[] = {S3C2410_GPF0_EINT0, S3C2410_GPG5_EINT13, S3C2410_GPG3_EINT11,  S3C2410_GPG11_EINT19};static int cp_mod[] = {S3C2410_GPB6_OUTP, S3C2410_GPB7_OUTP};//static int kbd_major = 0;//static int key_irq;static void (*kbdEvent)(void);void kbdEvent_dummy(void){};static int ISKBD_DOWN(void){	int i, j, key_down_flag = 0;	//int *cp, *rp;	//cp = cs;	//rp = rs;	for (i = 0; i < columns; i++)	{		for (j = 0; j < columns; j++)		{			if (j == i)				s3c2410_gpio_setpin(cs[j], 0);			else s3c2410_gpio_setpin(cs[j], 1);		}		for (j = 0; j < rows; j++)		{			if (!s3c2410_gpio_getpin(rs[j]))			{				key_down_flag = 1;				break;			}		}		if (key_down_flag) break;	}	for (j = 0; j < columns; j++)		s3c2410_gpio_setpin(cs[j], 0);	return key_down_flag;}static void KBD_CLOSE_INT(void){	int i;	for (i = 0; i < rows; i++)		disable_irq(key_irq[i]);// 	disable_irq(key1_irq);// 	disable_irq(key2_irq);// 	disable_irq(key3_irq);// 	disable_irq(key4_irq);}static void KBD_OPEN_INT(void){	int i;	for (i = 0; i < rows; i++)		enable_irq(key_irq[i]);// 	enable_irq(key1_irq);// 	enable_irq(key2_irq);// 	enable_irq(key3_irq);// 	enable_irq(key4_irq);}static irqreturn_t s3c2410_isr_kbd(int irq, void *dev_id, struct pt_regs *reg){	DPRINTK("Occured key board Interrupt, irq = %d\n",irq);		if ((kbddev.kbdStatus == KEYSTATUS_UP))	{		KBD_CLOSE_INT();		DPRINTK("Interrupt have been closed\n");		if (ISKBD_DOWN())		{			kbddev.kbdStatus = KEYSTATUS_DOWNX;			DPRINTK("KEYSTATUS is KEYSTATUS_DOWNX\n");			kbd_timer.expires = jiffies + KBD_TIMER_DELAY1;			add_timer(&kbd_timer);		}		else		{			KBD_OPEN_INT();			DPRINTK("Interrupt have been opened\n");		}	}	return irq;}static void kbdEvent_raw(void){	if (kbddev.kbdStatus == KEYSTATUS_DOWN)	{		BUF_HEAD = (key | KEY_DOWN);	}	else	{		BUF_HEAD = key;	}	DPRINTK("BUF_HEAD = %d\n", BUF_HEAD);	kbddev.head = INCBUF(kbddev.head, MAX_KBD_BUF);	wake_up_interruptible(&(kbddev.wq));	DPRINTK("BUF_HEAD = %d\n", BUF_HEAD);}static int Read_ExINT_Key(void){	int i, j;	int key_down_flag = 0;	int key_value;	int row = 0, col = 0;	//int *cp, *rp;	//cp = cs;	//rp = rs;	for (i = 0; i < columns; i++)	{		for (j = 0; j < columns; j++)		{			if (j == i)				s3c2410_gpio_setpin(cs[j], 0);			else s3c2410_gpio_setpin(cs[j], 1);		}		for (j = 0; j < rows; j++)		{			if (!s3c2410_gpio_getpin(rs[j])) 			{				row = j;				key_down_flag = 1;				break;			}		}		if (key_down_flag) 		{			col = i;			break;		}	}	key_value = row*columns + col + 1;	for (j = 0; j < columns; j++)		s3c2410_gpio_setpin(cs[j], 0);	return key_value;}static void s3c2410_get_kbd(void){	key = Read_ExINT_Key();	DPRINTK("key = %d\n", key); 	//kbdEvent = kbdEvent_raw;	kbdEvent();}static void kbd_timer_handler(unsigned long data){	if (ISKBD_DOWN())	{		if (kbddev.kbdStatus == KEYSTATUS_DOWNX)		{			kbddev.kbdStatus = KEYSTATUS_DOWN;			DPRINTK("KEYSTATUS is KEYSTATUS_DOWN\n");			kbd_timer.expires = jiffies + KBD_TIMER_DELAY;			s3c2410_get_kbd();		}		else		{			kbd_timer.expires = jiffies + KBD_TIMER_DELAY;		}		add_timer(&kbd_timer);	}	else	{		kbddev.kbdStatus = KEYSTATUS_UP;		del_timer(&kbd_timer);		DPRINTK("KEY UP, code = %d\n",key);		kbdEvent();		KBD_OPEN_INT();	}}static KBD_RET kbdRead(void){	KBD_RET kbd_ret;	kbd_ret = BUF_TAIL;		kbddev.tail = INCBUF(kbddev.tail, MAX_KBD_BUF);	return kbd_ret;} static ssize_t s3c2410_kbd_read(struct file *filp, char * buffer, size_t count, loff_t *ppos){	KBD_RET kbd_ret;	retry:		if (kbddev.head != kbddev.tail)		{			DPRINTK("BUF_TAIL = %d\n", BUF_TAIL);			kbd_ret = kbdRead();			DPRINTK("BUF_TAIL = %d\n", BUF_TAIL);			copy_to_user(buffer, (char *)&kbd_ret, sizeof(KBD_RET));			return sizeof(KBD_RET);		}		else		{			if (filp -> f_flags & O_NONBLOCK)			{				DPRINTK("mod is nonblock\n");				return -EAGAIN;			}			DPRINTK("wait_queue has slept\n");			wait_event_interruptible(kbddev.wq, (kbddev.head != kbddev.tail));			DPRINTK("wait_queue is waked\n");			if (signal_pending(current))				return -ERESTARTSYS;			goto retry;		}	return sizeof(KBD_RET);}static int s3c2410_kbd_open(struct inode *inode, struct file *filp){	kbddev.head = kbddev.tail = 0;	kbdEvent = kbdEvent_raw;	DPRINTK("cdev is opened\n");	return 0;}static int s3c2410_kbd_release(struct inode *inode, struct file *filp){	kbdEvent =kbdEvent_dummy;	return 0;}unsigned int s3c2410_kbd_poll(struct file *filp, struct poll_table_struct *wait){    unsigned int mask = 0;    poll_wait(filp, &kbddev.wq, wait);    if(kbddev.head != kbddev.tail) {        mask |= POLLIN | POLLRDNORM;        DPRINTK("poll: data ready\n");    }   return mask;}static struct file_operations s3c2410_fops = {	.owner = THIS_MODULE,	.open = s3c2410_kbd_open,	.read = s3c2410_kbd_read,	.release = s3c2410_kbd_release,	.poll = s3c2410_kbd_poll,};static int __init s3c2410_kbd_init(void){	int ret;	int i;	for (i = 0; i < rows; i++)	{		set_irq_type(key_irq[i], IRQT_FALLING);		s3c2410_gpio_cfgpin(rs[i], rp_mod[i]);		s3c2410_gpio_pullup(rs[i], 1);	}// 	set_irq_type(key1_irq, IRQT_FALLING);// 	set_irq_type(key2_irq, IRQT_FALLING);// 	set_irq_type(key3_irq, IRQT_FALLING);// 	set_irq_type(key4_irq, IRQT_FALLING);	// 	s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0);// 	s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPG5_EINT13);// 	s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11);// 	s3c2410_gpio_cfgpin(S3C2410_GPG11, S3C2410_GPG11_EINT19);// 	s3c2410_gpio_pullup(S3C2410_GPF0, 1);// 	s3c2410_gpio_pullup(S3C2410_GPG5, 1);// 	s3c2410_gpio_pullup(S3C2410_GPG3, 1);// 	s3c2410_gpio_pullup(S3C2410_GPG11, 1);	kbdEvent = kbdEvent_dummy;		ret = register_chrdev(kbd_major, DEVICE_NAME, &s3c2410_fops);	if (ret < 0) {		DPRINTK(DEVICE_NAME " can't get major number\n");		return ret;	}	//kbd_major = ret;	//#ifdef CONFIG_DEVFS_FS	ret = devfs_mk_cdev(MKDEV(kbd_major, KBDRAW_MINOR), 			      S_IFCHR | S_IRUSR | S_IWUSR, "keyboard");	if (ret < 0)	{		DPRINTK(DEVICE_NAME " can't make char device");		return ret;	}	//#endif	for (i = 0; i < rows; i++)	{		ret = request_irq(key_irq[i], s3c2410_isr_kbd, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_kbd);		if (ret < 0)		{			DPRINTK(DEVICE_NAME " can't request key%d_irq\n", i + 1);			return ret;		}	}// 	ret = request_irq(key1_irq, s3c2410_isr_kbd, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_kbd);// 	if (ret < 0) // 	{// 		DPRINTK(DEVICE_NAME " can't request key1_irq\n");// 		return ret;// 	}// // 	ret = request_irq(key2_irq, s3c2410_isr_kbd, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_kbd);// 	if (ret < 0) // 	{// 		DPRINTK(DEVICE_NAME " can't request key2_irq\n");// 		return ret;// 	}// // 	ret = request_irq(key3_irq, s3c2410_isr_kbd, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_kbd);// 	if (ret < 0) // 	{// 		DPRINTK(DEVICE_NAME " can't request key2_irq\n");// 		return ret;// 	}// // 	ret = request_irq(key4_irq, s3c2410_isr_kbd, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_kbd);// 	if (ret < 0) // 	{// 		DPRINTK(DEVICE_NAME " can't request key4_irq\n");// 		return ret;// 	}	for (i = 0; i < columns; i++)	{		s3c2410_gpio_cfgpin(cs[i], cp_mod[i]);		s3c2410_gpio_setpin(cs[i], 0);	}// 	s3c2410_gpio_cfgpin(S3C2410_GPB6, S3C2410_GPB6_OUTP);// 	s3c2410_gpio_cfgpin(S3C2410_GPB7, S3C2410_GPB7_OUTP);// 	s3c2410_gpio_setpin(S3C2410_GPB6, 0);// 	s3c2410_gpio_setpin(S3C2410_GPB7, 0);	kbddev.head = kbddev.tail = 0;	kbddev.kbdStatus = KEYSTATUS_UP;	init_waitqueue_head(&(kbddev.wq));	init_timer(&kbd_timer);	kbd_timer.function = kbd_timer_handler;#ifdef DEBUG	s3c2410_kbd_open(NULL, NULL);#endif	printk(DEVICE_NAME " initialized\n");	return 0;}static void __exit s3c2410_kbd_exit(void){#ifdef CONFIG_DEVFS_FS	int i;	for (i = 0; i < rows; i++)		free_irq(key_irq[i], s3c2410_isr_kbd);// 	free_irq(key1_irq, s3c2410_isr_kbd);// 	free_irq(key2_irq, s3c2410_isr_kbd);// 	free_irq(key3_irq, s3c2410_isr_kbd);// 	free_irq(key4_irq, s3c2410_isr_kbd);	unregister_chrdev(kbd_major, "keyboard");	unregister_chrdev(kbd_major,DEVICE_NAME);	devfs_remove( "keyboard" );#endif}module_init(s3c2410_kbd_init);module_exit(s3c2410_kbd_exit);	MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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