按键原理图:
1、驱动代码,建立按键驱动文件 input_key.c
点击(此处)折叠或打开
-
#include <linux/input.h>
-
#include <linux/module.h>
-
#include <linux/init.h>
-
#include <linux/slab.h>
-
#include <asm/irq.h>
-
#include <asm/io.h>
-
#include <linux/kernel.h>
-
#include <linux/fs.h>
-
#include <linux/init.h>
-
#include <linux/delay.h>
-
#include <linux/poll.h>
-
#include <linux/irq.h>
-
#include <asm/irq.h>
-
#include <linux/interrupt.h>
-
#include <asm/uaccess.h>
-
#include <mach/regs-gpio.h>
-
#include <mach/hardware.h>
-
#include <linux/platform_device.h>
-
#include <linux/cdev.h>
-
#include <linux/miscdevice.h>
-
#include <linux/device.h>
-
#include <linux/gpio.h>
-
#include <mach/irqs.h>
-
-
MODULE_LICENSE("GPL");
-
-
struct work_struct *work1;
-
-
struct timer_list buttons_timer;
-
-
unsigned int *gpio_data;
-
-
unsigned int key_num = 0;
-
-
wait_queue_head_t key_q;
-
-
struct input_dev *button_dev;
-
-
void work1_func(struct work_struct *work)
-
{
-
mod_timer(&buttons_timer, jiffies + (HZ /10));
-
}
-
-
void buttons_timer_function(unsigned long data)
-
{
-
input_report_key(button_dev, KEY_1, !s3c2410_gpio_getpin(S3C2410_GPG(0)));
-
input_report_key(button_dev, KEY_2, !s3c2410_gpio_getpin(S3C2410_GPG(3)));
-
-
input_sync(button_dev);
-
}
-
-
-
irqreturn_t key_int(int irq, void *dev_id)
-
{
-
//1. 检测是否发生了按键中断
-
-
//2. 清除已经发生的按键中断
-
-
//3. 提交下半部
-
schedule_work(work1);
-
-
return IRQ_HANDLED;
-
}
-
-
void key_hw_init()
-
{
-
s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPG0_EINT8);
-
s3c2410_gpio_cfgpin(S3C2410_GPF(3), S3C2410_GPG3_EINT11);
-
}
-
-
-
static int button_init()
-
{
-
int ret;
-
-
/*分配输入型设备结构*/
-
button_dev = input_allocate_device();
-
-
/*申明所支持的事件类型*/
-
set_bit(EV_KEY,button_dev->evbit);
-
-
/*申明可能上报的键编号*/
-
set_bit(KEY_1,button_dev->keybit);
-
set_bit(KEY_2,button_dev->keybit);
-
-
/*注册输入型设备*/
-
input_register_device(button_dev);
-
-
-
//注册中断处理程序
-
request_irq(IRQ_EINT8,key_int, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,"key",(void *)1);
-
request_irq(IRQ_EINT11,key_int, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,"key",(void *)2);
-
-
//按键初始化
-
key_hw_init();
-
-
//. 创建工作
-
work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
-
INIT_WORK(work1, work1_func);
-
-
/* 初始化定时器 */
-
init_timer(&buttons_timer);
-
buttons_timer.function = buttons_timer_function;
-
-
/* 向内核注册一个定时器 */
-
add_timer(&buttons_timer);
-
-
/*初始化等待队列*/
-
init_waitqueue_head(&key_q);
-
-
return 0;
-
-
}
-
-
static void button_exit()
-
{
-
input_unregister_device(button_dev);
-
}
-
-
-
module_init(button_init);
-
module_exit(button_exit);
2、Makefile
-
obj-m := input_key.o
-
KDIR := /home/win/code3/my2440/linux-2.6.39
-
all:
-
make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
-
clean:
-
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order
3、测试代码,key_app.c 采用静态编译
#arm-linux-gcc -static key_app.c -o key_app
点击(此处)折叠或打开
-
/*
-
* Buttons Example for Matrix V
-
*
-
* Copyright (C) 2004 capbily - friendly-arm
-
* capbily@hotmail.com
-
*/
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <sys/ioctl.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
#include <sys/select.h>
-
#include <sys/time.h>
-
#include <errno.h>
-
#include <linux/input.h>
-
int main(void)
-
{
-
int buttons_fd;
-
int key_value,i=0,count;
-
-
struct input_event ev_key;
-
buttons_fd = open("/dev/input/event1", O_RDWR);
-
if (buttons_fd < 0) {
-
perror("open device buttons");
-
exit(1);
-
}
-
-
printf("open device success\n");
-
-
for (;;)
-
{
-
count = read(buttons_fd,&ev_key,sizeof(struct input_event));
-
//printf("count=%d\n",count);
-
for(i=0; i<(int)count/sizeof(struct input_event); i++)
-
{
-
if(EV_KEY==ev_key.type)
-
printf("type:%d,code:%d,value:%d\n", ev_key.type,ev_key.code-1,ev_key.value);
-
if(EV_SYN==ev_key.type)
-
printf("syn event\n\n");
-
}
-
}
-
-
close(buttons_fd);
-
return 0;
-
}
按键输出结果:
4、调试过程中发现,如果上报的事件,按键编码的值没有发生改变,比如input_report_key(button_dev, KEY_1, !s3c2410_gpio_getpin(S3C2410_GPG(0)));改成input_report_key(button_dev, KEY_1, 1);那么测试程序read函数只有第一次按键操作时可以读到数据,后面再操作按键都感觉设备没有数据到达,read发生阻塞。
阅读(1452) | 评论(0) | 转发(0) |