设为首页 收藏本站
查看: 630|回复: 0

[经验分享] linux驱动——input输入子系统(1)—输入子系统核心层(Input Core)

[复制链接]
累计签到:2 天
连续签到:1 天
发表于 2015-12-10 08:41:34 | 显示全部楼层 |阅读模式
  1、
   DSC0000.jpg

  上图是input输入子系统框架,输入子系统由输入子系统核心层( Input Core ),驱动层和事件处理层(EventHandler)三部份组成。一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 inputdriver -> Input core ->Event handler -> userspace 到达用户空间传给应用程序。


  subsys_initcall(input_init);
module_exit(input_exit);

static int __init input_init(void)
{
int err;

err = class_register(&input_class);//注册一个名为input的类
  其中有:



  • struct class input_class = {

  • .name = "input",

  • };

  • if (err) {

  • printk(KERN_ERR "input: unable to register input_dev class\n");

  • return err;

  • }



  • err = input_proc_init();

  • if (err)

  • goto fail1;
  err = register_chrdev(INPUT_MAJOR, "input", &input_fops);注册了主设备号为INPUT_MAJOR的字符设备,操作函数集是:input_fops,如下所示:



  • static const struct file_operations input_fops = {

  • .owner = THIS_MODULE,

  • .open = input_open_file,

  • };

  • if (err) {

  • printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);

  • goto fail2;

  • }



  • return 0;





  • fail2: input_proc_exit();

  • fail1: class_unregister(&input_class);

  • return err;

  • }

  • static void __exit input_exit(void)  //做和input_init函数做相反的工作

  • {

  • input_proc_exit();

  • unregister_chrdev(INPUT_MAJOR, "input");

  • class_unregister(&input_class);

  • }

  2.1、接着看下input_open_file函数,源码如下:



  • static int input_open_file(struct inode *inode, struct file *file)

  • {

  • struct input_handler *handler;

  • const struct file_operations *old_fops, *new_fops = NULL;

  • int err;



  • lock_kernel();

  • /* No load-on-demand here? */

  • handler = input_table[iminor(inode) >> 5];
  其中iminor(inode)为打开文件所对应的次设备号。input_table是一个structinput_handler全局数组,只有8个元素,其定义为:
static struct input_handler *input_table[8];

  首先将设备结点的次设备号右移5位做为索引值到input_table中取对应项,从这里也可以看到,一个handler代表32(1> 5] = handler,其将handler赋给了input_table数组,所使用的规则也是右移5位。

  /**
* struct input_handler - implements one of interfaces for input devices
* @private: driver-specific data
* @event: event handler. This method is being called by input core with
* interrupts disabled and dev->event_lock spinlock held and so
* it may not sleep
* @connect: called when attaching a handler to an input device
* @disconnect: disconnects a handler from input device
* @start: starts handler for given handle. This function is called by
* input core right after connect() method and also when a process
* that "grabbed" a device releases it
* @fops: file operations this driver implements
* @minor: beginning of range of 32 minors for devices this driver
* can provide
* @name: name of the handler, to be shown in /proc/bus/input/handlers
* @id_table: pointer to a table of input_device_ids this driver can
* handle
* @blacklist: pointer to a table of input_device_ids this driver should
* ignore even if they match @id_table
* @h_list: list of input handles associated with the handler
* @node: for placing the driver onto input_handler_list
*
* Input handlers attach to input devices and create input handles. There
* are likely several handlers attached to any given input device at the
* same time. All of them will get their copy of input event generated by
* the device.
*
* Note that input core serializes calls to connect() and disconnect()
* methods.
*/
struct input_handler {


void *private;


void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
void (*start)(struct input_handle *handle);


const struct file_operations *fops;
int minor;
const char *name;


const struct input_device_id *id_table;
const struct input_device_id *blacklist;


struct list_head h_list;
struct list_head node;
};


if (!handler || !(new_fops = fops_get(handler->fops))) {
//检查handler是否存在
err = -ENODEV;
goto out;
}


/*
* That's _really_ odd. Usually NULL ->open means "nothing special",
* not "no device". Oh, well...
*/
if (!new_fops->open) {  //判断new_fops->open是否存在
fops_put(new_fops);
err = -ENODEV;
goto out;
}
old_fops = file->f_op;
file->f_op = new_fops;


err = new_fops->open(inode, file);  //使用新的open函数重新打开设备


if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
out:
unlock_kernel();
return err;
}


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-148985-1-1.html 上篇帖子: Centos 安装后不能上网 解决备忘 下篇帖子: Linux 文件系统层次结构及文件的管理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表