Article Directory
Linux input subsystem: drive multiple keys
- Drive multiple buttons
A button has multiple elements related to it:
- Interrupt number
- Button state
- The value of the key
The detailed description of input_dev is as follows
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;
}