linux input subsystem with multiple keys

Linux input subsystem: drive multiple keys

  • Drive multiple buttons
    A button has multiple elements related to it:
  1. Interrupt number
  2. Button state
  3. The value of the key

The detailed description of input_dev is as follows
Insert picture description here

Add the following information to the device tree file :

The key definition configuration information is as follows

key_int_node
{
    
    
	compatible = "test_key";
	#address-cells = <1>;   //表示下边寄存器的地址占一个位  reg
	#size-cells = <1>;    //表示下边寄存器的长度占一个位  reg
	
	key_int@0
	{
    
    
		key_name = "key2_power_eint";
		key_code = <116>;
		gpio = <&gpio 1 1 0>;
		//中断号描述
		reg = <0x11000c20 0x18>;
		interrupt-parent = <&gpx1>;
		interrupts = <1 0>;
	};	

	key_int@1
	{
    
    
		key_name = "key3_vup_eint";
		key_code = <115>;
		gpio = <&gpio 1 2 0>;
		reg = <0x11000c20 0x18>;
		interrupt-parent = <&gpx1>;
		interrupts = <2 0>;
	};	
};

These elements will also be designed in the code

struct device_node *of_get_next_child(const struct device_node *node,struct device_node *prev)

Parameter 1: Represents the node
Parameter 2: The previous node, if it is the first node, set to NULL


#define KEY_NUMS 3
//设计一个对象出来
struct key_desc
{
    
    
	int irqno;
	int key_code;
	char *name;
	int gpionum;
	void *reg_base;
	struct device_node *cnp;  //可以随时去获取节点各个信息
};

struct key_desc all_key[KEY_NUMS];


void get_all_child_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");
	}

	struct device_node *cnp;
	struct device_node *prev = NULL;
	char *key_name;
	u32 code;
	int gpionum;
	int irqno;
	int i = 0;
	do
	{
    
    
		//获取到子节点
		cnp = of_get_next_child(np,prev);
		//找到了子节点
		/*
		if(cnp != NULL)
		{
			//获取中断号
			irqno = irq_of_parse_and_map(cnp,0);
			printk("irqno = %d\n",irqno);
			//获取按键name
			of_property_read_string(cnp,"key_name",&key_name);  
			//获取key_code
			of_property_read_u32(cnp,"key_code",&code);
			//获取gpio 
			gpionum = of_get_named_gpio(cnp,"gpio",0);
			printk("name = %s,code = %s,gpionum = %d,irqno = %d\n",key_name,code,gpionum,irqno);
		}*/
	
		if(cnp != NULL)
		{
    
    
			all_key[i++].cnp = cnp;  //将当前的节点记录下来
		}
		
		prev = cnp;   //把当前的设置位prev
	} while(of_get_next_child(np,prev) != NULL);

}

In the init function

//分配inputDev
__set_bit(EV_KEY,inputdev->evbit);

int i;
for(i = 0; i < KEY_NUMS; i++)
{
    
    
	//设置key_bit,支持哪些按键
	//按键值从设备树来
	int code;
	struct device_node *cnp = all_key[i].cnp;
	code = of_property_read_u32(cnp,"key_code",&code);
	__set_bit(code,inputdev->keybit);
	all_key[i].key_code = code;   //先记录下来

	//申请中断
	int irqno;
	irqno = irq_of_parse_and_map(cnp,0);
	all_key[i].irqno = irqno;
	int irqflags = IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING;
	
	char *key_name;
	of_property_read_string(cnp,"key_name",&key_name); 
	all_key[i].name = key_name;
	
	ret = request_irq(irqno,input_key_irq_handler,irqflags,"key_name",&all_key[i]);
	if(ret != 0)
	{
    
    
		printk("request_irq error\n");
		goto err_0;
	}
}

Interrupt handling

irqreturn_t input_key_irq_handler(int irqno,void *devid)
{
    
    
	//区分不同的按键
	struct key_desc *pdesc = (struct key_desc *)devid;
	
	int gpionum = of_get_named_gpio(pdesc->cnp,"gpio",0);
	
	//直接通过gpio获取按键状态
	int value = gpio_get_value();
	
	if(value)
	{
    
    
		input_report_key(inputdev,EV_KEY,pdesc->key_code,0);
		input_sync(inputdev);  //上报数据结束
	}
	else
	{
    
    
		input_event(inputdev,EV_KEY,pdesc->key_code,1);
		input_sync(inputdev);   //上报数据结束
	}

	return IRQ_HANDLED;
}

Guess you like

Origin blog.csdn.net/qq_41782149/article/details/100652158