Linux input子系统分析_3_输入子系统核心分析

本文深入剖析了Linux输入子系统的内部工作原理,包括输入子系统核心的初始化过程、关键函数的作用及其实现方式,以及向上连接事件处理层、向下连接驱动层的接口介绍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.  输入子系统核心分析。

    1.输入子系统核心对应与/drivers/input/input.c文件,这个也是作为一个模块注册到内核的。所以首先分析模块初始化函数。

    static int __init input_init(void)
    {
        int err;
        input_init_abs_bypass();  //这个暂时没有发现是做什么的
        err = class_register(&input_class);  //向内核注册一个类,用于linux设备模型。注册后会在/sys/class下面出现input目录
        if (err) {
            printk(KERN_ERR "input: unable to register input_dev class\n");
            return err;
        }
        err = input_proc_init();  //和proc文件系统有关,暂时不管
        if (err)
            goto fail1;
        err = register_chrdev(INPUT_MAJOR, "input", &input_fops);  //注册字符设备,接口是2.4内核的。以主设备号INPUT_MAJOR,次设备号0-255,注册266个设备,说明input设备最大只能有255个   
        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;
    }

这个函数主要是注册了字符设备,这里和杂项设备的原理是一样,所以input设备也是一类字符设备,只不过操作方法交给了输入子系统。从这里可以看出无论linux设备驱动这块有多复杂,他们都是由一些基本的组件构成的,都是ldd3所讲的基本驱动程序模型。 
    2. 输入子系统的核心其他部分都是提供的接口,向上连接事件处理层,向下连接驱动层。
    向下对驱动层的接口主要有:
   

a. input_allocate_device()    这个函数主要是分配并初始化一个input_dev结构,分配一个input_dev接口,并初始化一些基本的成员,这就是我们不能简单用kmalloc分配input_dev结构的原因,因为缺少了一些初始化。

    /**
     * input_allocate_device - allocate memory for new input device
     *
     * Returns prepared struct input_dev or NULL.
     *
     * NOTE: Use input_free_device() to free devices that have not been
     * registered; input_unregister_device() should be used for already
     * registered devices.
     */
    struct input_dev *input_allocate_device(void)
    {
        struct input_dev *dev;
        dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
        if (dev) {
            dev->dev.type = &input_dev_type;
            dev->dev.class = &input_class;
            device_initialize(&dev->dev);
            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;
    }
    EXPORT_SYMBOL(input_allocate_device);

b. input_unregister_device  注消一个input设备。

    /**
     * input_unregister_device - unregister previously registered device
     * @dev: device to be unregistered
     *
     * This function unregisters an input device. Once device is unregistered
     * the caller should not try to access it as it may get freed at any moment.
     */
    void input_unregister_device(struct input_dev *dev)
    {
        struct input_handle *handle, *next;
        input_disconnect_device(dev);
        mutex_lock(&input_mutex);
        list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
            handle->handler->disconnect(handle);
        WARN_ON(!list_empty(&dev->h_list));
        del_timer_sync(&dev->timer);
        list_del_init(&dev->node);
        input_wakeup_procfs_readers();
        mutex_unlock(&input_mutex);
        device_unregister(&dev->dev);
    }
    EXPORT_SYMBOL(input_unregister_device);

c.    input_event()  --这个函数很重要,是驱动层向input子系统核心报告事件的函数,在事件传递过程中再分析。

    /**
     * input_event() - report new input event
     * @dev: device that generated the event
     * @type: type of the event
     * @code: event code
     * @value: value of the event
     *
     * This function should be used by drivers implementing various input
     * devices to report input events. See also input_inject_event().
     *
     * NOTE: input_event() may be safely used right after input device was
     * allocated with input_allocate_device(), even before it is registered
     * with input_register_device(), but the event will not reach any of the
     * input handlers. Such early invocation of input_event() may be used
     * to 'seed' initial state of a switch or initial position of absolute
     * axis, etc.
     */
    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);
        }
    }
    EXPORT_SYMBOL(input_event);

d.    input_allocate_device    

向上对事件处理层接口主要有:

e.    input_register_handler   注册一个事件处理器

f.    input_register_handle    注册一个input_handle结构


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值