终于要远离嵌入式应用可以转到安卓的驱动了,还是很激动的,终于可以做linux的驱动了,今天搞了一天,input子系统还是有点复杂啊,今天查找各种资料草草完成input子系统的按键输入设备例程,先记下来,再进行优化:
按键驱动:
/*以后写驱动可以讲头文件一股脑的加载代码前面*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/input.h>
/*中断函数头文件*/
#include <linux/interrupt.h>
#include <linux/irq.h>
#define IRQ_DEBUG
#ifdef IRQ_DEBUG
#define DPRINTK(x...) printk("IRQ_CTL DEBUG:" x)
#else
#define DPRINTK(x...)
#endif
#define DRIVER_NAME "irq_test"
#define KEY_GPIO(i) EXYNOS4_GPX1(i+1)
#define KEY_QWER(i) (KEY_Q+i)
struct input_dev *button_input_dev;
struct timer_list buttons_timer;
static struct ping_desc *buttons_id;
struct ping_desc{
unsigned char *name; //中断设备名称
int pin_irq; //按键的外部中断标志位
unsigned int pin; //引脚
unsigned int irq_ctl; //触发中断状态: IRQ_TYPE_EDGE_BOTH
unsigned int button; //dev_id,对应键盘的 L , S, 空格, enter
};
static struct ping_desc buttons_desc[2]=
{
{"key1", IRQ_EINT(9), EXYNOS4_GPX1(1), IRQ_TYPE_EDGE_FALLING,KEY_Q},
{"key2", IRQ_EINT(10), EXYNOS4_GPX1(2), IRQ_TYPE_EDGE_FALLING,KEY_W},
};
irqreturn_t buttons_irq(int irq, void *dev_id) {
/*上报事件*/
/* int i=0;
for(i = 0; i < 2; i++){
printk("key%d Down!\n", i+1);
if(irq==buttons_desc[1].pin_irq){
input_report_key(button_input_dev, buttons_desc[i].button, gpio_get_value(KEY_GPIO(i)));
input_sync(button_input_dev);
}
}
*/
int i=0;
for(i = 0; i < 2; i++){
if(irq == buttons_desc[i].pin_irq){
printk("key%d Down!\n", i);
input_report_key(button_input_dev, buttons_desc[i].button, gpio_get_value(buttons_desc[i].pin));
input_sync(button_input_dev);
}
}
return IRQ_HANDLED;
}
static int irq_probe(struct platform_device *pdev)
{
char *banner = "probe ...\n";
printk(banner);
return 0;
}
static int irq_remove (struct platform_device *pdev)
{
return 0;
}
static int irq_suspend (struct platform_device *pdev, pm_message_t state)
{
DPRINTK("irq suspend:power off!\n");
return 0;
}
static int irq_resume (struct platform_device *pdev)
{
DPRINTK("irq resume:power on!\n");
return 0;
}
static struct platform_driver irq_driver = {
.probe = irq_probe,
.remove = irq_remove,
.suspend = irq_suspend,
.resume = irq_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
static void __exit irq_test_exit(void)
{
/*7.释放中断函数,删除定时器,卸载释放驱动*/
int i;
input_unregister_device(button_input_dev); //卸载类下的驱动设备
for(i = 0;i < 2;i++) {
free_irq(buttons_desc[i].pin_irq,NULL); //释放中断函数
}
input_free_device(button_input_dev); //释放驱动结构体
platform_driver_unregister(&irq_driver);
return;
}
static int __init irq_test_init(void)
{
int i,j;
int error;
char *banner = "input device key_irq_test Initialize\n";
printk(banner);
for(i=0; i<2; i++){
if (request_irq(buttons_desc[i].pin_irq, buttons_irq,IRQ_TYPE_EDGE_FALLING,buttons_desc[i].name,NULL)) {
printk(KERN_ERR "itop4412_irq.c: Can't allocate irq %d\n", buttons_desc[i].pin_irq);
return -EBUSY;
}
}
button_input_dev = input_allocate_device();
if(!button_input_dev){
printk(KERN_ERR "itop4412_irq.c: Not enough memory\n");
error = -ENOMEM;
goto err_free_irq;
}
button_input_dev->name = "input key dev";
set_bit(EV_KEY, button_input_dev->evbit);
//让该设备支持qwer键
for(j = 0;j < 2;j++) {
set_bit(buttons_desc[j].button, button_input_dev->keybit);
}
error = input_register_device(button_input_dev);
if (error) {
printk(KERN_ERR "button.c: Failed to register device\n");
goto err_free_dev;
}
platform_driver_register(&irq_driver);
return 0;
err_free_dev:
input_free_device(button_input_dev);
err_free_irq:
for(i--;i < 2;i++) {
free_irq(buttons_desc[i].pin_irq,NULL);
}
return error;
}
module_init(irq_test_init);
module_exit(irq_test_exit);
MODULE_LICENSE("Dual BSD/GPL");
测试程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/input.h>
int main(int argc, char **argv)
{
int fd;
struct input_event event;
fd = open(argv[1],O_RDWR);
if(fd < 0){
perror("open error:");
return fd;
}
while(1){
read(fd,&event,sizeof(event));
if(event.type == EV_KEY){
if(event.code == KEY_Q){
printf("Q:霸王拳\n");
}
if(event.code == KEY_W){
printf("W:降龙十八掌\n");
}
}
}
close(fd);
return 0;
}