文章目录
linux输入子系统:驱动多个按键
驱动多个按键
一个按键有多个与其相关的元素:
中断号码
按键状态
按键的值
input_dev的详细描述如下图
在设备树文件中增加以下信息:
按键定义配置信息如下
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 = ;
//中断号描述
reg = <0x11000c20 0x18>;
interrupt-parent = ;
interrupts = <1 0>;
};
key_int@1
{
key_name = "key3_vup_eint";
key_code = <115>;
gpio = ;
reg = <0x11000c20 0x18>;
interrupt-parent = ;
interrupts = <2 0>;
};
};
在代码中也会设计这几个元素
struct device_node *of_get_next_child(const struct device_node *node,struct device_node *prev)
参数1:表示节点
参数2:之前的节点,如果是第一个节点,设置成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);
}
在init函数中
//分配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;
}
}
中断处理
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,1);
input_sync(inputdev); //上报数据结束
}
else
{
input_event(inputdev,EV_KEY,pdesc->key_code,1);
input_sync(inputdev); //上报数据结束
}
return IRQ_HANDLED;
}
标签:node,code,name,cnp,int,linux,key,按键,子系统
来源: https://blog.csdn.net/qq_41782149/article/details/100652158