linux驱动 -- 输入子系统
1:输入子系统介绍
一个统一的输入设备的开发框架, 统一生成设备文件, 统一返回固定格式值。
2:输入子系统开发设备
键盘、鼠标、触摸屏等等。
3:输入子系统运行框架
应用层:操作设备文件+open+close+read+write
输入子系统:为中间层
驱动层:注册设备为输入子系统,把输入设备的事件告诉给输入子系统
4:输入子系统的开发
无需再去注册生产设备文件,也无需做上层的交互->不需要返回有效数据
在输入子系统中:
1:需要把设备注册为输入子系统的设备
函数原型:
input_register_device(struct input_dev * dev);
2:在内核层上报输入设备的行为、事件
比如按键摁下需要告诉输入子系统
松开也需要告诉输入子系统
采用中断的方式确定按键摁下
5:内核接口函数
头文件:
#include "linux/input.h"
函数功能:上报事件给输入子系统
任何输入子系统注册设备,一旦发生任何事件都应该上报给输入子系统
上报事件函数原型:
input_event(struct input_dev * dev ,unsigned int typedef, unsigned int code,int value);
函数参数:
dev:
上报给你注册哪个输入子系统设备
核心结构体
type:
上报事件的类型->
EV_SYN->代表上报了一个同步消息
数据就会产生同步(输入子系统是有类似缓冲区概念)
EV_KEY->
代表上报了按键事件
code:
上报具体的什么事件
EV_SYN ->这个地方固定填写 0
EV_KEY ->
这个地方则代表你上报按键的具体是哪个按键!
KEY_1 KEY_2 KEY_Q ......
value:
代表具体上报值
如果你用 EV_SYN ->此处固定填 0
如果你用 EV_KEY ->代表你上报按键的具体的状态
0->按键松开
1->按键按下
函数功能:向内核注册输入子系统
函数原型:int input_register_device(struct input_dev *dev);
函数参数:
dev:
输入子系统的核心结构体需要用->input_allocate_device(void)开辟
struct input_dev
{
const char *name;
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]
这是记录当前注册输入子系统支持的事件
其中相关重要参数
EV_SYN:同步事件
EV_KEY:输入子系统支持 按键事件
EV_REL:相对事件
EV_ABS:绝对坐标
EV_REP:重复事件->列如按下不松手
通过函数set_bit();设置
用法:set_bit(EV_KEY,dev->evbit);
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
往keybit里面添加支持的键值,这个为键盘设备,摁下后会是一个世界编码表。
}
函数返回值:
注册输入子系统成功返回 0
注册输入子系统失败返回非 0
6:按键输入代码参考示例
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/of.h"
#include "linux/cdev.h"
#include "linux/fs.h"
#include "linux/gpio.h"
#include "linux/of_gpio.h"
#include "linux/device/class.h"
#include "linux/device.h"
#include "linux/platform_device.h"
#include "linux/miscdevice.h"
#include "asm/uaccess.h"
#include "linux/input.h"
#include "linux/irq.h"
#include "linux/interrupt.h"
int irqnum;
int gpio_num;
int value =0 ;
struct input_dev * mykeyp;
irqreturn_t mykey_irq(int irqnum, void * arg)
{
value = gpio_get_value(gpio_num);
if(value == 0)//按键松开
{
input_event(mykeyp,EV_KEY,KEY_1,0);
}else//按键按下!
{
input_event(mykeyp,EV_KEY,KEY_1,1);
}
input_sync(mykeyp);
return 0;
}
int mykey_probe(struct platform_device * devp)
{
int ret = 0;
gpio_num = of_get_named_gpio(devp->dev.of_node,"xyd-gpios",0);
gpio_request(gpio_num,"xyd_key");
gpio_direction_input(gpio_num);
//1:获取中断号
irqnum = platform_get_irq(devp,0);
//2:注册中断
ret =devm_request_irq(&devp->dev,irqnum,mykey_irq,0,"key_irq",NULL);
ret = ret ;
//3:注册按键为输入子系统设备
mykeyp = input_allocate_device();
mykeyp->name = "xyd_key";
set_bit(EV_KEY,mykeyp->evbit);//按键事件支持
set_bit(EV_REP,mykeyp->evbit);//重复事件支持
set_bit(KEY_1,mykeyp->keybit);//支持按键 1
mykeyp->keycodemax = 1;
return input_register_device(mykeyp);
}
struct of_device_id key_id_table={
.compatible = "xyd_key",
};
struct platform_driver keyplat={
.driver={
.name = "xyd_key",
.of_match_table = &key_id_table,
},
.probe = mykey_probe,
};
static int __init mykey_init(void)
{
return platform_driver_register(&keyplat);
}
static void __exit mykey_exit(void)
{ }
module_init(mykey_init);
module_exit(mykey_exit);
MODULE_LICENSE("GPL");