1. 程式人生 > >Linux--核心Uevent事件機制 與 Input子系統

Linux--核心Uevent事件機制 與 Input子系統

1. 輸入子系統由驅動層、輸入子系統核心、事件處理層三部分組成:
   一個輸入事件,如滑鼠移動、鍵盤按下等通過Driver->Inputcore->Event handler->userspace的順序到達使用者控制元件的應用程式。
2. input子系統仍然是字元裝置驅動程式,但是程式碼量減少很多,input子系統只需要完成兩個工作:初始化和事件報告。

3. (1)上報的大致過程:裝置驅動層->核心層->事件處理層->應用層

   (2)具體呼叫的函式(以evdev為例):
         input_event()->input_handle_event() ->input_pass_event() ->handle->handler->event(handle,type, code, value)
        ->evdev_event() ->evdev_pass_event() ,
        然後通過client->buffer[client->head++]= *event賦值給上層client(是struct evdev_client)

//2. 
Input 子系統之一--框架結構(初始化)
1. 第一層
===============================================================================
使用者空間訪問  <User space>  裝置節點訪問(略)
@@@@@@xx_test.c


2. 第二層
===============================================================================
事件處理層<Event Handler>
/*主要是和使用者空間互動。
(Linux中在使用者空間將所有的裝置都當初檔案來處理,由於在一般的驅動程式中都有提供fops介面,以及在/dev下生成相應的裝置檔案nod,這些操作在輸入子系統中由事件處理層完成)*/
@@@@@@evdev.c等。(以evdev_handler為例)
(1)===>>module_init(evdev_init);  module_exit(evdev_exit);
(2)===>>static int __init evdev_init(void)
{
    return input_register_handler(&evdev_handler);///
                    /*static struct input_handler evdev_handler = {
                        .event        = evdev_event,
                        .connect    = evdev_connect,
                        .disconnect    = evdev_disconnect,
                        .fops        = &evdev_fops,   ////evdev的檔案操作方法
                        .minor        = EVDEV_MINOR_BASE,
                        .name        = "evdev",
                        .id_table    = evdev_ids,*/
};




}

(3)===>>int input_register_handler(struct input_handler *handler)//註冊一個新的event handler
{
    struct input_dev *dev;
    

    list_add_tail(&handler->node, &input_handler_list);

    list_for_each_entry(dev, &input_dev_list, node);
        
        input_attach_handler(dev, handler);////將這個新的event handler 與其相容的input dev繫結在一起

    
}

(4)===>>static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
    

    id = input_match_device(handler, dev);//匹配規則:Input_dev和input_handler匹配後呼叫input_handler的connect。
    
    error = handler->connect(handler, dev, id);//
    
}
(5)===>>建立新的evdev字元裝置節點
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
             const struct input_device_id *id)
{
    struct evdev *evdev;
    int minor;
    

    for (minor = 0; minor < EVDEV_MINORS; minor++)//尋找未使用的minor
        if (!evdev_table[minor])
            break;

    dev_set_name(&evdev->dev, "event%d", minor);
    evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);//建立字元裝置節點event%d
    
    
}

3. 第三層
===============================================================================
核心層<Input Core>
/*承上啟下。為驅動層提供輸入設備註冊與操作介面,如:input_register_device;通知事件處理層對事件進行處理;在/Proc下產生相應的裝置資訊*/
@@@@@@input.c
(1)===>>subsys_initcall(input_init); module_exit(input_exit);
(2)===>>static int __init input_init(void)
{
    
        //建立 sysfs 系統檔案/proc/bus/input:devices && handlers
    err = class_register(&input_class);///  struct class input_class = {
                                                 .name        = "input",
                                                 .devnode    = input_devnode,//kasprintf(GFP_KERNEL, "input/%s", dev_name(dev));
                        
                            };
    //建立proc系統檔案/proc/bus/input:devices && handlers
    err = input_proc_init();
    if (err)
        goto fail1;


       //註冊字元裝置的檔案操作input_fops
    err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
                        static const struct file_operations input_fops = {
                            .owner = THIS_MODULE,
                            .open = input_open_file,///
                            .llseek = noop_llseek,}
}


(3)===>>static int input_open_file(struct inode *inode, struct file *file)
{
    struct input_handler *handler;
    
    /* No load-on-demand here? */
    handler = input_table[iminor(inode) >> 5];
    if (handler)
        new_fops = fops_get(handler->fops);

    
    file->f_op = new_fops;/////根據傳入的inode節點(即:event handler),設定相應的檔案操作方法

    err = new_fops->open(inode, file);////開啟檔案操作方法
    
}



4. 第四層
===============================================================================
裝置驅動層<Input driver>(略)
/*將底層的硬體輸入轉化為統一事件形式,想輸入核心(Input Core)彙報。*/
/*實現裝置驅動核心工作是:向系統報告按鍵、觸控式螢幕等輸入事件(event,通過input_event結構描述),不再需要關心檔案操作介面。
  驅動報告事件經過inputCore和Eventhandler到達使用者空間。*/
@@@@@@mtk_tpd.c  &&  ft5206_driver.c

===============================================================================