输入子系统实现按键驱动实验

判断通关:
实验现象截图,并上传代码

inputdev范例

/*
设备树文件:
   key_int_node{
        compatible = "test_key";
		interrupt-parent = <&gpx1>;
        interrupts = <2 0>;
	};
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_irq.h>

#include <asm/io.h>

#define GPX1CON_ADDR 0x11000c20
#define GPX1_SIZE 8

struct input_dev *pInputdev;
int irqno;
void* reg_virt_base;


int get_irqno_from_node(void)
{
	//获取到设备树中的节点

	struct device_node *np = of_find_node_by_path("/key_int_node");
	
	if(np){
		printk("find node ok\n");
	}
	else{
		printk("find node failed\n");
		return 0;
	}
	//通过节点去获取到中断号码
	irqno = irq_of_parse_and_map(np,0);
	
	printk("irqno = %d\n",irqno);

	return irqno;
}



irqreturn_t input_key_irq_handler(int irqno, void *devid)
{
	unsigned int GPX1DAT;
	printk("--------------%s------------------\n",__FUNCTION__);
	
	
	GPX1DAT = readl(reg_virt_base + 4);
	printk("----------GPX1DAT = %d-----------\n",GPX1DAT);
	
	if( GPX1DAT &= 0x1<<2 ){//抬起
		printk("__KERN__:Enter up\n");	 
		input_event(pInputdev,EV_KEY,KEY_POWER,0);	//上报数据
		input_sync(pInputdev);		//上报数据结束
	}
	else{//按下
		printk("__KERN__:Enter down\n");
		input_event(pInputdev,EV_KEY,KEY_POWER,1);	//上报数据
		input_sync(pInputdev);	//上报数据结束
	}

	return IRQ_HANDLED;
}


static int __init simple_input_dev_init(void)
{
	/*
		1,分配一个input device对象
		2,初始化input  device对象
		3,注册input device对象
	*/
	int ret ;
	pInputdev = input_allocate_device();
	if(pInputdev == NULL)
	{
		printk(KERN_ERR "input_allocate_device error");
		return -ENOMEM;
	}

	//当前设备能够产生“按键”类型数据
	__set_bit(EV_KEY,pInputdev->evbit);
	//当前设备能够产生power按键值
	__set_bit(KEY_POWER,pInputdev->keybit);	

	pInputdev->name = "button_dev";//随便取个名字 不然会报错

	ret = input_register_device(pInputdev);
	if(ret != 0)
	{
		printk(KERN_ERR "input_register_device error");
		goto err0;
	}

	irqno = get_irqno_from_node();

	ret = request_irq(irqno, input_key_irq_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "IRQ_EINT10", NULL);

	if(ret != 0)
	{
		printk("request_irq ERROR!\n");
		goto err1;
	}

	reg_virt_base= ioremap(GPX1CON_ADDR, GPX1_SIZE);
	
	return 0;

err1:
	input_unregister_device(pInputdev);

err0:
	input_free_device(pInputdev);
	return ret;
}

static void __exit simple_input_dev_exit(void)
{
	free_irq(irqno,NULL);
	input_unregister_device(pInputdev);
	input_free_device(pInputdev);
}


module_init(simple_input_dev_init);
module_exit(simple_input_dev_exit);
MODULE_LICENSE("GPL");

[root@farsight ]# ls /dev/input/
event0
[root@farsight ]# insmod simple_input_dev.ko
[   51.361454] simple_input_dev: loading out-of-tree module taints kernel.
[   51.367989] input: button_dev as /devices/virtual/input/input1
[root@farsight ]# ls /dev/input/
event0  event1
[root@farsight ]#
[   24.691143] ----------GPX1DAT = 0-----------
[   24.695394] __KERN__:Enter down
[   24.850114] --------------input_key_irq_handler------------------
[   24.854734] ----------GPX1DAT = 4-----------
[   24.858985] __KERN__:Enter up

相匹配的APP程序代码

#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <fcntl.h>

struct input_event *pEvent;

int main(int argc, char *argv[])
{
	int fd,ret;
	fd = open("/dev/input/event1",O_RDWR); 	// 地址以及设备文件名需要按实际情况修改

	if(fd < 0)
	{
		perror("open");
		exit(1);
	}

	while(1){
		ret = read(fd, (void*)pEvent, sizeof(struct input_event));

		if(pEvent->type == EV_KEY)	 //如果产生的是“按键”类型数据
			if(pEvent->code == KEY_POWER) 	//如果按键值是POWER
				if(pEvent->value)	//如果传输的数据大于0
				{
					printf("____APP____:Key up\n");
				}
				else
				{
					printf("____APP____:Key down\n");
				}
	}

	close(fd);

	return 0;
}
[ 5238.782829] --------------input_key_irq_handler------------------
[ 5238.787451] ----------GPX1DAT = 0-----------
[ 5238.791703] __KERN__:Enter down
[ 5239.004857] --------------input_key_irq_handler------------------
[ 5239.009476] ----------GPX1DAT = 4-----------
[ 5239.013728] __KERN__:Enter up
[ 5242.390972] --------------input_key_irq_handler------------------
[ 5242.395588] ----------GPX1DAT = 0-----------
[ 5242.399839] __KERN__:Enter down
[ 5242.609469] --------------input_key_irq_handler------------------
[ 5242.614089] ----------GPX1DAT = 4-----------
[ 5242.618341] __KERN__:Enter up

效果图