环境描述
kernel :linux 2.6.32
文件系统:yaffs,busybox1.13.1
硬件设备: TQ2440
一、一些基本理论
原理就不细说了,这里给一个连接,http://blog.csdn.net/ling1874/archive/2010/03/24/5410592.aspx
二 、code
- /*
- key_input.c
- @按键驱动程序,作为input子系统
- @针对S3C2440的驱动程序
- @2011.3.20,keytounix
- @hi.baidu.com/andio
- */
- //包含重要的和常用的头文件
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/poll.h>
- #include <linux/timer.h>
- #include <linux/irq.h>
- #include <linux/cdev.h>
- #include <linux/wait.h>//waitqueue
- #include <linux/errno.h>
- #include <linux/interrupt.h>//irq
- #include <linux/io.h>
- #include <linux/types.h>
- #include <linux/delay.h>
- #include <linux/semaphore.h>//sem
- #include <linux/fs.h>
- #include <linux/platform_device.h>//
- #include <linux/miscdevice.h>
- #include <linux/input.h>//input输入子系统
- #include <linux/device.h>
- #include <linux/workqueue.h>//workqueue
- #include <asm/uaccess.h>
- #include <asm/irq.h>
- //soc相关
- #include <mach/gpio.h>
- #include <mach/regs-clock.h>
- #include <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #include <mach/irqs.h>
- //////////////////////////////
- #define u8 unsigned char
- #define u16 unsigned short
- #define uint unsigned int
- //这个 宏获得t[n]的n数目
- #define get_elem_num(t) (sizeof(t)/sizeof(t[0]))
- #define ARRAY_SIZE(T) (sizeof(t)/sizeof(t[0]))
- ////////////////////////////////////
- //这是一个debug宏,用于调试
- #define _DEBUG_ 1
- #if _DEBUG_
- #define debug(format,msg...) printk(format,##msg)
- #else
- #define debug(format,msg...) (void *)(0)
- #endif
- struct key_info
- {
- uint irq_no;//中断号
- uint pin;//管脚值
- uint pin_set;//管脚设置
- }key_info_tab[]=
- {
- [0]={
- .irq_no=IRQ_EINT1,
- .pin=S3C2410_GPF(1),
-
- .pin_set = S3C2410_GPF1_EINT1,
- },
- [1]={
- .irq_no=IRQ_EINT4,
- .pin=S3C2410_GPF(4),
- .pin_set = S3C2410_GPF4_EINT4,
- },
- [2]={
- .irq_no=IRQ_EINT2,
- .pin=S3C2410_GPF(2),
- .pin_set = S3C2410_GPF2_EINT2,
- },
- [3]={
- .irq_no=IRQ_EINT0,
- .pin_set = S3C2410_GPF0_EINT0,
- .pin=S3C2410_GPF(0),
- }
- };
- u8 key_code[0x04]=
- {
- KEY_1,
- KEY_2,
- KEY_3,
- KEY_4
- };
- //这个宏直接获得 表x中的irq值
- #define irq(x) (key_info_tab[x].irq_no)
- //这个宏直接获得 表x中的pin值
- #define pin(x) (key_info_tab[x].pin)
- //这个宏直接获得 表x中的pin_set值
- #define set(x) (key_info_tab[x].pin_set)
- //这个宏直接获得 表x中的value值
- #define code(x) key_code[x]
- // 定义设备的相关信息
- #define DEV_NAME "usr_dev_key"
- #define VAR_KEY_DN 0x00
- #define TM1000MS 100
- #define METHOD_DELAYED_WORK 1
- static struct delayed_work delayed_work_wq;
- //工作队列的处理函数
- void my_work_proc(struct work_struct * my_work);
- static struct input_dev *dev_key;
- int volatile active_key;
- void my_delay_work_proc(struct work_struct * my_work)
- {
- int id= active_key;
- u8 key_real_var=s3c2410_gpio_getpin(pin(id));
- if(key_real_var==VAR_KEY_DN)
- {
- input_report_key(dev_key,code(id),code(id));
- input_sync(dev_key);
- }
- return;
- }
- static irqreturn_t irq_proc(unsigned int irq,int _id)
- {
- active_key =_id;
- #if METHOD_DELAYED_WORK
- schedule_delayed_work(&delayed_work_wq,TM1000MS/10);
- #endif
- debug("extern from %s,active_key=%d\n",__func__,active_key);
- return IRQ_RETVAL(IRQ_HANDLED);
- };
- /*
- @dev_init,设备初始化函数,程式化的东西
- @
- */
- static int dev_init(void)
- {
- int ret=0;
- int i;
- char * msg;
- //初始化作为input子系统的按键
- dev_key=input_allocate_device();
- dev_key->evbit[0]=BIT(EV_KEY);//支持按键
- dev_key->keycode=key_code;//
- dev_key->keycodesize=sizeof(u8);
- dev_key->keycodemax=get_elem_num(key_code);
-
- for(i=0;i<get_elem_num(key_code);i++)
- {
-
-
- set_bit(key_code[i],dev_key->keybit);
-
-
- }
-
- dev_key->name=DEV_NAME;
-
-
- input_register_device(dev_key);
- ///中断
- for(i=0;i<get_elem_num(key_info_tab);i++)
- {
- ret=request_irq(irq(i),irq_proc,IRQ_TYPE_EDGE_BOTH,DEV_NAME,i);
- msg=(ret==0?"OK":"ERR");
- debug("register %s.ext_irq[%d] -------[%s],using irq_no=%d\n",DEV_NAME,i,msg,key_info_tab[i].irq_no);
- if(ret!=0)
- goto unregister_irq_handle;
- }
- INIT_DELAYED_WORK(&delayed_work_wq,my_delay_work_proc);
- out:
- return ret;
- unregister_irq_handle:
- for(i=i-1;i>=0;i--)
- {
- free_irq(irq(i),irq_proc);
- }
- return ret;
-
- };
- static int dev_exit(void)
- {
- int i;
- for(i=0;i<get_elem_num(key_info_tab);i++)
- {
- free_irq(irq(i),irq_proc);
- }
- input_unregister_device(dev_key);
- return 0;
- };
- MODULE_AUTHOR("keytounix");
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_DESCRIPTION("driver for TQ2440 key");
- module_init(dev_init);
- module_exit(dev_exit);
三、Makefile
- #TARGET=
- TARGET=key_input
- #KERNEL
- KERNEL=2.6.32
- #variable
- CC=arm-linux-gcc -w
- obj-m :=$(TARGET).o
- KERNELDIR :=kernel/linux-$(KERNEL)
- default:
- make -C $(KERNELDIR) M=$(shell pwd) modules
- clean:
- rm -rf module* *.symvers $(TARGET).o $(TARGET).mod.c $(TARGET).mod.o $(TARGET).ko $(TARGET).tmp_versions
四、测试程序
编译方法:#arm-linux-gcc -march=armv4t test.c -o test
#insmod key_input.ko
#./test /dev/event0 //或者
#./test /dev/input/event0
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <linux/input.h>
- int main(int argc, char ** argv)
- {
- int fd;
- int yalv;
- size_t rb;/* the events (up to 64 at once) */
- struct input_event ev[64];
- if ((fd = open(argv[1], O_RDONLY)) < 0) {
- perror("evdev open");
- exit(1);
- }
- rb=read(fd,ev,sizeof(struct input_event)*64);
- if (rb < (int) sizeof(struct input_event))
- {
- perror("evtest: short read");
- exit (1);
- }
- for (yalv = 0; yalv < (int) (rb / sizeof(struct input_event)); yalv++)
- {
- if (EV_KEY == ev[yalv].type)
- printf("%ld.%06ld ", ev[yalv].time.tv_sec,ev[yalv].time.tv_usec);
- printf("type %d code %d value %d\n", ev[yalv].type, ev[yalv].code, ev[yalv].value);
- }
- close(fd);
- return 0;
- }
五、问题
阅读(1666) | 评论(0) | 转发(0) |