返回信息流#include<linux/module.h>
#include<linux/init.h>
#include<linux/config.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/interrupt.h>
#include<linux/wait.h>
#include<linux/cdev.h>
#include<linux/sched.h>
#include<linux/devfs_fs_kernel.h>
#include<asm/hardware.h>
#include<asm/delay.h>
#include<asm/uaccess.h>
#include<asm/io.h>
#include<asm/arch-s3c2410/regs-gpio.h>
#include<asm/arch-s3c2410/irqs.h>
#define KEY_NUM 4
#define DEVICE_NAME "key"
#define KEY_MAJOR 0
#define KEY_MINOR 0
#define MAX_KEY_BUF 16
#define KEY_IRQ1 IRQ_EINT0
#define KEY_IRQ2 IRQ_EINT2
#define KEY_IRQ3 IRQ_EINT11
#define KEY_IRQ4 IRQ_EINT19
#define KEY_STATUS_1 0
#define KEY_STATUS_2 2
#define KEY_STATUS_3 11
#define KEY_STATUS_4 19
define KEY_STATUS_DOWNX 0
#define KEY_STATUS_DOWN 1
#define KEY_STATUS_UP 2
#define KEY_TIMER_DELAY1 HZ/100 //100ms
#define KEY_TIMER_DELAY2 HZ/5 //200ms
#define KEY_TIMER_DELAY3 HZ //1000ms
//unsigned long rINTPND;
void __iomem * rINTPND;
void __iomem * rINTMASK;
void __iomem * rEINPEND;
void __iomem * rEINPMASK;
void __iomem * rSRCPND;
void __iomem * rEXTINT0;
void __iomem * rEXTINT1;
void __iomem * rEXTINT2;
void __iomem * rGPFDATA;
void __iomem * rGPGDATA;
void __iomem * rGPFCON;
void __iomem * rGPGCON;
#define INT_IRQ1 1<<0
#define INT_IRQ2 1<<2
#define INT_IRQ11 1<<11
#define INT_IRQ19 1<<19
#define INT_IRQ8_23 1<<5
static int key_major=KEY_MAJOR;
static int flag=0;
typedef struct {
unsigned int keyStatus[KEY_NUM];
unsigned char buf[MAX_KEY_BUF];
unsigned int head,tail;
wait_queue_head_t wq;
struct cdev k_dev;
} key_dev;
static struct timer_list key_timer[KEY_NUM];
static key_dev * k_dev;
static struct key_info
{
int irq_no;
unsigned int gpio_port;
unsigned int gpio_function;
int key_no;
} key_info_tab[KEY_NUM]=
{
{ KEY_IRQ1,S3C2410_GPF0,S3C2410_GPF0_EINT0 ,0 }
,
{ KEY_IRQ2,S3C2410_GPF2,S3C2410_GPF2_EINT2,1 }
,
{ KEY_IRQ3,S3C2410_GPG3,S3C2410_GPG3_EINT11,2 }
,
{ KEY_IRQ4,S3C2410_GPG11,S3C2410_GPG11_EINT19 ,3 }
};
static unsigned char key_read(void)
{
unsigned char ret;
ret=k_dev->buf[k_dev->tail];
k_dev->tail++;
k_dev->tail=(k_dev->tail)%(MAX_KEY_BUF);
return ret;
}
static void key_write(unsigned char key)
{
k_dev->buf[k_dev->head]=key;
k_dev->head++;
k_dev->head=(k_dev->head)%(MAX_KEY_BUF);
}
static void key_event(int key)
{
unsigned char key_no='0';
printk("key_event key =%d !\n",key);
if(key==0)
key_no='a';
else if(key==1)
key_no='b';
else if(key==2)
key_no='c';
else if(key==3)
key_no='d';
key_write(key_no);
key_num=key;
flag=1;
wake_up_interruptible(&(k_dev->wq));
}
static void clear_pending(unsigned int value)
{
writel(value,rSRCPND);
writel(value,rINTPND);
}
static void clear_sub_pending(unsigned int value)
{
writel(value,rEINPEND);
//writel(value,rINTPND);
}
static void clear_interrupt(int key)
{
unsigned int value;
value=ioread32(rINTPND);
if(value==INT_IRQ1)
{
clear_pending(INT_IRQ1);
}
else if(value==INT_IRQ2)
{
clear_pending(INT_IRQ1);
}
else if(value==INT_IRQ8_23)
{
clear_pending(INT_IRQ8_23);
value=ioread32(rEINPEND);
if(value==INT_IRQ11)
{
clear_sub_pending(INT_IRQ11);
}
else if(value==INT_IRQ19)
{
clear_sub_pending(INT_IRQ19);
}
}
}
static int Is_key_down(int key)
{
int ret;
int value;
value=s3c2410_gpio_getpin(key_info_tab[key].gpio_port);
if(value==0)
ret=1;
else
ret=0;
return ret;
}
static void key_timer_handle(unsigned long arg)
{
int key=(int)arg;
if(Is_key_down(key))
{
if(k_dev->keyStatus[key]==KEY_STATUS_DOWNX)
{
k_dev->keyStatus[key]=KEY_STATUS_DOWN;
key_timer[key].expires=jiffies+KEY_TIMER_DELAY3;
key_event(key);
add_timer(&key_timer[key]);
}
else
{
key_timer[key].expires=jiffies+KEY_TIMER_DELAY2;
add_timer(&key_timer[key]);
}
}
else
{
printk("key %d up!\n",key);
k_dev->keyStatus[key]=KEY_STATUS_UP;
enable_irq(key_info_tab[key].irq_no);
}
}
static irqreturn_t s3c2410_key_ISR(int irq,void *dev_id,struct pt_regs *regs)
{
int value;
int key;
struct key_info * k;
k=(struct key_info *)dev_id;
key=k->key_no;
if(key<0 || key>3 )
{
printk("Error irq no!\n");
return -1;
}
disable_irq(key_info_tab[key].irq_no); //绂佹涓柇
clear_interrupt(key);
k_dev->keyStatus[key]=KEY_STATUS_DOWNX;
key_timer[key].expires=jiffies+KEY_TIMER_DELAY1;
add_timer(&key_timer[key]);
return 0;
}
static int key_request_irqs(void)
{
int i,ret=0;
struct key_info *k;
for(i=0; i<sizeof(key_info_tab)/sizeof(key_info_tab[0]); i++)
{
k=key_info_tab+i;
ret=request_irq(k->irq_no,s3c2410_key_ISR,SA_INTERRUPT,DEVICE_NAME,k);
if(ret)
{
printk("Request irq(irq_no=%d) failed!\n",k->irq_no);
break;
}
else
printk("Request irq(irq_no=%d) succed!\n",k->irq_no);
}
return ret;
}
static void key_free_irqs(void)
{
int i;
struct key_info *k;
for(i=0; i<sizeof(key_info_tab)/sizeof(key_info_tab[0]); i++)
{
k=key_info_tab+i;
free_irq(k->irq_no,k);
}
}
static void key_init_timer(void)
{
int i;
for(i=0; i<KEY_NUM;i++)
{
init_timer(&key_timer[i]);
key_timer[i].function=&key_timer_handle;
key_timer[i].data=i;
key_timer[i].expires=jiffies+KEY_TIMER_DELAY1;
}
}
static int s3c2410_key_open(struct inode *inode,struct file *filp)
{
int i;
key_request_irqs();
key_init_timer();
return 0;
}
static int s3c2410_key_release(struct inode *inode,struct file *filp)
{
key_free_irqs();
return 0;
}
static ssize_t s3c2410_key_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)
{
unsigned char button_ret;
retry:
printk("OPEN:retry start\n");
if(k_dev->head!=k_dev->tail)
{
button_ret=key_read();
printk("s3c2410_key_read:the button_ret is %d\n",button_ret);
copy_to_user(buffer,(char *)&button_ret,sizeof(unsigned char));
flag=0;
return sizeof(unsigned char);
}
else
{
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
printk("OPEN: sleep\n");
//interruptible_sleep_on(&(buttondev.wq));
wait_event_interruptible(k_dev->wq,flag);
flag=0;
printk("OPEN: sleep_after\n");
if(signal_pending(current))
{
printk("rturn -ERESTARTSYS\n");
return -ERESTARTSYS;
}
goto retry;
}
return sizeof(unsigned char);
}
static struct file_operations key_fops= {
.owner = THIS_MODULE,
.open = s3c2410_key_open,
.read = s3c2410_key_read,
.release = s3c2410_key_release,
};
static void key_enable_irq(void)
{
unsigned int value;
value=0;
value|=(1<11)|(1<<19);
iowrite32(value,rEINPEND);
value=ioread32(rEINPMASK);
value&=~((1<11)|(1<<19));
iowrite32(value,rEINPMASK);
clear_pending(INT_IRQ1|INT_IRQ2| INT_IRQ8_23);
value=ioread32(rINTMASK);
value&=~((INT_IRQ1|INT_IRQ2| INT_IRQ8_23));
iowrite32(value,rINTMASK);
}
static void key_init_irqs(void)
{
int i;
struct key_info *k;
for(i=0; i<sizeof(key_info_tab)/sizeof(key_info_tab[0]); i++)
{
k=key_info_tab+i;
s3c2410_gpio_cfgpin(k->gpio_port, k->gpio_function);
set_irq_type(k->irq_no,IRQT_LOW);
//set_irq_type(k->irq_no,S3C2410_EXTINT_LOWLEV);
}
key_enable_irq();
}
/* IO remap */
static void key_ioremap(void)
{
rINTPND=ioremap(0x4a000010,4);
rEINPEND=ioremap(0x560000a8,4);
rSRCPND=ioremap(0x4a000000,4);
rEXTINT0=ioremap(0x56000088,4);
rEXTINT1=ioremap(0x5600008c,4);
rEXTINT2=ioremap(0x56000090,4);
rGPFDATA=ioremap(0x56000054,4);
rGPGDATA=ioremap(0x56000064,4);
rEINPMASK=ioremap(0x560000a4,4);
rINTMASK=ioremap(0x4a000008,4);
rGPFCON=ioremap(0x56000050,4);
rGPGCON=ioremap(0x56000060,4);
}
static void key_setup_cdev( key_dev * dev,int index)
{
int err,i;
int devno=MKDEV(key_major,index);
cdev_init(&dev->k_dev,&key_fops);
dev->k_dev.owner=THIS_MODULE;
dev->k_dev.ops=&key_fops;
err=cdev_add(&dev->k_dev,devno,1);
init_waitqueue_head(&(dev->wq));
for(i=0 ; i<KEY_NUM; i++)
dev->keyStatus[i]=KEY_STATUS_UP;
dev->head=dev->tail=0;
key_ioremap();
if(err)
printk(KERN_NOTICE"Error %d adding key %d",err,index);
}
static int __init s3c2410_key_init(void)
{
int ret;
dev_t devno=MKDEV(key_major,0);
if(key_major)
{
ret=register_chrdev_region(devno,1,DEVICE_NAME);
}
else
{
ret=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
key_major=MAJOR(devno);
}
if(ret<0)
return ret;
k_dev=kmalloc(sizeof(key_dev),GFP_KERNEL);
if(!k_dev)
{
ret=-ENOMEM;
goto fail_malloc;
}
memset(k_dev,0,sizeof(key_dev));
key_setup_cdev(k_dev,0);
key_init_irqs();
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(key_major,0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);
#endif
printk(DEVICE_NAME" initialized\n");
return 0;
fail_malloc:
#ifdef CONFIG_DEVFS_FS
devfs_remove(DEVICE_NAME);
#endif
unregister_chrdev_region(devno,1);
}
static void __exit s3c2410_key_eixt(void)
{
printk(DEVICE_NAME" exited\n");
cdev_del(&k_dev->k_dev);
kfree(k_dev);
unregister_chrdev_region(MKDEV(key_major,0),1);
#ifdef CONFIG_DEVFS_FS
devfs_remove(DEVICE_NAME);
#endif
//key_free_irqs();
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION ("A key device driver");
module_init(s3c2410_key_init);
module_exit(s3c2410_key_eixt);
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #608同步于 2008/6/11
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖
好几天没什么动静了,上个键盘驱动吧
fzylijun886
2008/6/11镜像同步1 回复
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复