42 linux内核里的输入子系统分析
2017-06-24 15:51
399 查看
linux里的子系统: linux内核里把某种功能类型的源码划分成一个源码模块, 也就是把一类相关的源文件集中起来封装出的功能模块. 如内核源码目录下”drivers/input”里就是输入子系统的源码, “drivers/i2c”就是i2c子系统.
///////////
输入子系统的主要入口在”drivers/input/input.c”源文件:
////////////////////
“drivers/input/evdev.c”可看出, handler对象已实现好用户程序的调用接口功能函数.
/////////////////
输入设备注册时,内核会让输入设备与handler对象进行匹配, 确定输入设备使用哪个handler对象的接口.
输入子系统是linux内核里设备驱动分层思想的一个应用.
我们写的输入设备驱动里只需要实现好硬件部分的功能,再根据硬件的状态提交数据就可以了。不同的输入设备硬件,意味着需要不同的输入设备驱动来实现. 但在linux内核里,用户程序获取输入设备数据的接口都是统一的,标准的接口(struct input_event数据), 所以在内核里把这接口(struct input_handler)独立起来, 供所有输入设备驱动实现数据转交到用户进程.
///////////
输入子系统的主要入口在”drivers/input/input.c”源文件:
static const struct file_operations input_fops = { .owner = THIS_MODULE, .open = input_open_file, .llseek = noop_llseek, }; static int __init input_init(void) { ... err = register_chrdev(INPUT_MAJOR, "input", &input_fops); //当用户程序操作"/dev/input/event*"设备文件时,首先会用到input_fops里的input_open_file函数. ... }; subsys_initcall(input_init); //子系统初始化 static int input_open_file(struct inode *inode, struct file *file) { struct input_handler *handler; //表示一种输入设备对用户程序的接口, 也就是这种接口提供input_event数据到用户进程. 内核里有input_handler的对象evdev_handler(最常用), joydev_handler(手柄类设备), mousedev_handler(鼠标类设备). // 通常情况下输入设备驱动使用的都是evdev_handler, 它可支持键盘,鼠标,触摸屏等输入设备。产生的设备文件为event*. 内核提供的input_handler对象都已经实现好file_operations里的功能函数, 我们的设备驱动只要提供数据给handler对象, 用户进程即可通过调用handler对象获取设备驱动的数据. const struct file_operations *old_fops, *new_fops = NULL; ... handler = input_table[iminor(inode) >> 5]; if (handler) new_fops = fops_get(handler->fops); ... old_fops = file->f_op; file->f_op = new_fops; //像misc子系统一样,更换文件描述符的file_operations对象。更换后,用户调用read, write这此操作时就会调用new_fops里的功能函数 err = new_fops->open(inode, file); if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); } ... }
////////////////////
“drivers/input/evdev.c”可看出, handler对象已实现好用户程序的调用接口功能函数.
static const struct file_operations evdev_fops = { .owner = THIS_MODULE, .read = evdev_read, .write = evdev_write, .poll = evdev_poll, .open = evdev_open, .release = evdev_release, .unlocked_ioctl = evdev_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = evdev_ioctl_compat, #endif .fasync = evdev_fasync, .flush = evdev_flush, .llseek = no_llseek, }; static struct input_handler evdev_handler = { .event = evdev_event, //输入设备驱动里调用input_report..., input_sync这些函数时就是调用handler的evdev_event函数 .connect = evdev_connect, .disconnect = evdev_disconnect, .fops = &evdev_fops, .minor = EVDEV_MINOR_BASE, .name = "evdev", .id_table = evdev_ids, }; static int __init evdev_init(void) { return input_register_handler(&evdev_handler); //handler对象注册时,会加入input_handler_list链表里 }
/////////////////
输入设备注册时,内核会让输入设备与handler对象进行匹配, 确定输入设备使用哪个handler对象的接口.
int input_register_device(struct input_dev *dev) { ... /* Every input device generates EV_SYN/SYN_REPORT events. */ __set_bit(EV_SYN, dev->evbit); ... list_add_tail(&dev->node, &input_dev_list); //注册输入设备时会加入设备链表input_dev_list; list_for_each_entry(handler, &input_handler_list, node) //遍历handler对象的链表 input_attach_handler(dev, handler); //进行匹配 ... }
输入子系统是linux内核里设备驱动分层思想的一个应用.
我们写的输入设备驱动里只需要实现好硬件部分的功能,再根据硬件的状态提交数据就可以了。不同的输入设备硬件,意味着需要不同的输入设备驱动来实现. 但在linux内核里,用户程序获取输入设备数据的接口都是统一的,标准的接口(struct input_event数据), 所以在内核里把这接口(struct input_handler)独立起来, 供所有输入设备驱动实现数据转交到用户进程.
相关文章推荐
- linux内核输入子系统分析
- [转]2.6内核输入子系统分析-续
- LINUX 输入子系统分析
- 内核输入子系统分析
- LINUX 输入子系统架构分析
- linux input输入子系统分析《二》:s3c2440的ADC简单驱动实例分析
- Linux输入子系统分析
- 2.6内核输入子系统分析
- linux输入子系统——深入分析(一)
- [转]linux 输入子系统驱动实例分析--gpio keys
- linux input输入子系统分析《一》:初识input输入子系统
- Linux输入子系统分析 (1) -- 输入子系统初始化
- LINUX 输入子系统分析
- Linux 内核 SCSI IO 子系统分析
- 2.6内核输入子系统分析-续
- Linux输入子系统分析(一)
- Linux输入子系统分析(四)
- Linux输入子系统分析 -- 输入子系统初始化
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- Linux输入子系统分析(五)