【1】input设备驱动的目的
input设备驱动的工作很简单,就是操作底层硬件,获得input信息,提交给input核心层。
【2】input设备驱动的编写流程
(一)设备结构体中定义一个struct input_dev 结构体指针变量
内核中使用input_dev结构体来描述一个input设备,input_dev结构体的定义在input.h头文件里。
struct test_device{
…
struct input_dev *test_input_dev;
…
};
struct test_device * test_dev;
test_dev = kzalloc(sizeof(struct test_device),GFP_KERNEL);
(二)创建input_dev结构体
在加载函数或probe函数中,分配input_dev结构体空间
//函数原型:struct input_dev *input_allocate_device(void)
test_dev->test_input_dev = input_allocate_device();
(三)初始化struct input_dev结构体
1)设置当前input设备支持的事件和事件编码
通过设置`struct input_dev`结构体内的` unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; `变量,设置input设备支持的事件类型。事件类型包括EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等。
例如:绝对事件。
set_bit(EV_ABS, test_dev->test_input_dev->evbit);
2)通过设置设备`struct input_dev`结构体内的各种事件对应的bitmap变量,设定当前input设备支持的事件类型的具体值。
例如:绝对事件的数值范围为-500到+500 。
#define MAG_MAX_NEG -500
#define MAG_MAX_POS 500
input_set_abs_params(test_dev->test_input_dev, ABS_GAS, MAG_MAX_NEG, MAG_MAX_POS, 0, 0);
(四)注册struct input_dev结构体
使用input_register_device在加载函数中注册`struct input_dev结构体`,
例如:
ret =input_register_device(test_dev->test_input_dev);
if(ret)
{
printk( "Failed to input_unregister_device\n");
goto err_input_unregister_device;
}
(五)在input设备发生输入操作时,提交事件
当前没有具体的input设备,我们使用定时器模拟。
1)定义定时器
struct timer_list s_timer; //定时器结构体
2) 初始化定时器并注册定时器
test_dev->count =0;
init_timer(&test_dev->s_timer);
test_dev->s_timer.function = second_timer_handle;
test_dev->s_timer.expires = jiffies + HZ;
add_timer(&test_dev->s_timer); /*添加(注册)定时器*/
3)定时器处理函数
static void second_timer_handle(unsigned long arg)
{
mod_timer(&test_dev->s_timer,jiffies + HZ);
//提交input事件
input_report_abs(test_dev->test_input_dev,ABS_GAS,test_dev->count);
input_sync(test_dev->test_input_dev);
test_dev->count++;
if(test_dev->count ==100)
test_dev->count =0;
printk( "current jiffies is %ld\n", jiffies);
printk( "count is %d\n", test_dev->count);
}
(六)释放struct input_dev结构体
在卸载函数中释放 struct input_dev 结构体
input_unregister_device(test_dev->test_input_dev);
【3】代码
(一)input驱动代码
#include
#include
#include
#include
//input子系统需要的头文件
#include
MODULE_LICENSE("GPL");
#define MAG_MAX_NEG -500
#define MAG_MAX_POS 500
struct test_device{
struct input_dev *test_input_dev;
struct timer_list s_timer; //定时器结构体
unsigned int count;
};
struct test_device * test_dev;
//定时器处理函数
static void second_timer_handle(unsigned long arg)
{
mod_timer(&test_dev->s_timer,jiffies + HZ);
//提交input事件
input_report_abs(test_dev->test_input_dev,ABS_GAS,test_dev->count);
input_sync(test_dev->test_input_dev);
test_dev->count++;
if(test_dev->count ==100)
test_dev->count =0;
printk( "current jiffies is %ld\n", jiffies);
printk( "count is %d\n", test_dev->count);
}
static int __init demo_init(void) //加载函数
{
int ret =0;
test_dev = kzalloc(sizeof(struct test_device),GFP_KERNEL);
if(test_dev == NULL)
{
printk("Failed to allocate driver struct\n");
ret = -ENOMEM;
goto err_kzalloc_device;
}
test_dev->test_input_dev = input_allocate_device();
if(test_dev->test_input_dev == NULL) {
printk( "Failed to allocate input dev\n");
ret = -ENOMEM;
goto err_input_allocate_device;
}
test_dev->test_input_dev->name = "test_input";
set_bit(EV_ABS, test_dev->test_input_dev->evbit);
input_set_abs_params(test_dev->test_input_dev, ABS_GAS, MAG_MAX_NEG, MAG_MAX_POS, 0, 0);
ret =input_register_device(test_dev->test_input_dev);
if(ret)
{
printk( "Failed to input_unregister_device\n");
goto err_input_unregister_device;
}
//初始化定时器,注册定时器
test_dev->count =0;
init_timer(&test_dev->s_timer);
test_dev->s_timer.function = second_timer_handle;
test_dev->s_timer.expires = jiffies + HZ;
add_timer(&test_dev->s_timer);
printk("demo_init");
return ret;
err_input_unregister_device:
input_free_device(test_dev->test_input_dev);
err_input_allocate_device:
kfree(test_dev);
err_kzalloc_device:
return ret;
}
static void __exit demo_exit(void) //卸载函数
{
del_timer(&test_dev->s_timer);
input_unregister_device(test_dev->test_input_dev);
input_free_device(test_dev->test_input_dev);
kfree(test_dev);
printk("demo_exit");
}
module_init(demo_init);
module_exit(demo_exit);
(二)input测试代码
#include
#include
int main(int argc, const char *argv[])
{
int fd;
struct input_event env;
int c = 0;
int i;
fd =open("/dev/input/event4",0666);
if(fd<=0)
{
puts("open error");
return -1;
}
while(1)
{
c=read(fd,&env,sizeof(struct input_event));
if(c<0)
{
perror("read error");
return -1;
}
printf("type:%d code:%d value:%d\n",
env.type,
env.code,
env.value);
}
return 0;
}
(三)代码现象