UInput driver分析

http://blog.sina.com.cn/s/blog_602f87700100llew.html

 

UInput driver分析

(2010-09-03 17:02:44)
标签:

it

分类: linux_kernel

作者:Sam (甄峰) sam_code@hotmail.com

 

Sam在开发中需要在用户态程序中模拟系统Keyboard,Mouse event. 开始想用之前在2.4 Kernel中开发的一个Virtual Input Driver,在改写为2.6Kernel模式后,连续尝试了2个嵌入式平台,发现竟然都缺乏必要的内核符号。突然想起之前在哪看到过Input User level driver这样的东西。赶快问了问Google老师。发现它就是UInput。(发现TCC8900所使用的IR Remote Controller Driver与Sam很多年前在S3C2440A上开发的IR Remote Controller Driver做法几乎完全一致,嘿嘿)

 

赶快以Module形式编译uinput.

先察看drivers/input/misc/Kconfig,看到INPUT_UINPUT(User level driver support)前提为INPUT_MISC。

于是在make menuconfig中

Device Drivers  --->

Input device support  --->

[*]   Miscellaneous devices  --->

<M>   User level driver support 

呵呵,现在才理解misc是各种其它非标准设备的意思。

#make

将其编译为uinput.ko

 

读uinput.c之前,最好先读 driver/char/misc.c

 

解析 misc.c

 

1. init函数

subsys_initcall(misc_init);
insmod misc时,会调用misc_init()

misc_init()使用比较老的方式创建字符设备driver:

register_chrdev(MISC_MAJOR,"misc",&misc_fops)

主设备号为:MISC_JAJOR=10

driver名字为 misc, 在/proc/device中出现。

driver处理程序为misc_fops.

 

2. driver处理程序:

static const struct file_operations misc_fops = {
 .owner  = THIS_MODULE,
 .open  = misc_open,
};
也就是说:它只赋值了open--misc_open()

换句话说,当用户在使用系统调用open主设备号为10的device时,kernel会最终调用misc_open().

 

misc_open():

它首先察看全局链表misc_list 成员中是否有次设备号与open()参数inode的次设备号相同。

如果有,则将链表中c->fops取出,并用它取代参数2 file中的fops.

并调用c->fops->open(inode, file)

注意:这里非常关键,因为misc是一系列driver的组合。各个driver所做工作完全不同,他们之间使用次设备号区分。

但Kernel只关心主设备号,也就是说,它只会把主设备号对应的file给对应出来。所以在open()时,需要使用次设备号作标记,替换对应driver的file(open()的参数2)的fops.

 

3.int misc_register(struct miscdevice * misc)

查全局链表misc_list内容。如果需要注册的参数misc的子设备号在链表misc_list中已经存在。则返回busy.

 

如果注册的参数misc的子设备号为MISC_DYNAMIC_MINOR(255,动态子设备号)。则从misc全局子设备号(misc_minors)中取出一个未用的来使用。并将misc_minors中对应子设备号标记为已用。

 

建立dev_t (主,次设备号)

 

并经参数misc加入到misc_list中去。 

 

这样,就很清楚misc的处理了。先使用misc_register()注册一个次设备号对应driver.并将其放入misc_list链表。当用户使用系统调用open主设备号为10的device时,则在misc_list寻找device(也就是node)对应的次设备号fops对应file的对应fops.

 

 

 

 

 解析 uinput.c

 

1. init函数

 module_init(uinput_init);
insmod uinput时,会调用uinput_init()

它调用misc_register(&uinput_misc);

请注意参数uinput_misc。

static struct miscdevice uinput_misc = {
 .fops  = &uinput_fops,
 .minor  = UINPUT_MINOR, (223)
 .name  = UINPUT_NAME,  (uinput)
};

注册后,当用户使用系统调用open主设备号为10,次设备号为223的node时,则使用uinput_fops取代file->fops.

且同时调用fops->open()

 

2. open函数:

创建结构体uinput_device 实体,并将file->private_data 指向该实体。

 

struct uinput_device {
 struct input_dev *dev;
 struct mutex  mutex;
 enum uinput_state state;
 wait_queue_head_t waitq;
 unsigned char  ready;
 unsigned char  head;
 unsigned char  tail;
 struct input_event buff[UINPUT_BUFFER_SIZE];

 struct uinput_request *requests[UINPUT_NUM_REQUESTS];
 wait_queue_head_t requests_waitq;
 spinlock_t  requests_lock;
};

 

posted @ 2015-01-26 20:13  alxe_yu  阅读(221)  评论(0)    收藏  举报