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

📄 key.c

📁 Linux s3c2410键盘驱动源码
💻 C
字号:
#define	__KERNEL__
#define	MODULE


/////////////////////////////////////////////////////////////////////////////
#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/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/malloc.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 <linux/devfs_fs_kernel.h>
#include "mx1_def.h"
#include "key.h"


void delay(void);
int key_open(struct inode * inode, struct file * filp);
int key_release(struct inode * inode, struct file * filp);
unsigned int key_poll(struct file * filp, struct poll_table_struct * wait);
int init_key(void);
static void pc_irq_handle(int irq, void *dev_id, struct pt_regs *regs);
void cleanup_key(void);
ssize_t key_read(struct file * filp, char * buf, size_t count, loff_t * l);

char *dev_id="KeyBoardIrq";
#define	V_ADDRESS(x)	(*((volatile unsigned long* )(0xF0000000|x)))

unsigned char  key_val=0xff;
wait_queue_head_t 	ts_wait;

char keymap[4][4] ={
			{'1','2','3','a'},
			{'4','5','6','b'},
			{'7','8','9','c'},
			{'*','0','#','d'},
		    };

struct file_operations key_fops = {
	open:           key_open,
	release:        key_release,
	read:           key_read,
	poll:           key_poll,
	};


int key_open(struct inode * inode, struct file * filp)
{
	//       enable_irq(12);
	MOD_INC_USE_COUNT;
	return 0;
}

/******************************************************************************
* Function Name: key_release
*
* Input: 		inode	:
* 			filp	:
* Value Returned:	int	: Return status.If no error, return 0.
*
* Description: release resource when close the inode
*
* Modification History:
* 	wang kuo
*****************************************************************************/
int key_release(struct inode * inode,
struct file * filp)
{
	//    disable_irq(12);
	MOD_DEC_USE_COUNT;
	return 0;
}

ssize_t key_read(struct file * filp, char * buf, size_t count, loff_t * l)
{
	copy_to_user(buf, &key_val, 1);
	key_val = 0xff;
	return 0;
}

unsigned int key_poll(struct file * filp, struct poll_table_struct * wait)
{
	poll_wait(filp,&ts_wait,wait);

	if (key_val != 0xff)
	return POLLIN |POLLRDNORM;
	else
	return 0;
}
static void pc_irq_handle(int irq, void *dev_id, struct pt_regs *regs)
{

	unsigned long status_isr=0;
	unsigned int row=5, col=5;

	if(!(V_ADDRESS(PTC_ISR) & 0xf0000000))	
		return;
	// Disable Interruption
	V_ADDRESS(PTC_IMR)  &=~ 0xf0000000;
	status_isr=V_ADDRESS(PTC_ISR)>>28;
	if(!status_isr)
			return;
	for(col=0;col<4;col++)
	{
		if( status_isr == (1 << col) )
			break;
	}
	V_ADDRESS(PTC_ISR)  |= 0xf0000000;
	
	/////////////////////////////////////////////////////////////////////////
	mdelay(100);
	if(V_ADDRESS(PTC_SSR) >= 0xf0000000)
	{
		V_ADDRESS(PTC_DR)   &=~0xa300000;
                V_ADDRESS(PTC_IMR)  |= 0xf0000000;
                return;
	}

	V_ADDRESS(PTC_DR)   &=~0xa300000;
	V_ADDRESS(PTC_DR) |=0x100000;
	mdelay(100);
	if( V_ADDRESS(PTC_SSR) & (0x10000000 << col))
	{
		row=0;
		goto evt;
	}	

	V_ADDRESS(PTC_DR)   &=~0xa300000;
	V_ADDRESS(PTC_DR)   |=0x2000000;
	mdelay(100);
	if(  V_ADDRESS(PTC_SSR) & (0x10000000 << col))
	{
		row=1;
		goto evt;
	}
		
	V_ADDRESS(PTC_DR)   &=~0xa300000;
	V_ADDRESS(PTC_DR)   |=0x200000;
	mdelay(100);
	if( V_ADDRESS(PTC_SSR) & (0x10000000 << col))
	{
		row=2;
		goto evt;
	}

	V_ADDRESS(PTC_DR)   &=~0xa300000;
	V_ADDRESS(PTC_DR)   |=0x8000000;
	mdelay(100);
	if( V_ADDRESS(PTC_SSR) & (0x10000000 << col))
	{
		row=3;
		goto evt;
	}
	else
	{	
        	V_ADDRESS(PTC_DR)   &=~0xa300000;
	        V_ADDRESS(PTC_IMR)  |= 0xf0000000;
		return;
	}
evt:	key_val = keymap[row][col];
	///////////////////////////////////////////////////////////////////////////////
	//    restore_flags(flags);
	V_ADDRESS(PTC_DR)   &=~0xa300000;
	mdelay(100);
	V_ADDRESS(PTC_IMR)  |= 0xf0000000;
	wake_up_interruptible(&ts_wait);
}
void delay(void)
{
	unsigned long i= 1<<12;
	
	for(;i>0;i--){};
}



//////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef MODULE
int init_module(void)
#else
int __init init_key(void)
#endif
{
	unsigned int result = 0;
	init_waitqueue_head(&ts_wait);

	// pc 20 21 25 27 output 0
	
	V_ADDRESS(PTC_GIUS) |= 0xa300000;
	V_ADDRESS(PTC_DDIR) |= 0xa300000;
	V_ADDRESS(PTC_OCR2) |= 0xcc0f00;		
	V_ADDRESS(PTC_DR)   &=~0xa300000;
	


	// PC28~pc31 INTERRUPT

	V_ADDRESS(PTC_GIUS) |= 0xf0000000;		
	V_ADDRESS(PTC_DDIR) &=~0xf0000000;
	V_ADDRESS(PTC_ICR2) &=~0xff000000;
	V_ADDRESS(PTC_ICR2) |= 0x55000000;
	V_ADDRESS(PTC_ISR)  |= 0xf0000000;

	result = register_chrdev(250, "keyBoard", &key_fops);

	if (result < 0) {
		printk("<1>key_dev: can't get major number 250\n");
		unregister_chrdev(250,"keyBoard");
		return result;
	}
//	printk("<1>register_chrdev: %d\n", result);
	
	V_ADDRESS(PTC_IMR)  |= 0xf0000000;	// PC28~pc431

	result=request_irq(13,pc_irq_handle,SA_SHIRQ,"keyBoard", dev_id);
	enable_irq(13);
	
//	printk("<1> request_irq: %d\n", result);
	return 0;
}



#ifdef MODULE
void cleanup_module(void)
#else
void __exit cleanup_key(void)
#endif
{
	disable_irq(13);
	V_ADDRESS(PTC_IMR)  &=~ 0xf0000000;
	free_irq(13, dev_id);
	unregister_chrdev(250,"keyBoard");
}



#ifndef MODULE
module_init(init_key);
module_exit(cleanup_key);
#endif

⌨️ 快捷键说明

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