当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > input驱动编程实例

input驱动编程实例 时间:2018-09-26      来源:未知

【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;

}

(三)代码现象

上一篇:C语言的内存分配和段错误的处理

下一篇:线程间的互斥锁和条件变量

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部