Linux input 子系统范例和基本函数解析.doc

上传人:白大夫 文档编号:3255179 上传时间:2019-08-06 格式:DOC 页数:6 大小:29KB
返回 下载 相关 举报
Linux input 子系统范例和基本函数解析.doc_第1页
第1页 / 共6页
亲,该文档总共6页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《Linux input 子系统范例和基本函数解析.doc》由会员分享,可在线阅读,更多相关《Linux input 子系统范例和基本函数解析.doc(6页珍藏版)》请在三一文库上搜索。

1、Linux input 子系统范例和基本函数解析输入子系统是为了将输入设备的功能呈现给应用程序。它支持 鼠标、键盘、蜂鸣器、触摸屏、传感器等需要不断上报数据的设备。简单的例子这个例子中的设备只有一个按键key,当key按下时,将产生中断,内核检测到中断并对其进行处理。#include #include static struct input_dev *button_dev; /*输入设备结构体*/*中断处理函数*/staTIc irqreturn_t button_interrupt(int irq, void *dummy) /*向输入子系统报告产生按键事件*/ input_report_k

2、ey(button_dev, BTN_0, inb(BUTTON_PORT) /*通知接收者,一个报告发送完毕*/ input_sync(button_dev); return IRQ_HANDLED; /?/*加载函数*/staTIc int _init button_init(void) int error; /*申请中断处理函数*/ /返回0表示成功,返回-INVAL表示无效 if(request_irq(BUTTON_IRQ,button_interrupt,0,button,NULL) /*申请失败,则打印出错信息*/ printk(KERN_ERR button.c: Cant a

3、llocate irq %dn, button_irq); return -EBUSY; /*分配一个设备结构体*/ /将在 sys/class/input/input-n 下面创建设备属性文件 button_dev = input_allocate_device(); if (!button_dev) /*判断分配是否成功*/ printk(KERN_ERR button.c: Not enough memoryn); error = -ENOMEM; goto err_free_irq; button_dev-evbit0 = BIT_MASK(EV_KEY); /*设置按键信息*/ bu

4、tton_dev-keybitBIT_WORD(BTN_0) = BIT_MASK(BTN_0); error = input_register_device(button_dev); /*注册一个输入设备*/ if (error) printk(KERN_ERR button.c: Failed to register devicen); goto err_free_dev; return 0; err_free_dev: /*以下是错误处理*/ input_free_device(button_dev); err_free_irq: free_irq(BUTTON_IRQ, button_

5、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);从这个简单的例子中可以看到。在初始化函数 button_init() 中注册了一个中断处理函数,然后调用 input_allocate_device() 函

6、数分配了一个 input_dev 结构体,并调用 input_register_device() 对其进行注册。在中断处理函数 button_interrupt() 中,实例将接收到的按键信息上报给 input 子系统,从而通过 input子系统,向用户态程序提供按键输入信息。input 子系统的关键函数input_allocate_device()input_register_device()-input_attach_handler()-input_match_device()input_allocate_device()这个函数在内存中为输入设备结构体分配一个空间,并对其主要成员进行初始

7、化。其代码如下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 = /*初始化设备的类型*/ dev-dev.class = /*设置为输入设备类*/ device_initialize( /*初始化device结构*/ mutex_init( /*初始化互斥锁*/ spin_lock_init( /*初

8、始化事件自旋锁*/ INIT_LIST_HEAD( /*初始化链表*/ INIT_LIST_HEAD( /*初始化链表*/ _module_get(THIS_MODULE); /*模块引用技术加1*/ return dev;-其返回一个指向 input_dev 类型的指针,该结构体是一个输入设备结构体,包含了输入设备的相关信息(按键码、设备名、支持的事件)。input_register_device()这个函数是输入子系统核心(input core)提供的函数。它将input_dev 结构体注册到输入子系统核心中(input_dev 结构体必须由 input_allocate_device()

9、函数来分配的)。如果函数注册失败,必须调用 input_free_device() 函数来释放分配的空间。如果函数注册成功,在卸载函数中应该调用 input_unregister_device() 函数来注销输入设备结构体。我们看一下函数原型:int input_register_device(struct input_dev *dev) /定义一些函数中将用到的局部变量 staTIc atomic_t input_no = ATOMIC_INIT(0); struct input_handler *handler; const char *path; int error; /设置 input

10、_dev 所支持的事件类型,由 evbit 成员来表示。具体类型在后面归纳。 _set_bit(EV_SYN, dev-evbit); /初始化 timer 定时器,用来处理重复点击按键。(去抖) init_timer( /如果 repREP_DELAY 和 REP_PERIOD 没有设值,则赋默认值。为了去抖。 if (!dev-repREP_DELAY dev-timer.function = input_repeat_key; dev-repREP_DELAY = 250; dev-repREP_PERIOD = 33; /检查下列两个函数是否被定义,没有被定义则赋默认值。 if (!d

11、ev-getkeycode) dev-getkeycode = input_default_getkeycode; /得到指定位置键值 if (!dev-setkeycode) dev-setkeycode = input_default_setkeycode; /设置指定位置键值 /设置 input_dev 中 device 的名字为 inputN /将如 input0 input1 input2 出现在 sysfs 文件系统中 dev_set_name( /将 input-dev 包含的 device 结构注册到 Linux 设备模型中。 /并在文件系统中表现出来 error = devi

12、ce_add( if (error) return error; /打印设备的路径并输出调试信息 path = kobject_get_path( printk(KERN_INFO input: %s as %sn, dev-name ? dev-name : Unspecified device , path ? : N/A); kfree(path); error = mutex_lock_interruptible( if (error) device_del( return error; /将 input_dev 加入 input_dev_list 链表中(这个链表中包含有所有 inp

13、ut 设备) list_add_tail( list_for_each_entry(handler, /调用 input_attatch_handler()函数匹配 handler 和 input_dev。 /这个函数很重要,在后面单独分析。 input_attach_handler(dev, handler); input_wakeup_procfs_readers(); mutex_unlock( return 0;给 evbit 设置的,input_dev所支持的事件类型:#define EV_SYN 0x00 /*表示设备支持所有的事件*/#define EV_KEY 0x01 /*键

14、盘或者按键,表示一个键码*/#define EV_REL 0x02 /*鼠标设备,表示一个相对的光标位置结果*/#define EV_ABS 0x03 /*手写板产生的值,其是一个绝对整数值*/#define EV_MSC 0x04 /*其他类型*/#define EV_LED 0x11 /*LED灯设备*/#define EV_SND 0x12 /*蜂鸣器,输入声音*/#define EV_REP 0x14 /*允许重复按键类型*/#define EV_PWR 0x16 /*电源管理事件*/input_attatch_handler()这个函数用来匹配 input_dev 和 handler

15、,匹配成功才进行关联。函数代码如下static int input_attach_handler(struct input_dev *dev,struct input_handler *handler) / input_device_id 这个结构体表示设备的标识,存储了设备信息。 const struct input_device_id *id; /*输入设备的指针*/ int error; /先判断 handler 的 blacklist 有无赋值,然后判断是否匹配 /blacklist 是一个 input_device_id *类型,指向了一个表,表中存放的是该驱动程序应该忽略的设备 i

16、f (handler-blacklist /* 设备和处理函数之间的匹配 */ /匹配 handler-id_table指向的列表中的设备 和 dev-id 数据 id = input_match_device(handler-id_table, dev); if (!id) return -ENODEV; /匹配成功则调用 handler-connect,连接 handler 和 input_dev error = handler-connect(handler, dev, id);/*连接设备和处理函数*/ if (error return error;input_device_id 结构

17、体的定义:struct input_device_id kernel_ulong_t flags; /*标志信息*/ _u16 bustype; /*总线类型*/ _u16 vendor; /*制造商ID*/ _u16 product; /*产品ID*/ _u16 version; /*版本号*/ . kernel_ulong_t driver_info; /*驱动额外的信息*/;input_match_device()这个函数用来将 input_dev 和 handler 进行匹配。handler-id_table 中定义了其支持 input_dev 设备。static const stru

18、ct input_device_id *input_match_device(const struct input_device_id *id,struct input_dev *dev) int i; /匹配 id 和 dev-id 中的信息 for (; id-flags | id-driver_info; id+) if (id-flags if (id-flags if (id-flags if (id-flags MATCH_BIT(evbit, EV_MAX); MATCH_BIT(keybit, KEY_MAX); MATCH_BIT(relbit, REL_MAX); MATC

19、H_BIT(absbit, ABS_MAX); MATCH_BIT(mscbit, MSC_MAX); MATCH_BIT(ledbit, LED_MAX); MATCH_BIT(sndbit, SND_MAX); MATCH_BIT(ffbit, FF_MAX); MATCH_BIT(swbit, SW_MAX); return id; return NULL;在上面,只有 flags 中的信息匹配成功,或者 flags 没有定义才会调用下面。#define MATCH_BIT(bit, max) for (i = 0; i biti if (i != BITS_TO_LONGS(max)

20、continue;从宏定义中可以看到,只有当 input device和input handler 的 ID 成员在 evbit、keybit、 swbit 项相同才会匹配成功。而且匹配的顺序是从evbit、keybit到swbit。只要有一项不同,就会循环到ID中的下一项进行比较。总结在 input 的分配和注册中,我们分析了四个函数。1. input_allocate_device 在内存中为输入设备结构体分配空间并进行初始化。2. input_register_device()-input_attach_handler()-input_match_device()input_regist

21、er_device将input_dev 结构体注册到输入子系统核心中。主要操作是 初始化 input_dev 并将其 device_add 进 Linux 设备驱动模型中(在文件系统中创建 inputN 等文件);打印其路径;调用 input_attach_handler 匹配 handler 和 input_dev。input_attach_handler匹配 handler 和 input_dev。主要操作是,判断 dev 在不在 devices 的黑名单中,不在就 调用 input_match_device 进行匹配,成功就调用 handler-connect 连接设备和处理函数。input_match_device真正的 将 input_dev 和 handler 进行匹配。主要操作是匹配 id 和 dev-id 中的信息。包括 bustype、vendor、product、version 等;再匹配 evbit 事件类型、keybit 按键类型 等。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1