📄 buttons.c
字号:
#include <linux/module.h>
//#include <linux/delay.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/arch/S3C2410.h>
#include <asm/arch/irqs.h>
#define DEVICE_NAME "buttons"
#define BUTTON_MAJOR 0
static int buttonsMajor=0;
int key_value=1;
int ready=0;
static int uptime;
static int downtime;
/*定义按键所使用的cpu资源*/
static struct key_info{
int irq_no;
unsigned int gpio_port;
int key_no;
}key_info_tab[2]={
{IRQ_EINT0,GPIO_F0,0},
{IRQ_EINT11,GPIO_G3,5},
};
/*
static int led_open(struct inode *inode,struct file *file)
{
MOD_INC_USE_COUNT;
return 0;
}
static int led_close(struct inode *inode,struct file *file)
{
MOD_DEC_USE_COUNT;
leds_event(led_start);
return 0;
}
*/
static void buttons_irq(int irq,void *dev_id,struct pt_regs *reg)
{
struct key_info *k;
int i;
int found=0;
int up;
int flags;
//使用irq号码判断是否是某个键盘,因为中断程序被4个按键中断共用
for(i=0;i<sizeof(key_info_tab)/sizeof(key_info_tab[1]);i++)
{
k=key_info_tab+i;
if(k->irq_no==irq)
{
found=1;
break;
}
}
if(!found)
{
printk("not found irq %d",irq);
return;
}
save_flags(flags);//保存当前中断状态
cli();//置位cpsr,禁用中断//???????????????????????????
//set_gpio_mode_user(k->gpio_port,GPIO_MODE_IN);//复位中断端口,从端口读取电平高低值
up=read_gpio_bit(k->gpio_port);
set_external_irq(k->irq_no,EXT_BOTH_EDGES,GPIO_PULLUP_DIS);
restore_flags(flags);//恢复中断状态
//保存从中断读出的值
if(!up)
{
key_value=0;
downtime = jiffies;
}
else
{
if(irq==IRQ_EINT0) key_value=1;
if(irq==IRQ_EINT11) key_value=2;
uptime=jiffies;
if((uptime-downtime)>=50) //key_value=3;
{
if(irq==IRQ_EINT0) key_value=11;
if(irq==IRQ_EINT11) key_value=22;
}
}
ready=1;//置位全局状态
//???????????????????????????????????????????????????????????????????????
//wake_up_interruptible(&buttons_wait);//等待任务唤醒,select调用的进程
}
static int request_irqs(void)
{
struct key_info *k;
int i;
for(i=0;i<sizeof(key_info_tab)/sizeof(key_info_tab[1]);i++)
{
k=key_info_tab+i;
set_external_irq(k->irq_no,EXT_BOTH_EDGES,GPIO_PULLUP_DIS);
if(request_irq(k->irq_no,&buttons_irq,SA_INTERRUPT,DEVICE_NAME,&buttons_irq))
{
return -1;
}
}
return 0;
}
static void free_irqs(void)
{
struct key_info *k;
int i;
for(i=0;i<sizeof(key_info_tab)/sizeof(key_info_tab[1]);i++)
{
k=key_info_tab+i;
free_irq(k->irq_no,buttons_irq);
}
}
static int 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 struct file_operations buttons_fops=
{
owner: THIS_MODULE,
read: buttons_read,
};
static devfs_handle_t devfs_handle,devfs_buttons_dir;
static int __init buttons_init(void)
{
int ret;
ready=0;
ret=register_chrdev(BUTTON_MAJOR,DEVICE_NAME,&buttons_fops);
if(ret<0)
{
printk(DEVICE_NAME "can't register major number\n");
return ret;
}
ret=request_irqs();
if(ret)
{
unregister_chrdev(BUTTON_MAJOR,DEVICE_NAME);
//printk(DEVICE_NAME "can't register irqs\n);
return ret;
}
ret=devfs_register_chrdev(BUTTON_MAJOR,DEVICE_NAME,&buttons_fops);
if(ret<0)
{
return ret;
}
if(!BUTTON_MAJOR)
{
buttonsMajor=ret;
printk("major number=%d\n",buttonsMajor);
}
devfs_buttons_dir=devfs_mk_dir(NULL,DEVICE_NAME,NULL);
devfs_handle=devfs_register(devfs_buttons_dir,"1",DEVFS_FL_DEFAULT,ret,0,S_IFCHR|S_IRUSR|S_IWUSR,&buttons_fops,NULL);
return 0;
}
static void __exit buttons_exit(void)
{
int res;
res=unregister_chrdev(buttonsMajor,DEVICE_NAME);
devfs_unregister(devfs_handle);
devfs_unregister(devfs_buttons_dir);
free_irqs();
}
module_init(buttons_init);
module_exit(buttons_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -