📄 key.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 + -