linux驅動開發擴充套件 輸入事件驅動層原始碼分析

2021-10-10 14:37:07 字數 4078 閱讀 1528

drivers/input/evdev.c

#define evdev_minor_base	64

#define evdev_minors 32

#define evdev_buffer_size 64

struct evdev ;
struct evdev_client ;
static struct evdev *evdev_table[evdev_minors];
evdev_table陣列中的每個成員對應了乙個裝置所對應的evdev類handler,用來記錄核心中所有已經與裝置匹配上的evdev handler的相關資料

evdev_init

static int __init evdev_init(void)

函式內部呼叫核心層提供的註冊函式進行evdev_handler的註冊  

evdev_handler

static struct input_handler evdev_handler = ;
struct input_handler ;
id_table

該資料結構中的資料會在device與handler的匹配函式input_match_device中被使用,用來判斷device和handler能否匹配上

evdev類handler可以與任何input device相匹配

其他類的handler例如mousedev就需要根據它裡面id_table的定義和匹配規則去分析

evdev_fops

static const struct file_operations evdev_fops = ;
evdev_read

該函式就是我們在應用層去read核心中實際執行的函式,根據在應用層read所看到的現象,這個函式內部應該會阻塞直到有輸入事件產生,並返回給應用層若干個(取決於count的大小)struct input_event型別的變數

(1)一些錯誤判斷

(2)阻塞等待輸入事件等

retval = wait_event_interruptible(evdev->wait,

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

(3)將資料返回給應用層

while (retval + input_event_size() <= count &&

evdev_fetch_next_event(client, &event))

這裡的while迴圈是為了當我們傳給evdev_read函式的count值大於乙個struct input_event時,返回給我們多個值

input_event_to_user函式中呼叫了copy_to_user函式

evdev_connect

struct evdev *evdev;
建立struct evdev型別的指標evdev,成功連線device和handler後這個指標會被記錄在evdev_table陣列中

int minor;
這裡的minor指的是次裝置號相對於該類handler的基準次裝置號的偏移

for (minor = 0; minor < evdev_minors; minor++)

if (!evdev_table[minor])

break;

從evdev_table陣列中找到第乙個沒有被使用的空間,將該位置的下標作為裝置的次裝置號偏移量minor

if (minor == evdev_minors)
如果evdev_table中evdev_minors個位置已經被全部使用,則直接退出

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

if (!evdev)

return -enomem;

為evdev分配空間

init_list_head(&evdev->client_list);

spin_lock_init(&evdev->client_lock);

mutex_init(&evdev->mutex);

init_waitqueue_head(&evdev->wait);

一些必要的初始化

dev_set_name(&evdev->dev, "event%d", minor);
設定裝置檔案所對應的檔名,我們在sysfs檔案系統和/dev/input下可以看到event0、event1...

evdev->exist = 1;

evdev->minor = minor;

evdev->handle.dev = input_get_device(dev);

evdev->handle.name = dev_name(&evdev->dev);

evdev->handle.handler = handler;

evdev->handle.private = evdev;

evdev->dev.devt = mkdev(input_major, evdev_minor_base + minor);

evdev->dev.class = &input_class;

evdev->dev.parent = &dev->dev;

evdev->dev.release = evdev_free;

填充evdev的一些成員,包括次裝置號偏移minor,handle中的device和handler,裝置的裝置號,所屬的類等

error = input_register_handle(&evdev->handle);

if (error)

goto err_free_evdev;

呼叫核心層提供的函式input_register_handle註冊handle 

error = evdev_install_chrdev(evdev);

if (error)

goto err_unregister_handle;

該函式內部實際上就是將evdev新增到evdev_table陣列中 

device_initialize(&evdev->dev);

...error = device_add(&evdev->dev);

if (error)

goto err_cleanup_evdev;

這兩句**等同於我們註冊裝置時呼叫的device_register

evdev_event

struct timespec ts;

ktime_get_ts(&ts);

核心中獲取時間

struct input_event event;

event.time.tv_sec = ts.tv_sec;

event.time.tv_usec = ts.tv_nsec / nsec_per_usec;

event.type = type;

event.code = code;

event.value = value;

填充struct input_event型別的變數event的成員值

事件驅動開發

最近android的事件驅動開發風靡一時,一夜之間似乎所有人都在搞這個東西,這裡我就記錄一下我是怎麼把我的應用 tt日程管理 重構為事件驅動模式的。首先呢,最主要的,就是eventbus,github位址,類似的乙個開源專案是otto,github位址,不過我看了好多文章,似乎說otto效能上不如e...

linux驅動開發擴充套件 核心啟動logo

static struct logo data fb logo read mostly 裡面包含了色深depth以及一些調色盤資料和logo資料指標 struct linux logo 該結構體中包含了logo本身的所有資訊以及影象資料,這些資料並沒有直接出現在核心原始碼中,核心原始碼中只能找到lo...

tiny4412 Linux驅動開發之輸入子系統

本次介紹linux的輸入子系統的驅動開發.linux 核心的輸入子系統為滑鼠 鍵盤 觸控螢幕 遊戲杆等輸入裝置提供了驅動框架。當程式設計師要為自己的輸入裝置編寫驅動程式時,只需要實現從裝置獲取輸入事件即可。至於 輸入事件如何處理,使用者介面如何實現,都由輸入子系統完成。這大大減輕了輸入驅動程式 的編...