button_drv.c
1 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/input.h> 4 #include <linux/gpio.h> 5 #include <linux/interrupt.h> 6 7 8 static int irqno; 9 static struct input_dev *key_inputdev; 10 11 12 irqreturn_t input_key_irq_svc(int irqno, void *dev_id) 13 { 14 //区分是按下还是抬起 15 16 int value = gpio_get_value(S5PV210_GPH0(1)); 17 18 if(value) 19 { 20 printk("<kernel>-- KEY_DOWN up "); 21 //抬起 22 //上报数据--给input handler层 23 24 //参数1--哪个设备上报的 25 //参数2--哪个按键 26 //参数3--按键的状态--1按下/0抬起 27 input_report_key(key_inputdev, KEY_DOWN, 0); 28 29 //最后一定要同步--上报结束 30 input_sync(key_inputdev); 31 32 }else 33 { 34 printk("<kernel>-- KEY_DOWN pressed "); 35 //按下 36 //input_report_key(key_inputdev, KEY_DOWN, 1); 37 input_event(key_inputdev, EV_KEY, KEY_DOWN, 1); 38 input_sync(key_inputdev); 39 } 40 41 42 return IRQ_HANDLED; 43 } 44 45 46 47 48 49 static int __init input_key_drv_init(void) 50 { 51 52 /* 53 1, 分配一个 input device对象 54 55 2, 初始化input device对象 56 57 3, 注册input device对象 58 59 4, 硬件初始化,获取到硬件的数据,上报给input handler 60 61 */ 62 63 key_inputdev = input_allocate_device(); 64 65 //2, 初始化input device对象--其实就是初始化evbit[], keybit[]或者absbit等 66 67 #if 0 68 // 2.1 设置当前设备能够产生按键类型数据 69 key_inputdev->evbit[EV_KEY/32] |= 1<<(EV_KEY%32); 70 // 2.2 设置当前设备能够产生哪些按键 71 key_inputdev->keybit[KEY_UP/32] |= 1<<(KEY_UP%32); 72 #else 73 // 2.1 设置当前设备能够产生按键类型数据 74 key_inputdev->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); 75 76 // 2.2 设置当前设备能够产生哪些按键 77 key_inputdev->keybit[BIT_WORD(KEY_UP)] |= BIT_MASK(KEY_UP); 78 key_inputdev->keybit[BIT_WORD(KEY_DOWN)] |= BIT_MASK(KEY_DOWN); 79 key_inputdev->keybit[BIT_WORD(KEY_LEFT)] |= BIT_MASK(KEY_LEFT); 80 key_inputdev->keybit[BIT_WORD(KEY_RIGHT)] |= BIT_MASK(KEY_RIGHT); 81 82 #endif 83 84 85 // 3, 注册input device对象 86 input_register_device(key_inputdev); 87 88 // 4, 硬件初始化,获取到硬件的数据,上报给input handler 89 //申请中断--暂时只申请一次 90 //irqno = IRQ_EINT(1); 91 irqno = gpio_to_irq(S5PV210_GPH0(1)); 92 request_irq(irqno, input_key_irq_svc, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, 93 "eint1_keydown", NULL); 94 95 96 return 0; 97 } 98 99 static void __exit input_key_drv_exit(void) 100 { 101 free_irq(irqno, NULL); 102 input_unregister_device(key_inputdev); 103 input_free_device(key_inputdev); 104 105 } 106 107 module_init(input_key_drv_init); 108 module_exit(input_key_drv_exit); 109 MODULE_LICENSE("GPL");
Makefile
1 CROSS_COMPILE = arm-none-linux-gnueabi- 2 CC = $(CROSS_COMPILE)gcc 3 4 #指定内核源码路径 5 KERNEL_DIR = /home/farsight/s5pv210/kernel/linux-3.0.8 6 CUR_DIR = $(shell pwd) 7 8 MYAPP = input_key_app 9 10 MODULE = input_key_drv 11 12 all: 13 #让make进入内核源码编译,同时将当前目录中的c程序作为内核模块一起编译 14 make -C $(KERNEL_DIR) M=$(CUR_DIR) modules 15 ifneq ($(MYAPP), ) 16 $(CC) -o $(MYAPP) $(MYAPP).c 17 endif 18 19 clean: 20 #删除上面编译生成的文件 21 make -C $(KERNEL_DIR) M=$(CUR_DIR) clean 22 rm -rf $(MYAPP) 23 24 install: 25 cp *.ko $(MYAPP) /opt/rootfs/drv_module 26 27 #指定当前目录下哪个文件作为内核模块编 28 obj-m += $(MODULE).o
test
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 #include <sys/ioctl.h> 9 #include <linux/input.h> 10 11 12 int main(void) 13 { 14 15 int fd; 16 int ret; 17 18 struct input_event package; 19 20 21 fd = open("/dev/event0",O_RDWR); 22 if(fd < 0) 23 { 24 perror("open"); 25 exit(1); 26 } 27 28 while(1) 29 { 30 bzero(&package,sizeof(package)); 31 ret = read(fd, &package,sizeof(package)); 32 if(ret < 0) 33 { 34 perror("read"); 35 exit(1); 36 } 37 //拆包 38 if(package.type == EV_KEY) 39 { 40 if(package.code == KEY_DOWN) 41 { 42 if(package.value) 43 { 44 printf("<app>-- KEY_DOWN pressed "); 45 }else 46 { 47 printf("<app>-- KEY_DOWN up "); 48 } 49 } 50 if(package.code == KEY_POWER) 51 { 52 if(package.value) 53 { 54 printf("<app>-- KEY_POWER pressed "); 55 }else 56 { 57 printf("<app>-- KEY_POWER up "); 58 } 59 } 60 } 61 } 62 63 close(fd); 64 65 return 0; 66 }