#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include<linux/config.h>
#include<linux/module.h>
#include<linux/version.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/errno.h>
#include<linux/sched.h>//声明中断
#include<linux/fs.h>//声明file文件
#include<asm/system.h>/*cli(),*_flages*/
#include<linux/poll.h>
#include<linux/types.h>
#include<linux/slab.h>
#include <asm/arch/S3C2410.h>
#include <asm/hardware.h>//devf
//-------------------------------
#include <asm/io.h>/* ioremap */
#include <linux/delay.h>
#include <asm/delay.h>
//--------------------------------
#include <asm-arm/arch-s3c2410/smdk.h>
#include <linux/ioport.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
//define the interrupt No.
#define interrupt_k4 IRQ_EINT0
#define interrupt_k3 IRQ_EINT2
#define interrupt_k2 IRQ_EINT11
#define interrupt_k1 IRQ_EINT19
/*
struct IRQ_STRUCT
{
unsigned int irq_no;
void (*irq_fun)();
};
static IRQ_STRUCT irq_struct[4];
*/
//定义键盘的主设备号define the major of keypad
#define KEYPAD_MAJOR 59
#ifndef MOD_INC_USE_COUNT
#define MOD_INC_USE_COUNT
#endif
#ifndef MOD_DEC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif
#define COMMAND1 1
#define KBD_GETKEY 1
static int keyvalue;
#define DEVICE_NAME "keypad"
//setup the GPIO F ports register
#define key_rGPFCON (*(volatile unsigned long *) key_r_GPFCON)
#define key_rGPFUP (*(volatile unsigned long *) key_r_GPFUP)
#define key_rGPFDAT (*(volatile unsigned long *) key_r_GPFDAT)
//setup the GPIO G ports register
#define key_rGPGCON (*(volatile unsigned long *) key_r_GPGCON)
#define key_rGPGUP (*(volatile unsigned long *) key_r_GPGUP)
#define key_rGPGDAT (*(volatile unsigned long *) key_r_GPGDAT)
unsigned long *key_r_GPFCON, *key_r_GPFDAT, *key_r_GPFUP;
unsigned long *key_r_GPGCON, *key_r_GPGDAT, *key_r_GPGUP;
static int __init keypad_init(void);
static void __exit keypad_cleanup(void);
static void key1_irq(int irq,void *dev_id,struct pt_regs *regs);
static void key2_irq(int irq,void *dev_id,struct pt_regs *regs);
static void key3_irq(int irq,void *dev_id,struct pt_regs *regs);
static void key4_irq(int irq,void *dev_id,struct pt_regs *regs);
static int keypad_getkey(void);
static int keypad_open(struct inode *inode,struct file *file);
static int keypad_close(struct inode *inode,struct file *file);
static int keypad_ioctl(struct inode *inode ,struct file* file,unsigned int cmd,unsigned long arg);
void keypad_setup(void);
/********************************************************************/
static devfs_handle_t devfs_handle;
static struct file_operations keypad_fops=
{
owner:THIS_MODULE,
llseek:NULL,
read: NULL,
write: NULL,
ioctl: keypad_ioctl,
open: keypad_open,
release: keypad_close,
};
/********************************************************************/
void keypad_setup(void)
{
keyvalue = 0;
}
static int keypad_open(struct inode * inode,struct file *file)
{
printk(KERN_CRIT"DEMO:Keypad Device Open /n");
MOD_INC_USE_COUNT;
return 0;
}
static int keypad_close(struct inode * inode,struct file *file)
{
printk(KERN_CRIT"DEMO:Keypad device close/n");
MOD_DEC_USE_COUNT;
return 0;
}
static int keypad_ioctl(struct inode *inode ,struct file* file,unsigned int cmd,unsigned long arg)
{
int value=0;
switch(cmd)
{//接受一个按键
case KBD_GETKEY:
value = keypad_getkey();
if(value!=0)
keyvalue=0;
return value;
}
}
static void key1_irq(int irq,void *dev_id,struct pt_regs *regs)
{
//屏蔽键盘中断
disable_irq(irq);
printk("Key1 Interrupt ok/n");
keyvalue=1;
enable_irq(irq);
}
static void key2_irq(int irq,void *dev_id,struct pt_regs *regs)
{
//屏蔽键盘中断
disable_irq(irq);
printk("Key2 Interrupt ok/n");
keyvalue=2;
enable_irq(irq);
}
static void key3_irq(int irq,void *dev_id,struct pt_regs *regs)
{
//屏蔽键盘中断
disable_irq(irq);
printk("Key3 Interrupt ok/n");
keyvalue=3;
enable_irq(irq);
}
static void key4_irq(int irq,void *dev_id,struct pt_regs *regs)
{
//屏蔽键盘中断
disable_irq(irq);
printk("Key4 Interrupt ok/n");
keyvalue=4;
enable_irq(irq);
}
static int keypad_getkey()
{
//如果有键按下,则反回键值
if (keyvalue)
{
return keyvalue;
}
//printk("Waiting......./n");
//无键按下,返回0
return 0;
}
static int __init keypad_init(void)
{
int result;
//int i;
//setup the F_PORT register
key_r_GPFCON =ioremap(0x56000050,4);
key_r_GPFDAT =ioremap(0x56000054,4);
key_r_GPFUP =ioremap(0x56000058,4);
key_rGPFUP =0xff;
key_rGPFCON = 0xffee;
//setup the G_PORT register
key_r_GPGCON = ioremap(0x56000060,4);
key_r_GPGDAT = ioremap(0x56000064,4);
key_r_GPGUP = ioremap(0x56000068,4);
key_rGPGUP = 0xffff;
key_rGPFCON = 0xffbfffbf;
/*
irq_struct[0].irq_no=interrupt_k1;
irq_struct[0].irq_fun=key1_irq;
irq_struct[1].irq_no=interrupt_k2;
irq_struct[1].irq_fun=key2_irq;
irq_struct[2].irq_no=interrupt_k3;
irq_struct[2].irq_fun=key3_irq;
irq_struct[3].irq_no=interrupt_k4;
irq_struct[3].irq_fun=key4_irq;
*/
devfs_handle = devfs_register(NULL,DEVICE_NAME, DEVFS_FL_DEFAULT,KEYPAD_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR,&keypad_fops, NULL);
result = register_chrdev(KEYPAD_MAJOR,DEVICE_NAME,&keypad_fops);
if(result<0)
{
printk(KERN_INFO "[FAILED:Cannot register keypad Device!]/n");
return -EIO;
}
else
printk("Initializing Keypad Device/t---->/t/n");
keypad_setup();
//register the external interrupt
//for(i=0;i<4;i++)
//{
set_external_irq(interrupt_k1, EXT_FALLING_EDGE, GPIO_PULLUP_EN);
result=request_irq(interrupt_k1,&key1_irq,SA_INTERRUPT,DEVICE_NAME,&key1_irq);
if (result<0)
{
printk(KERN_INFO"[FAILED:Cannot registe key1 interrupt!]/n");
return result;
}
else
printk("[key 1 has been registed!]/n");
set_external_irq(interrupt_k2, EXT_FALLING_EDGE, GPIO_PULLUP_EN);
result=request_irq(interrupt_k2,&key2_irq,SA_INTERRUPT,DEVICE_NAME,&key2_irq);
if (result<0)
{
printk(KERN_INFO"[FAILED:Cannot registe key2 interrupt!]/n");
return result;
}
else
printk("[key 2 has been registed!]/n");
set_external_irq(interrupt_k3, EXT_FALLING_EDGE, GPIO_PULLUP_EN);
result=request_irq(interrupt_k3,&key3_irq,SA_INTERRUPT,DEVICE_NAME,&key3_irq);
if (result<0)
{
printk(KERN_INFO"[FAILED:Cannot registe key3 interrupt!]/n");
return result;
}
else
printk("[key 3 has been registed!]/n");
set_external_irq(interrupt_k4, EXT_FALLING_EDGE, GPIO_PULLUP_EN);
result=request_irq(interrupt_k4,&key4_irq,SA_INTERRUPT,DEVICE_NAME,&key4_irq);
if (result<0)
{
printk(KERN_INFO"[FAILED:Cannot registe key4 interrupt!]/n");
return result;
}
else
printk("[key 4 has been registed!]/n");
//}
printk("Keypad Driver has been installed!/n");
return 0;
}
static void __exit keypad_cleanup(void)
{
//int i;
//for(i=0;i<4;i++)
devfs_unregister(devfs_handle);
unregister_chrdev(KEYPAD_MAJOR,DEVICE_NAME);
free_irq(interrupt_k1,key1_irq);
free_irq(interrupt_k2,key2_irq);
free_irq(interrupt_k3,key3_irq);
free_irq(interrupt_k4,key4_irq);
printk("DEMO:Keypad device is cleanup/n");
return ;
}
/********************************************************************/
#ifdef MODULE
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zhu jacky<jianqi.zhu@gmail.com >");
MODULE_DESCRIPTION("Keypad Device");
#endif
module_init(keypad_init);
module_exit(keypad_cleanup);
/*
linux在io.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地址映射到核心虚地址空间(3GB-4GB)中,如下:
void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
void iounmap(void * addr);函数用于取消ioremap()所做的映射,参数addr是指向核心虚地址的指针。
这两个函数都是实现在mm/ioremap.c文件中。
*/