实例代码如下:

#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h> #include <asm/irq.h>
#include <asm/io.h> #define BUTTON_IRQ 123
static struct input_dev *button_dev ;/*输入设备结构体*/
static irqreturn_t button_interrupt(int irq, void *dummy) /*中断处理函数*/
{
input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & );/*向输入子系统报告产生按键事件*/ ===========》》》》》【3】
input_sync(button_dev);/*通知接受者,一个报告发送完毕*/
return IRQ_HANDLED;
} static int __init button_init(void)
{
int error;
if (request_irq(BUTTON_IRQ, button_interrupt, , "button", NULL)) { /*申请中断*/
printk(KERN_ERR "button.c: Can't allocate irq %d\n", BUTTON_IRQ);
return -EBUSY;
}
button_dev=input_allocate_device();/*分配一个设备结构体*/ ===========》》》》》》【1】
if(!button_dev)
{
printk(KERN_ERR"button.c:Not enough memory\n");
error= -ENOMEM;
goto err_free_irq;
}
button_dev.evbit[] = BIT_MASK(EV_KEY);/*设置按键信息*/ 设置输入设备所支持的事件类型
button_dev.keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); error=input_register_device(button_dev);/*注册一个输入设备*/ ===========》》》》》》【2】
if(error)
{
printk(KERN_ERR"failed to register device\n");
goto err_free_dev;
}
return ; err_free_dev:
input_free_device(button_dev);
err_free_irq:
free_irq(BUTTON_IRQ,button_interrupt);
return error;
} static void __exit button_exit(void)
{
input_unregister_device(button_dev);/*注销按键设备*/
free_irq(BUTTON_IRQ, button_interrupt);/*释放按键占用的中断*/
} module_init(button_init);
module_exit(button_exit);
【1】input_allocate_device()函数分配一个input_dev结构体,输入设备用input_dev结构体描述。
struct input_dev *input_allocate_device(void)
{
struct input_dev *dev; dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);/*分配一个input_dev结构体,并初始化为0*/
if (dev) {
dev->dev.type = &input_dev_type;/*初始化设备类型*/
dev->dev.class = &input_class;/*设置为输入设备类*/
device_initialize(&dev->dev);/*初始化device结构*/
mutex_init(&dev->mutex);/*初始化互斥锁*/
spin_lock_init(&dev->event_lock);/*初始化事件自旋锁*/
INIT_LIST_HEAD(&dev->h_list);/*初始化链表*/
INIT_LIST_HEAD(&dev->node);/*初始化链表*/ __module_get(THIS_MODULE);
} return dev;
}

【2】input_register_device()将input_dev结构体注册到输入子系统核心中。

int input_register_device(struct input_dev *dev)
{
static atomic_t input_no = ATOMIC_INIT();
struct input_handler *handler;
const char *path;
int error; /* Every input device generates EV_SYN/SYN_REPORT events. */
__set_bit(EV_SYN, dev->evbit);/*设置input_dev所支持的事件类型,由input_dev的evbit成员来表示*/ /* KEY_RESERVED is not supposed to be transmitted to userspace. */
__clear_bit(KEY_RESERVED, dev->keybit); /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
input_cleanse_bitmasks(dev); /*
* If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c.
*/
init_timer(&dev->timer);/*初始化一个timer定时器,为处理重复击键*/
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = ;/*这两个值没有定义则设为默认,为自动处理重复按键定义*/
dev->rep[REP_PERIOD] = ;
} /*检查函数是否定义,未定义则使用默认*/
if (!dev->getkeycode)
dev->getkeycode = input_default_getkeycode;/*得到键值*/ if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;/*设置键值*/ dev_set_name(&dev->dev, "input%ld",
(unsigned long) atomic_inc_return(&input_no) - );/*设置input_dev中的device 的名字,以input0/1/2出现在sysfs文件系统中*/ error = device_add(&dev->dev);
if (error)
return error; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s\n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path); error = mutex_lock_interruptible(&input_mutex);
if (error) {
device_del(&dev->dev);
return error;
} list_add_tail(&dev->node, &input_dev_list);/*加入链表*/ list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);/*调用input_attach_handler来匹配input_dev和handler*/===========》》》》》》【2.1】 input_wakeup_procfs_readers(); mutex_unlock(&input_mutex); return ;
}
  其中input_dev所支持的事件类型在include/linux/input.h中定义,如下:
 
 【2.1】input_attach_handler()匹配input_dev和handler。
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error; id = input_match_device(handler, dev);/*handler 与dev之间的匹配*/
if (!id)
return -ENODEV; error = handler->connect(handler, dev, id);/*匹配成功,则调用connect将handler与dev连接起来*/
if (error && error != -ENODEV)
printk(KERN_ERR
"input: failed to attach handler %s to device %s, "
"error: %d\n",
handler->name, kobject_name(&dev->dev.kobj), error); return error;
}

总结【2】:注册input device 就是为input device 设置默认值,并将其挂接到input_dev_list中,并且与挂载在input_handler_list中的handler相匹配,如果匹配成功,则调用connect。

【3】input_report_key()向输入子系统报告发生的事件:

static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_KEY, code, !!value);
}
input_event()报告指定type、value的输入事件:
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
unsigned long flags; if (is_event_supported(type, dev->evbit, EV_MAX)) { spin_lock_irqsave(&dev->event_lock, flags);
add_input_randomness(type, code, value);
input_handle_event(dev, type, code, value);//向输入子系统传送事件信息,,不继续深入分析了-------------------------!!
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
 

linux 输入子系统(2)----简单实例分析系统结构(input_dev层)的更多相关文章

  1. linux 输入子系统(3)----事件处理(input_handler层)

    输入子系统主要设计input_dev.input_handler.input_handle.如下: [1]每个struct input_dev代表一个输入设备 struct input_dev { c ...

  2. linux输入子系统简述【转】

    本文转载自:http://blog.csdn.net/xubin341719/article/details/7678035 1,linux输入子系统简述 其实驱动这部分大多还是转载别人的,linux ...

  3. 7.Linux 输入子系统分析

    为什么要引入输入子系统? 在前面我们写了一些简单的字符设备的驱动程序,我们是怎么样打开一个设备并操作的呢? 一般都是在执行应用程序时,open一个特定的设备文件,如:/dev/buttons .... ...

  4. Linux输入子系统框架分析(1)

    在Linux下的输入设备键盘.触摸屏.鼠标等都能够用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层.事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备 ...

  5. Linux输入子系统详解

    input输入子系统框架  linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(Input ...

  6. linux输入子系统

    linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(InputCore)和输入子系统设备驱 ...

  7. Linux输入子系统(Input Subsystem)

    Linux输入子系统(Input Subsystem) http://blog.csdn.net/lbmygf/article/details/7360084 input子系统分析  http://b ...

  8. linux输入子系统概念介绍

    在此文章之前,我们讲解的都是简单的字符驱动,涉及的内容有字符驱动的框架.自动创建设备节点.linux中断.poll机制.异步通知.同步互斥.非阻塞.定时器去抖动. 上一节文章链接:http://blo ...

  9. linux输入子系统(input subsystem)之evdev.c事件处理过程

    1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...

随机推荐

  1. 1045 access denied for user &#39;root&#39;@&#39;localhost&#39; using password yes的解决方法

    今天把一个项目和项目的数据库都下载到了本地,安装好项目和在本地配置好数据库后,在浏览器登陆项目的后台却出现了以下错误:   后来上百度搜索了好几个答案,都是讲述修改数据库密码的步骤,但是就是没有说明为 ...

  2. 关于CocoaPods update/CocoaPods install 慢、没反应、卡住的解决方案(Pods升级步骤)

    pod管理第三方库带来的便利大家有目共睹,但是--,估计有很多人会遇到这样一种尴尬情况: Pod install 或 Pod update  执行之后,就不动了,一直一个界面简直要崩溃... 网上有很 ...

  3. Cocos2d-JS事件处理机制

    在很多图形用户技术中,事件处理机制一般都有三个重要的角色:事件.事件源和事件处理者.事件源是事件发生的场所,通常就是各个视图或控件,事件处理者是接收事件并对其进行处理的一段程序.事件处理机制中三个角色 ...

  4. html5上传本地图片,在线预览及裁剪(filereader,canvas)

    1 我们常常需要上传头像,点击上传按钮时候需要预览一下,使用filereader方法无需和后台交互,代码如下: //本地图片在上传之前的预览效果 //图片上传预览 function previewIm ...

  5. JS字符串方法总结整理

    //javascript字符串方法总结   1.String.charAt(n)      //取得字符串中的第n个字符   2.String.charCodeAt(n)  //取得字符串中第n个字符 ...

  6. 如何深入学习CSS

    学习CSS有了一定基础后,有的人会觉得好象没有什么学的.因为知道一些基本的理论性的东西.CSS说它容易是因为它的知识点有限.说它难学就在于各浏览器对CSS的支持程度不同.如何深入学习我给出以下几点见意 ...

  7. MUI 返回顶部

    //绑定滚动到顶部按钮事件 if ($("#scroll-up").length > 0) { var scrollToTopBox = $("#scroll-up ...

  8. 【Linux】-NO.7.Linux.3.Maven.1.001-【CentOS 7 Install Maven 3.5】-

    1.0.0 Summary Tittle:[Linux]-NO.7.Linux.3.Maven.1.001-[CentOS 7 Install Maven 3.5]- Style:Linux Seri ...

  9. windows服务写完之后怎么让它跑起来

    当然你可以在命令框里面自己去手动的敲代码,也可以写一个.bat文件一劳永逸......这里我就介绍写.bat文件的方法 就是上图所示的三个东东啦,有了这三个东东,把他们拖到你windows服务的deb ...

  10. Spring Boot 更换 Banner

    Spring 启动时,会有一个Banner图案,这个图案是可以更换的 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ ...