linux input 子系統例項分析

2021-05-27 13:46:31 字數 4508 閱讀 1233

一,前言:

1, 近日要寫乙個很特殊的鍵盤驅動,故對linux的input子系統分析了一番,寫下分析筆記,以防不日即忘。

2, 使用input子系統的一般流程為:input_allocate_device()申請乙個input_dev裝置——>初始化該input_dev——>input_register_device()向子系統註冊該裝置——>中斷時input_event()向子系統報告事件。此流程一目了然,即使不看input子系統,我們按照它給出的一般流程也可以把自己寫的io驅動加入到input子系統裡去,但input_event()提交完資料後,我們的資料去哪了呢,怎麼處理呢,總覺得雲裡霧裡的,總想一**竟。

3,此分析基於linux核心:2.6.19.2(linux-2.6.29的核心已經對input子系統有所修改,但基本的思路是一致的)

二:下面給出乙個簡單的驅動,用定時器來模擬中斷來提交鍵盤的事件。

#include

#include

#include

#include

#include

#include

#include

#include

/*! input device structure. */

static struct input_dev *serkbd_dev = null;

static struct timer_list report_timer;

static unsigned short t_interval = 2*hz;

#define  keycodes 8

#define press_left_code     30

#define press_right_code    29

#define press_up_code       28

#define press_down_code     27

#define rel_left_code       158

#define rel_right_code      157

#define rel_up_code         156

#define rel_down_code       155

static u16 serkpd_keycodes[keycodes] = else,      /* matches all devices */

,                /* terminating zero entry */

如英文註解,可以匹配所有的input裝置。故每匹配完乙個裝置就呼叫一次它本身的connect():

static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev,

const struct input_device_id *id)

struct input_handle *handle;

if (!(handle = kzalloc(sizeof(struct input_handle), gfp_kernel)))

return null;

handle->dev = dev;

handle->handler = handler;

handle->name = evbug_name

input_open_device(handle);

printk(kern_debug "evbug.c: connected device: /"%s/", %s/n", dev->name, dev->phys);

return handle;

這個函式很簡單,它先申請乙個input_handle結構體,然後把dev和handler賦給它,可以想像一下,handle有兩隻手,乙隻手牽著dev,另乙隻手牽著handler,這樣無論是dev還是handler都可以通過handle找到對方。

4,input_open_device()函式定義如下:

int input_open_device(struct input_handle *handle)

struct input_dev *dev = handle->dev;

int err;

err = mutex_lock_interruptible(&dev->mutex);

if (err)

return err;

handle->open++;

if (!dev->users++ && dev->open)

err = dev->open(dev);

if (err)

handle->open--;

mutex_unlock(&dev->mutex);

return err;

函式很簡單,增加open和users計數,如果第一次開啟,就呼叫dev->open,記得我們的測試驅動中的open函式下定義是這樣的:

static int ser_kpp_open(struct input_dev *dev)

return 0;

什麼都沒做,直接返回0.

5,  最後我們看一下evbug.c裡面的event函式。

static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)

printk(kern_debug "evbug.c: event. dev: %s, type: %d, code: %d, value: %d/n",

handle->dev->phys, type, code, value);

就是input_event()報告事件的時候最終把資料傳到這裡來。這裡只是簡單地把這些資訊輸出來。

四,小結:input_dev在註冊的時候會掛在input_dev_list鍊錶上,然後通過遍歷input_handler_list嘗試匹配已有的每個handler,並把成功匹配的handle掛在dev->h_list鍊錶上,當驅動input_event()報告事件時,就通過dev->h_list鍊錶找到每乙個已匹配的handler,並把事件傳給它們處理。

而與此對應handler註冊時則會把自己掛在input_handler_list上,然後通過遍歷input_dev_list鍊錶,看看有沒有匹配的input_dev, 有則把自己掛在匹配的dev->h_list上。當有事件到來時,input_handler結構體裡面的event函式就可以對事件作處理了。

抓住了這樣乙個主線,整個input子系統的大概來龍去脈就基本清楚了。

下面順便貼一下測試結果:

root@361-21com:/mnt/sd# insmod ser_keyb.ko

input: serkpd as /class/input/input0

ser-keypad init

root@361-21com:/mnt/sd# evbug.c: event. dev: , type: 1, code: 30, value: 1

evbug.c: event. dev: , type: 1, code: 30, value: 0

evbug.c: event. dev: , type: 1, code: 29, value: 1

evbug.c: event. dev: , type: 1, code: 29, value: 0

evbug.c: event. dev: , type: 1, code: 28, value: 1

evbug.c: event. dev: , type: 1, code: 28, value: 0

evbug.c: event. dev: , type: 1, code: 27, value: 1

evbug.c: event. dev: , type: 1, code: 27, value: 0

evbug.c: event. dev: , type: 1, code: 158, value: 1

evbug.c: event. dev: , type: 1, code: 158, value: 0

evbug.c: event. dev: , type: 1, code: 157, value: 1

evbug.c: event. dev: , type: 1, code: 157, value: 0

evbug.c: event. dev: , type: 1, code: 156, value: 1

evbug.c: event. dev: , type: 1, code: 156, value: 0

evbug.c: event. dev: , type: 1, code: 155, value: 1

evbug.c: event. dev: , type: 1, code: 155, value: 0

這兩天頭緒又有點亂,又不知道該幹嗎。其實input的東西遠遠沒有搞明白,但很沒心思搞,抵抗外界干擾的能力太差!

文章出處:

Linux Input子系統 概述

輸入裝置總類繁雜,包括按鍵,鍵盤,觸控螢幕,滑鼠,搖桿等等,它們本身都是字元裝置,不過核心為了能將這些裝置的共性抽象出來,簡化驅動的開發,建立了乙個input子系統。input子系統分為三層,從下至上分別是輸入裝置驅動層,輸入核心層以及輸入事件驅動層。這三層中的輸入核心層和輸入事件驅動層都是核心已經...

Linux INPUT子系統實驗

按鍵 滑鼠 鍵盤 觸控螢幕都屬於輸入裝置,針對這些裝置linux核心提供了乙個叫做input的子系統框架來處理輸入時間,本質上還是字元裝置,只是在此基礎上加上了input框架,使用者只需要負責上報輸入事件,input核心層負責處理這些事件。input子系統分為input驅動層 input核心層 in...

linux input子系統驅動(一)

linux input子系統分析 概述與資料結構 input子系統處理輸入事務,任何輸入裝置的驅動程式都可以通過input輸入子系統提供的介面註冊到核心,利用子系統提供的功能來與使用者空間互動。輸入裝置一般包括鍵盤,滑鼠,觸控螢幕等,在核心中都是以輸入裝置出現的。下面分析input輸入子系統的結構,...