drivers/input/evdev.c
#define evdev_minor_base 64
#define evdev_minors 32
#define evdev_buffer_size 64
struct evdev ;
struct evdev_client ;
evdev_table陣列中的每個成員對應了乙個裝置所對應的evdev類handler,用來記錄核心中所有已經與裝置匹配上的evdev handler的相關資料static struct evdev *evdev_table[evdev_minors];
evdev_init函式內部呼叫核心層提供的註冊函式進行evdev_handler的註冊static int __init evdev_init(void)
evdev_handlerstatic 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_fopsstatic const struct file_operations evdev_fops = ;
evdev_read該函式就是我們在應用層去read核心中實際執行的函式,根據在應用層read所看到的現象,這個函式內部應該會阻塞直到有輸入事件產生,並返回給應用層若干個(取決於count的大小)struct input_event型別的變數
(1)一些錯誤判斷
(2)阻塞等待輸入事件等
(3)將資料返回給應用層retval = wait_event_interruptible(evdev->wait,
client->head != client->tail || !evdev->exist);
這裡的while迴圈是為了當我們傳給evdev_read函式的count值大於乙個struct input_event時,返回給我們多個值while (retval + input_event_size() <= count &&
evdev_fetch_next_event(client, &event))
input_event_to_user函式中呼叫了copy_to_user函式
evdev_connect建立struct evdev型別的指標evdev,成功連線device和handler後這個指標會被記錄在evdev_table陣列中struct evdev *evdev;
這裡的minor指的是次裝置號相對於該類handler的基準次裝置號的偏移int minor;
從evdev_table陣列中找到第乙個沒有被使用的空間,將該位置的下標作為裝置的次裝置號偏移量minorfor (minor = 0; minor < evdev_minors; minor++)
if (!evdev_table[minor])
break;
如果evdev_table中evdev_minors個位置已經被全部使用,則直接退出if (minor == evdev_minors)
為evdev分配空間evdev = kzalloc(sizeof(struct evdev), gfp_kernel);
if (!evdev)
return -enomem;
一些必要的初始化init_list_head(&evdev->client_list);
spin_lock_init(&evdev->client_lock);
mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait);
設定裝置檔案所對應的檔名,我們在sysfs檔案系統和/dev/input下可以看到event0、event1...dev_set_name(&evdev->dev, "event%d", minor);
填充evdev的一些成員,包括次裝置號偏移minor,handle中的device和handler,裝置的裝置號,所屬的類等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;
呼叫核心層提供的函式input_register_handle註冊handleerror = input_register_handle(&evdev->handle);
if (error)
goto err_free_evdev;
該函式內部實際上就是將evdev新增到evdev_table陣列中error = evdev_install_chrdev(evdev);
if (error)
goto err_unregister_handle;
這兩句**等同於我們註冊裝置時呼叫的device_registerdevice_initialize(&evdev->dev);
...error = device_add(&evdev->dev);
if (error)
goto err_cleanup_evdev;
evdev_event核心中獲取時間struct timespec ts;
ktime_get_ts(&ts);
填充struct input_event型別的變數event的成員值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;
事件驅動開發
最近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 核心的輸入子系統為滑鼠 鍵盤 觸控螢幕 遊戲杆等輸入裝置提供了驅動框架。當程式設計師要為自己的輸入裝置編寫驅動程式時,只需要實現從裝置獲取輸入事件即可。至於 輸入事件如何處理,使用者介面如何實現,都由輸入子系統完成。這大大減輕了輸入驅動程式 的編...