linux input子系統驅動(一)

2021-07-09 09:24:14 字數 4854 閱讀 3452

linux input子系統分析--概述與資料結構

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

一. input子系統結構與功能實現

1. input子系統是分層結構的,總共分為三層: 硬體驅動層,子系統核心層,事件處理層。 

(1)其中硬體驅動層負責操作具體的硬體裝置,這層的**是針對具體的驅動程式的,需要驅動程式的作者來編寫。

(2)子系統核心層是鏈結其他兩個層之間的紐帶與橋梁,向下提供驅動層的介面,向上提供事件處理層的介面。

(3)事件處理層負責與使用者程式打交道,將硬體驅動層傳來的事件報告給使用者程式。

2. 各層之間通訊的基本單位就是事件,任何乙個輸入裝置的動作都可以抽象成一種事件,如鍵盤的按下,觸控螢幕的按下,滑鼠的移動等。事件有三種屬性:型別(type),編碼(code),值(value),input子系統支援的所有事件都定義在input.h中,包括所有支援的型別,所屬型別支援的編碼等。事件傳送的方向是 硬體驅動層-->子系統核心-->事件處理層-->使用者空間

3. 以觸控螢幕為例說明輸入子系統的工作流程:

注:mini2440的觸控螢幕驅動所用驅動層對應的模組檔案為:s3c2410_ts.c,事件處理層對應的模組檔案為 evdev.c

(1)s3c2410_ts模組初始化函式中將觸控螢幕註冊到了輸入子系統中,於此同時,註冊函式在事件處理層煉表中尋找事件處理器,這裡找到的是evdev,並且將驅動與事件處理器掛載。並且在/dev/input中生成裝置檔案event0,以後我們訪問這個檔案就會找的我們的觸控螢幕驅動程式。

(2)應用程式開啟裝置檔案/dev/input/event0,讀取裝置檔案,呼叫evdev模組中read,如果沒有事件程序就會睡眠。  

(3)當觸控螢幕按下,驅動層通過子系統核心將事件(就是x,y座標),傳給事件處理層也就是evdev,evdev喚醒睡眠的程序,將事件傳給程序處理。

二.主要input通用資料結構

1.input_dev 這是input裝置基本的裝置結構,每個input驅動程式中都必須分配初始化這樣乙個結構,成員比較多 

(1)有以下幾個陣列:

[cpp]view plain

copy

unsigned 

long

evbit[bits_to_longs(ev_cnt)];   

//事件支援的型別

// 下面是每種型別支援的編碼

unsigned long

keybit[bits_to_longs(key_cnt)];   

//按鍵  

unsigned long

relbit[bits_to_longs(rel_cnt)];     

unsigned long

absbit[bits_to_longs(abs_cnt)];   

//絕對座標,其中觸控螢幕驅動使用的就是這個

unsigned long

mscbit[bits_to_longs(msc_cnt)];  

unsigned long

ledbit[bits_to_longs(led_cnt)];  

unsigned long

sndbit[bits_to_longs(snd_cnt)];  

unsigned long

ffbit[bits_to_longs(ff_cnt)];  

unsigned long

swbit[bits_to_longs(sw_cnt)];  

evbit[bits_to_longs(ev_cnt)]; 這個陣列以位掩碼的形式,代表了這個裝置支援的事件的型別。設定方式如:

dev->evbit[0] = bit(ev_syn) | bit(ev_key) | bit(ev_abs)

absbit[bits_to_longs(abs_cnt)]; 這個陣列也是以位掩碼的形式,代表這個型別的事件支援的編碼

觸控螢幕驅動支援ev_abs,所以要設定這個陣列, 有乙個專門設定這個陣列的函式input_set_abs_params,**如下:

[cpp]view plain

copy

static

inline

void

input_set_abs_params(

struct

input_dev *dev, 

intaxis, 

intmin, 

intmax, 

intfuzz, 

intflat)    

觸控螢幕驅動中是這樣呼叫的

input_set_abs_params(dev, abs_x, 0, 0x3ff, 0, 0);   //這個是設定ad轉換的x座標

input_set_abs_params(dev, abs_y, 0, 0x3ff, 0, 0);   //這個是設定ad轉換的y座標

input_set_abs_params(dev, abs_pressure, 0, 1, 0, 0); //這個是設定觸控螢幕是否按下的標誌

設定abs_x編碼值範圍為0-0x3ff,因為mini2440的ad轉換出的資料最大為10位,所以不會超過0x3ff。

(2) struct input_id id 成員

這個是標識裝置驅動特徵的

[cpp]view plain

copy

struct

input_id ;  

如果需要特定的事件處理器來處理這個裝置的話,這幾個就非常重要,因為子系統核心是通過他們,將裝置驅動與事件處理層聯絡起來的。但是因為觸控螢幕驅動所用的事件處理器為evdev,匹配所有,所有這個初始化

也無關緊要。

(3) 還有其他一些成員,也比較重要,但是驅動程式可以不用管,都是由子系統核心來處理的。

(4) 可以看出input_dev 結構所屬層為硬體驅動層,以後就用input_dev來表示輸入裝置。

2. input_handler 這是事件處理器的資料結構,代表乙個事件處理器

(1)幾個操作函式

void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);

int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);

void (*disconnect)(struct input_handle *handle);

void (*start)(struct input_handle *handle);

event 函式是當事件處理器接收到了來自input裝置傳來的事件時呼叫的處理函式,負責處理事件,非常重要,在事件傳遞過程中會詳細分析。

connect 函式是當乙個input裝置模組註冊到核心的時候呼叫的,將事件處理器與輸入裝置聯絡起來的函式,也就是將input_dev和input_handler配對的函式。

disconnect 函式實現connect相反的功能。

start 暫時沒有發現有什麼作用。

(2) 兩個id

const struct input_device_id *id_table; //這個是事件處理器所支援的input裝置

const struct input_device_id *blacklist; //這個是事件處理器應該忽略的input裝置

這兩個陣列都會用在connect函式中,input_device_id結構與input_id結構類似,但是input_device_id有乙個flag,用來讓程式選擇比較哪項,如:busytype,vendor還是其他。

(3) 兩個鍊錶

struct list_head

h_list;  //這個鍊錶用來鏈結他所支援的input_handle結構,input_dev與input_handler配對之後就會生成乙個input_handle結構

struct list_head

node;    //鏈結到input_handler_list,這個鍊錶鏈結了所有註冊到核心的事件處理器

(4) 其他的成員一看**就知道是什麼意思,這裡就不說明了。

3.  input_handle 結構體代表乙個成功配對的input_dev和input_handler

[cpp]view plain

copy

struct

input_handle ;  

4. 三個資料結構之間的關係

input_dev 是硬體驅動層,代表乙個input裝置

input_handler 是事件處理層,代表乙個事件處理器

input_handle 個人認為屬於核心層,代表乙個配對的input裝置與input事件處理器

input_dev 通過全域性的input_dev_list鏈結在一起。裝置註冊的時候實現這個操作。

input_handler 通過全域性的input_handler_list鏈結在一起。事件處理器註冊的時候實現這個操作(事件處理器一般核心自帶,一般不需要我們來寫)

input_hande 沒有乙個全域性的鍊錶,它註冊的時候將自己分別掛在了input_dev 和 input_handler 的h_list上了。通過input_dev 和input_handler就可以找到input_handle 在裝置註冊和事件處理器, 註冊的時候都要進行配對工作,配對後就會實現鏈結。通過input_handle也可以找到input_dev和input_handler。

Linux Input子系統 概述

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

Linux INPUT子系統實驗

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

linux input 子系統例項分析

一,前言 1,近日要寫乙個很特殊的鍵盤驅動,故對linux的input子系統分析了一番,寫下分析筆記,以防不日即忘。2,使用input子系統的一般流程為 input allocate device 申請乙個input dev裝置 初始化該input dev input register device...