輸入子系統(1) 框架認識

2021-08-19 18:08:29 字數 3228 閱讀 4371

入口函式:

drivers/input/input.c:

input_init > err = register_chrdev(input_major, "input", &input_fops);

static const struct file_operations input_fops = {

.owner = this_module,

.open = input_open_file,

註冊input_handler

1 、放入陣列

input_table[handler->minor >> 5] = handler;

2、放入鍊錶

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

3、 對於每個input_dev,呼叫input_attach_handler

list_for_each_entry(dev, &input_dev_list, node)

input_attach_handler(dev, handler); // 根據input_handler的id_table判斷能否支援這個input_dev

註冊input_device

1、放入鍊錶

list_add_tail(&dev->node, &input_dev_list);

2、對於每個input_handler,呼叫input_attach_handler

list_for_each_entry(handler, &input_handler_list, node)

input_attach_handler(dev, handler); // 根據input_handler的id_table判斷能否支援這個input_dev

input_attach_handler:聯絡input_device和input_handler

1、匹配

id = input_match_device(handler->id_table, dev);

2、連線

error = handler->connect(handler, dev, id);

3、註冊input_dev或input_handler時,會兩兩比較左邊的input_dev和右邊的input_handler,

根據input_handler的id_table判斷input_handler能否支援input_dev,

如果能支援,則呼叫input_handler的connect函式建立"連線"

建立連線handler->connect

1、分配乙個input_handle結構體

2、設定

input_handle.dev = input_dev;  // 指向左邊的input_dev

input_handle.handler = input_handler;  // 指向右邊的input_handler

3、註冊

input_handler->h_list = &input_handle;

inpu_dev->h_list      = &input_handle;

4、例子evdev_connect

// 分配乙個input_handle

evdev = kzalloc(sizeof(struct evdev), gfp_kernel);

// 設定

evdev->handle.dev = dev;  // 指向左邊的input_dev

evdev->handle.name = evdev->name;

evdev->handle.handler = handler;  // 指向右邊的input_handler

evdev->handle.private = evdev;

// 註冊

error = input_register_handle(&evdev->handle);

讀按鍵過程

1、input_open_file

struct input_handler *handler = input_table[iminor(inode) >> 5];

new_fops = fops_get(handler->fops)  //  =>&evdev_fops

file->f_op = new_fops;

err = new_fops->open(inode, file);

evdev_read

// 無資料並且是非阻塞方式開啟,則立刻返回

if (client->head == client->tail && evdev->exist && (file->f_flags & o_nonblock))

return -eagain;

// 否則休眠

retval = wait_event_interruptible(evdev->wait,

client->head != client->tail || !evdev->exist);

3、喚醒:evdev_event

wake_up_interruptible(&evdev->wait);

4、誰來呼叫evdev_event:裝置驅動

在裝置的中斷服務程式裡,確定事件是什麼,然後呼叫相應的input_handler的event處理函式。

例子:(/drivers/input/keyboard/gpio_keys.c)

gpio_keys_isr

// 上報事件

input_event(input, type, button->code, !!state);

input_sync(input);

input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

struct input_handle *handle;

list_for_each_entry(handle, &dev->h_list, d_node)

if (handle->open)

handle->handler->event(handle, type, code, value);

怎麼寫符合輸入子系統框架的驅動程式?

1. 分配乙個input_dev結構體

2. 設定

3. 註冊

4. 硬體相關的**,比如在中斷服務程式裡上報事件

輸入子系統框架之我見

輸入子系統是linux驅動中很重要的一部分,按鍵 觸控螢幕 滑鼠等等的驅動都可以通過這個框架來構建,下面就來總結下輸入子系統的框架。核心層主要在input.c檔案中,class register input class register chrdev input major,input input ...

linux輸入子系統 5 學習框架

注 本系列 input子系統學習系列文章,是我在實際開發過程中遇到也是必須啃下去的第乙個linux驅動,所以有必要記載下來的。由於剛開始未接觸過input子系統,部分資料還是借鑑網路,本系列文章是本人的學習心得以及集百家所長的產物。input subsystem理論部分 input subsyste...

輸入子系統

驅動函式操作步驟 在初始化函式中 1.分配乙個input dev結構體 struct input dev buttons dev buttons dev input allocate device 2.設定 2.1 能產生哪類事件 set bit ev key,buttons dev evbit s...