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

📄 key_struct_driver_waitq.c

📁 此代码为上传的源码为ARM9 s3c2410的键盘驱动,读者可编应用程序进行测试
💻 C
字号:
/************************************************************************
 *	创建日期:2007/12/21
 *	文件名称:key_irq.c
 *	文件作者:teacher liang
 *	文件功能描述:MATRIX4开发板上一共有16个按键,分别影射到GPF0、GPF2、
 *		      GPG3、GPG11, *	当按下按键时分别产生0、2、11、19号
 *		      外部中断。这个驱动十分简单,它仅仅是在按下了按键后打
 *		      印出一串消息。如果希望按下按键后做一些更有意义的事,
 *		      需要改写中断处理程序key_handler。 
 * **********************************************************************/

#include <linux/init.h>		// 模块初始化、清除函数的宏定义;
#include <linux/sched.h>	// 大部分内核API的定义;
#include <linux/module.h>	// 必须,
#include <linux/version.h>	// 内核版本
#include <linux/moduleparam.h>  // 模块参数
#include <linux/kernel.h>	// printk

#include <linux/types.h>	// dev_t定义;
#include <linux/fs.h>		// 文件系统头文件,必需;
#include <linux/cdev.h>		//struct cdev定义

#include <linux/interrupt.h>	//注册和注销函数等

#include <asm/signal.h>		//request_irq函数的标识
#include <asm/arch/irqs.h>   	//中断号
#include <asm/hardware.h>	//GPIO口操作函数
#include <asm/irq.h>		//disable_irq, set_irq_type等函数的声明
#include <asm/arch/regs-gpio.h>	//GPIO口定义
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/poll.h>

//#include "led_struct_driver.h"#define MATRIX4_KEYBOARD_NAME "matrix4_key"
void LedDisp(int led); /* function symbol from led driver(led_struct_driver.c)*/
static unsigned int key_major=0;
static unsigned int key_minor=0;

static unsigned int key_irq_munber[4]={IRQ_EINT19, IRQ_EINT11, IRQ_EINT2, IRQ_EINT0};
//static int eint[4] = {IRQ_EINT19, IRQ_EINT11, IRQ_EINT2, IRQ_EINT0};
static unsigned int ioport[4] = {S3C2410_GPG11, S3C2410_GPG3, S3C2410_GPF2, S3C2410_GPF0};
static unsigned int kscan[4] = {S3C2410_GPE11, S3C2410_GPG6, S3C2410_GPE13, S3C2410_GPG2};

static int ready = 0;static int key_value = 0;

static struct s3c2410_key {
	int irq_no;	unsigned int gpio_port;	unsigned int gpio_port_kscan;	int key_no;} s3c2410_key_tab[16] = {
	/*键盘第1列 k10 k7 k4 k1*/	{ IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE11, 1 },
	{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE11, 4 },
	{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE11, 7 },
	{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE11, 10 },
		/*键盘第2列 k11 k8 k5 k2*/	{ IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG6, 2 },
	{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG6, 5 },
	{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG6, 8 },
	{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG6, 11 },
		/*键盘第3列 k12 k9 k5 k3*/	{ IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE13, 3 },
	{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE13, 6 },
	{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE13, 9 },
	{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE13, 12 },
		/*键盘第4列 k16 k15 k14 k13*/	{ IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG2, 13 },
	{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG2, 14 },
	{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG2, 15 },
	{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG2, 16 },
};

//定义与绑定tasklet函数void key_tasklet_action(unsigned long t);
DECLARE_TASKLET(key_tasklet, key_tasklet_action, 0);
void key_tasklet_action(unsigned long t)
{	printk("<1>led action\n");
	LedDisp((int)t);	printk("<1> the key value is : %d \n",key_value);
}

/*初始化按键的等待队列*/static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);

static int matrix4_gpio_setup(void)
{	s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);
	s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);
	s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);
	s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);
	s3c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);
}/* 设置GPIO口为输入状态 */static void buttons_port_reset(void){	//int i;	s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_INP);
	s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_INP);
	s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);
	s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_INP);

	//s3c2410_gpio_setpin(S3C2410_GPF0,1);

}

/* 设置单个kscan口为输出0 */static void buttons_kscan_reset(int column){	int i;	for(i=0; i < sizeof kscan / sizeof kscan[1]; i++) {		if(i == column)			s3c2410_gpio_setpin(kscan[i], 0);
		else			s3c2410_gpio_setpin(kscan[i], 1);
	}}
/* 初始化kscan口为输出0 */static void buttons_io_port_init(void){	int i;	s3c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);	
	for(i=0; i < sizeof kscan / sizeof kscan[1]; i++) {		//set_gpio_ctrl(kscan[i] | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
		//write_gpio_bit(, 0);
		//s3c2410_gpio_cfgpin(kscan[i], );
		s3c2410_gpio_setpin(kscan[i],0);	}}/* 重新设置中断 */static void buttons_int_reset(void){/*
	int i;
	for(i=0; i < sizeof eint / sizeof eint[1]; i++) {		set_external_irq(eint[i], EXT_FALLING_EDGE, GPIO_PULLUP_DIS);	}
*/
	s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);
	s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);
	s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);
	s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);
	
}

static irqreturn_t buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
{	struct s3c2410_key *k;	int i, j;	int found = 0;	int up = -1;	int column = 0;	int row = 0;		buttons_port_reset();    /* 设置GPIO为输入状态 */		mdelay(10); /*延时10000us*/
	/* 键盘扫描 */	for ( j = 0; j < sizeof kscan / sizeof kscan[1]; j++) {		buttons_kscan_reset(j);		column = j;		for ( i = 0; i < sizeof key_irq_munber / sizeof key_irq_munber[1]; i++) {
			if(key_irq_munber[i] == irq) {
				row = i;			//	up = read_gpio_bit(ioport[i]);
				up = s3c2410_gpio_getpin(ioport[i]);
				break;			}		}		if(up == 0) {			found = 1;			break;		}	}	mdelay(10);                              /* 延时去抖 */
		if (found) {		k = s3c2410_key_tab + column * 4 + row;
		if (up) {			key_value = k->key_no + 0x80;//		} else {			key_value = k->key_no;		}	}		ready = 1;	wake_up_interruptible(&buttons_wait);
	//调度tasklet执行
	key_tasklet.data = row+1;
	tasklet_schedule(&key_tasklet);
	buttons_io_port_init();     /* 重新设置GPIO为输出 */	buttons_int_reset();        /* 重新设置中断 */

	return 0;
}
/*static void key_handler(int irq,void *dev_id,struct pt_regs *regs)
{
	disable_irq(irq);
	printk("<1>the irq is %d \n",(irq-16));
	enable_irq(irq);
	return 0;
}*/static int matrix4_buttons_open(struct inode *inode,struct file *filp)
{	
	printk("<1>matrix4_keyboard_open \n");
	return 0;
}

static int matrix4_buttons_release(struct inode *inode,struct file *filp)
{
	return 0;
}

static int matrix4_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos){	static int key;//	int flags;	int repeat;		if (!ready)		return -EAGAIN;			if (count != sizeof key_value)		return -EINVAL;			//save_flags(flags); 		if (key != key_value) {		key = key_value;		repeat = 0;	} else {		repeat = 1;	}		//restore_flags(flags);		/*if (repeat) {		return -EAGAIN;	}*/		copy_to_user(buffer, &key, sizeof key);	ready = 0;		return sizeof key_value;}static unsigned int matrix4_buttons_select(struct file *filp, struct poll_table_struct *wait)
{	if (ready)		return 1;			poll_wait(filp, &buttons_wait, wait); 
	//通过调用函数 poll_wait,增加buttons_wait等待队列到poll_table 结构。		return 0;}static int matrix4_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	switch(cmd) {	default:		return -EINVAL;	}}static struct file_operations matrix4_buttons_fops = {	.owner = THIS_MODULE,
	.open = matrix4_buttons_open,
	.release = matrix4_buttons_release,
	.ioctl = matrix4_buttons_ioctl,
	.poll =  matrix4_buttons_select,
	.read = matrix4_buttons_read,
};


/*
static struct file_operations key_fops={
	.owner = THIS_MODULE,
	.open	= matrix4_keyboard_open,
	.release = matrix4_keyboard_release,
};
*/

static dev_t dev;
static struct cdev *key_cdev;

static int matrix4_buttons_init(void)
{
	int i;
	int result;	if(key_major)
	{
		dev=MKDEV(key_major,key_minor);
		result=register_chrdev_region(dev,1,MATRIX4_KEYBOARD_NAME);
	}
	else 
	{
		result=alloc_chrdev_region(&dev,key_minor,1,MATRIX4_KEYBOARD_NAME);
		key_major=MAJOR(dev);
	}
	if(result<0)
	{
		printk("<1>MATRIX4 keyboard device cannot get key_major!\n");
		return -1;
	}

	key_cdev=cdev_alloc();
	cdev_init(key_cdev,&matrix4_buttons_fops);
	key_cdev->owner=THIS_MODULE;
//	key_cdev->ops=&key_fops;

	/* 注册中断 */
	matrix4_gpio_setup();
	for(i=0;i<4;i++)
	{
		if(request_irq(key_irq_munber[i],buttons_irq,SA_INTERRUPT,MATRIX4_KEYBOARD_NAME,NULL)){
			printk("<1>Error : cannot register irq %d \n",key_irq_munber[i]);
			return -1;
		}
		set_irq_type(key_irq_munber[i],IRQT_FALLING);
	}

	result=cdev_add(key_cdev,dev,1);
	if(result){
		printk("<1>Error: while register keyboard device !\n");
		return -1;
	}	return 0;}

static void matrix4_buttons_exit(void)
{
	int i;
	unregister_chrdev_region(dev,1);
	cdev_del(key_cdev);
	for(i=0;i<4;i++)
		free_irq(key_irq_munber[i],buttons_irq);
}

module_init(matrix4_buttons_init);
module_exit(matrix4_buttons_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("");
MODULE_DESCRIPTION("MATRIX4 keyboard driver!");

⌨️ 快捷键说明

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