input 就是輸入的意思,因此 input 子系統就是管理輸入的子系統,和 pinctrl 和 gpio 子系統一樣,都是 linux 核心針對某一類裝置而建立的框架。比如按鍵輸入、鍵盤、滑鼠、觸控螢幕等等這些都屬於輸入裝置,不同的輸入裝置所代表的含義不同,按鍵和鍵盤就是代表按鍵資訊,滑鼠和觸控螢幕代表座標資訊,因此在應用層的處理就不同,對於驅動編寫者而言不需要去關心應用層的事情,我們只需要按照要求上報這些輸入事件即可。為此 input子系統分為 input 驅動層、input 核心層、input 事件處理層,最終給使用者空間提供可訪問的裝置節點,input 子系統框架如圖 58.1.1.1 所示:
圖 58.1.1.1 中左邊就是最底層的具體裝置,比如按鍵、usb 鍵盤/滑鼠等,中間部分屬於linux 核心空間,分為驅動層、核心層和事件層,最右邊的就是使用者空間,所有的輸入裝置以檔案的形式供使用者應用程式使用。可以看出 input 子系統用到了我們前面講解的驅動分層模型,我們編寫驅動程式的時候只需要關注中間的驅動層、核心層和事件層,這三個層的分工如下:
驅動層:輸入裝置的具體驅動程式,比如按鍵驅動程式,向核心層報告輸入內容。
核心層:承上啟下,為驅動層提供輸入裝置註冊和操作介面。通知事件層對輸入事件進行處理。
事件層:主要和使用者空間進行互動。
1767
struct class input_class =;.
....
.2414
static
int __init input_init
(void
)2415
2423
2424 err =
input_proc_init()
;2425
if(err)
2426
goto fail1;
2427
2428 err =
register_chrdev_region
(mkdev
(input_major,0)
,2429 input_max_char_devices,
"input");
2430
if(err)
2434
2435
return0;
2436
2437 fail2:
input_proc_exit()
;2438 fail1:
class_unregister
(&input_class)
;2439
return err;
2440
}
1、註冊 input_dev在使用 input 子系統的時候我們只需要註冊乙個 input 裝置即可,input_dev 結構體表示 input
裝置,此結構體定義在include/linux/input.h
檔案中,定義如下(有省略):
示例** 58.1
.2.2 input_dev 結構體
121struct input_dev
;
第 129 行,evbit 表示輸入事件型別,可選的事件型別定義在include/uapi/linux/input.h
檔案
中,事件型別如下:
示例** 58.1
.2.3 事件型別
#define ev_syn 0x00
/* 同步事件 */
#define ev_key 0x01
/* 按鍵事件 */
#define ev_rel 0x02
/* 相對座標事件 */
#define ev_abs 0x03
/* 絕對座標事件 */
#define ev_msc 0x04
/* 雜項(其他)事件 */
#define ev_sw 0x05
/* 開關事件 */
#define ev_led 0x11
/* led */
#define ev_snd 0x12
/* sound(聲音) */
#define ev_rep 0x14
/* 重複事件 */
#define ev_ff 0x15
/* 壓力事件 */
#define ev_pwr 0x16
/* 電源事件 */
#define ev_ff_status 0x17
/* 壓力狀態事件 */
比如本章我們要使用到按鍵,那麼就需要註冊ev_key
事件,如果要使用連按功能的話還需要註冊ev_rep
事件。繼續回到示例** 58.1.2.2 中,第 129 行~137 行的 evbit、keybit、relbit 等等都是存放不同事件對應的值。比如我們本章要使用按鍵事件,因此要用到 keybit,keybit 就是按鍵事件使用的點陣圖,linux 核心定義了很多按鍵值,這些按鍵值定義在include/uapi/linux/input.h
檔案中,按鍵值如下:
示例** 58.1.2.4 按鍵值
215 #define key_reserved 0
216 #define key_esc 1
217 #define key_1 2
218 #define key_2 3
219 #define key_3 4
220 #define key_4 5
221 #define key_5 6
222 #define key_6 7
223 #define key_7 8
224 #define key_8 9
225 #define key_9 10
226 #define key_0 11..
....
2、上報輸入事件當我們向 linux 核心註冊好 input_dev 以後還不能高枕無憂的使用 input 裝置,input 裝置都是具有輸入功能的,但是具體是什麼樣的輸入值 linux 核心是不知道的,我們需要獲取到具體的輸入值,或者說是輸入事件,然後將輸入事件上報給 linux 核心。比如按鍵,我們需要在按鍵中斷處理函式,或者消抖定時器中斷函式中將按鍵值上報給 linux 核心,這樣 linux 核心才能獲取到正確的輸入值。不同的事件,其上報事件的 api 函式不同,我們依次來看一下一些常用的事件上報 api 函式。
首先是 input_event 函式,此函式用於上報指定的事件以及對應的值,函式原型如下:
void
input_event
(struct input_dev *dev,
unsigned
int type,
unsigned
int code,
int value)
函式引數和返回值含義如下: dev:需要上報的 input_dev。 type: 上報的事件型別,比如 ev_key。3、**示例code:事件碼,也就是我們註冊的按鍵值,比如 key_0、key_1 等等。 value:事件值,比如 1 表示按鍵按下,0 表示按鍵鬆開
和按鍵中斷程式類似裝置樹下的中斷,唯一不同的是在keyio_init
函式裡申請完中斷後要申請輸入事件、註冊輸入裝置
/* 申請 input_dev */
keyinputdev.inputdev =
input_allocate_device()
; keyinputdev.inputdev->name = keyinput_name;
keyinputdev.inputdev->evbit[0]
=bit_mask
(ev_key)
|bit_mask
(ev_rep)
;input_set_capability
(keyinputdev.inputdev, ev_key, key_0)
;/* 註冊輸入裝置 */
ret =
input_register_device
(keyinputdev.inputdev);if
(ret)
timer_function定時器功能函式裡改為上報按鍵事件
if
(value ==0)
else
Linux裝置驅動之 input子系統
什麼是input input子系統處理輸入事務,任何輸入裝置的驅動程式都可以通過input輸入子系統提供的介面註冊到核心,利用子系統提供的功能來與使用者空間互動。輸入裝置一般包括鍵盤,滑鼠,觸控螢幕等,在核心中都是以輸入裝置出現的。下面分析input輸入子系統的結構,以及功能實現。linux中inp...
Linux裝置驅動 input輸入子系統
不同的輸入裝置 如按鍵 鍵盤 觸控螢幕 滑鼠等 都有它們的差異性 如中斷 讀鍵值 座標值是裝置相關的 及共同性 如輸入事件的緩衝區管理以及字元裝置驅動的file operations介面則對輸入裝置是通用的 因此在linux核心中設計了input輸入子系統來完成輸入裝置之間的共性工作,而我們只需要使...
Linux裝置驅動開發 input子系統
基於linux 2.6.22.6核心,arm9 s3c2440開發板 原始碼分析 drivers input input.c input init err register chrdev input major,input input fops static const struct file op...