2. 輸入事件程式碼

輸入協議使用型別和程式碼的對映來向用戶空間表達輸入裝置值。本文件描述了這些型別和程式碼,以及它們如何以及何時可以使用。

單個硬體事件會生成多個輸入事件。每個輸入事件包含單個數據項的新值。一種特殊的事件型別 EV_SYN 用於將輸入事件分離成在同一時刻發生的輸入資料更改資料包。在下文中,術語“事件”指包含型別、程式碼和值的單個輸入事件。

輸入協議是一種有狀態協議。只有當事件程式碼的值發生變化時,事件才會被髮出。然而,狀態在 Linux 輸入子系統內部維護;驅動程式不需要維護狀態,並且可以嘗試發出未更改的值而不會造成損害。使用者空間可以使用 linux/input.h 中定義的 EVIOCG* ioctl 來獲取事件程式碼值的當前狀態。裝置支援的事件報告也由 sysfs 在 class/input/event*/device/capabilities/ 中提供,裝置的屬性則在 class/input/event*/device/properties 中提供。

2.1. 事件型別

事件型別是邏輯輸入構造下程式碼的集合。每種型別都有一組適用於生成事件的程式碼。有關每種型別的有效程式碼的詳細資訊,請參閱“程式碼”部分。

  • EV_SYN

    • 用作分隔事件的標記。事件可以按時間或空間分隔,例如多點觸控協議。

  • EV_KEY

    • 用於描述鍵盤、按鈕或其他類似按鍵裝置的狀​​態變化。

  • EV_REL

    • 用於描述相對軸值變化,例如將滑鼠向左移動 5 個單位。

  • EV_ABS

    • 用於描述絕對軸值變化,例如描述觸控式螢幕上觸控的座標。

  • EV_MSC

    • 用於描述不屬於其他型別的雜項輸入資料。

  • EV_SW

    • 用於描述二值狀態輸入開關。

  • EV_LED

    • 用於開啟和關閉裝置上的 LED。

  • EV_SND

    • 用於向裝置輸出聲音。

  • EV_REP

    • 用於自動重複裝置。

  • EV_FF

    • 用於向輸入裝置傳送力反饋命令。

  • EV_PWR

    • 一種用於電源按鈕和開關輸入的特殊型別。

  • EV_FF_STATUS

    • 用於接收力反饋裝置狀態。

2.2. 事件程式碼

事件程式碼定義了事件的精確型別。

2.2.1. EV_SYN

EV_SYN 事件的值未定義。它們的用法僅由它們在 evdev 事件流中傳送的時間來定義。

  • SYN_REPORT

    • 用於同步事件並將它們分離成在同一時刻發生的輸入資料更改資料包。例如,滑鼠的移動可以為一次移動設定 REL_X 和 REL_Y 值,然後發出一個 SYN_REPORT。下一次移動將發出更多的 REL_X 和 REL_Y 值併發送另一個 SYN_REPORT。

  • SYN_CONFIG

    • 待定

  • SYN_MT_REPORT

  • SYN_DROPPED

    • 用於指示 evdev 客戶端事件佇列中的緩衝區溢位。客戶端應忽略所有事件,包括下一個 SYN_REPORT 事件,並查詢裝置(使用 EVIOCG* ioctl)以獲取其當前狀態。

2.2.2. EV_KEY

EV_KEY 事件的形式為 KEY_<name> 或 BTN_<name>。例如,KEY_A 用於表示鍵盤上的“A”鍵。當鍵被按下時,會發出一個帶有鍵程式碼且值為 1 的事件。當鍵被釋放時,會發出一個值為 0 的事件。有些硬體在鍵重複時傳送事件。這些事件的值為 2。通常,KEY_<name> 用於鍵盤按鍵,而 BTN_<name> 用於其他型別的瞬時開關事件。

一些 EV_KEY 程式碼具有特殊含義

  • BTN_TOOL_<name>

    • 這些程式碼與輸入觸控板、數位板和觸控式螢幕結合使用。這些裝置可以使用手指、筆或其他工具。當事件發生並使用工具時,相應的 BTN_TOOL_<name> 程式碼應設定為值 1。當工具不再與輸入裝置互動時,BTN_TOOL_<name> 程式碼應重置為 0。所有觸控板、數位板和觸控式螢幕在生成事件時應至少使用一個 BTN_TOOL_<name> 程式碼。同樣,所有觸控板、數位板和觸控式螢幕一次只能匯出一個 BTN_TOOL_<name>。為了不破壞現有的使用者空間,建議不要在一個 EV_SYN 幀中切換工具,而是首先將舊的 BTN_TOOL_<name> 傳送為 0,然後傳送一個 SYN_REPORT,再將新的 BTN_TOOL_<name> 設定為 1。

  • BTN_TOUCH

    BTN_TOUCH 用於觸控接觸。當輸入工具被確定為處於有意義的物理接觸中時,此屬性的值必須設定為 1。有意義的物理接觸可以指任何接觸,也可以指由實現定義的屬性決定的接觸。例如,觸控板可能僅當觸控壓力升至某個值以上時才將值設定為 1。BTN_TOUCH 可以與 BTN_TOOL_<name> 程式碼結合使用。例如,一支筆式數位板可以在筆懸停在數位板表面上方但未觸及時將 BTN_TOOL_PEN 設定為 1,將 BTN_TOUCH 設定為 0。

注意:為了使舊版 mousedev 模擬驅動程式正常工作,BTN_TOUCH 必須是同步幀中發出的第一個 evdev 程式碼。

注意:歷史上,帶有 BTN_TOOL_FINGER 和 BTN_TOUCH 的觸控裝置被使用者空間解釋為觸控板,而沒有 BTN_TOOL_FINGER 的類似裝置則被解釋為觸控式螢幕。為了與當前使用者空間向後相容,建議遵循此區分。將來,這種區分將被棄用,並使用 linux/input.h 中定義的裝置屬性 ioctl EVIOCGPROP 來傳達裝置型別。

  • BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP

    • 這些程式碼表示觸控板或觸控式螢幕上的一指、二指、三指和四指互動。例如,如果使用者使用兩根手指在觸控板上移動以滾動螢幕內容,則在移動期間應將 BTN_TOOL_DOUBLETAP 設定為值 1。請注意,所有 BTN_TOOL_<name> 程式碼和 BTN_TOUCH 程式碼在目的上是正交的。由手指觸控生成的觸控板事件應為每個組中的一個程式碼生成事件。在任何同步幀期間,這些 BTN_TOOL_<name> 程式碼中最多隻能有一個值為 1。

注意:歷史上,一些驅動程式在同一個同步幀中發出了多個指計數程式碼,值為 1。此用法已棄用。

注意:在多點觸控驅動程式中,應使用input_mt_report_finger_count()函式發出這些程式碼。有關詳細資訊,請參閱多點觸控 (MT) 協議

2.2.3. EV_REL

EV_REL 事件描述屬性的相對變化。例如,滑鼠可能向左移動一定數量的單位,但其在空間中的絕對位置是未知的。如果絕對位置已知,則應使用 EV_ABS 程式碼而不是 EV_REL 程式碼。

一些 EV_REL 程式碼具有特殊含義

  • REL_WHEEL, REL_HWHEEL

    • 這些程式碼分別用於垂直和水平滾輪。該值是滾輪上移動的棘齒數,其物理尺寸因裝置而異。對於高解析度滾輪,這可能是基於高解析度滾動事件的近似值,請參閱 REL_WHEEL_HI_RES。這些事件程式碼是傳統程式碼,如果可用,應優先使用 REL_WHEEL_HI_RES 和 REL_HWHEEL_HI_RES。

  • REL_WHEEL_HI_RES, REL_HWHEEL_HI_RES

    • 高解析度滾輪資料。累積值 120 代表移動一個棘齒。對於不提供高解析度滾動的裝置,該值始終是 120 的倍數。對於提供高解析度滾動的裝置,該值可以是 120 的分數。

      如果垂直滾輪支援高解析度滾動,除了 REL_WHEEL 或 REL_HWHEEL 之外,還會發出此程式碼。REL_WHEEL 和 REL_HWHEEL 可能是基於高解析度滾動事件的近似值。無法保證在高解析度 REL_WHEEL 或 REL_HWHEEL 事件發生時,高解析度資料是 120 的倍數。

2.2.4. EV_ABS

EV_ABS 事件描述屬性的絕對變化。例如,觸控板可以發出觸控位置的座標。

一些 EV_ABS 程式碼具有特殊含義

  • ABS_DISTANCE

    • 用於描述工具與互動表面的距離。此事件僅當工具懸停時(即靠近裝置且 BTN_TOUCH 程式碼的值為 0 時)才應發出。如果輸入裝置可以在三維空間中自由使用,則應考慮使用 ABS_Z。

    • 當工具進入可檢測範圍時,BTN_TOOL_<name> 應設定為 1;當工具離開可檢測範圍時,應設定為 0。BTN_TOOL_<name> 指示硬體當前檢測到的工具型別,並且獨立於 ABS_DISTANCE 和/或 BTN_TOUCH。

  • ABS_PROFILE

    • 用於描述多值配置檔案開關的狀態。僅當所選配置檔案更改時才發出事件,指示新選擇的配置檔案值。

  • ABS_MT_<name>

  • ABS_PRESSURE/ABS_MT_PRESSURE

    • 對於觸控裝置,許多裝置將接觸尺寸轉換為壓力。手指隨著壓力變平,導致更大的接觸面積,因此壓力和接觸尺寸直接相關。其他裝置則不然,例如帶有真正壓力感測器(“壓力板”)的數字化儀和觸控板。

      裝置應設定軸的解析度,以指示壓力是否以可測量的單位表示。如果解析度為零,則壓力資料為任意單位。如果解析度非零,則壓力資料以單位/克表示。例如,解析度為 1 時值為 10 表示 10 克,解析度為 1000 時值為 10 表示 10 微克。

2.2.5. EV_SW

EV_SW 事件描述有狀態的二進位制開關。例如,SW_LID 程式碼用於表示筆記型電腦蓋子何時關閉。

繫結到裝置或從掛起恢復時,驅動程式必須報告當前的開關狀態。這確保了裝置、核心和使用者空間狀態的同步。

恢復時,如果開關狀態與掛起前相同,則輸入子系統將過濾掉重複的開關狀態報告。驅動程式不需要在任何時候保持開關的狀態。

2.2.6. EV_MSC

EV_MSC 事件用於不屬於其他類別的輸入和輸出事件。

一些 EV_MSC 程式碼具有特殊含義

  • MSC_TIMESTAMP

    • 用於報告自上次重置以來的微秒數。此事件應編碼為 uint32 值,允許其迴繞,沒有特殊後果。假定兩個連續事件之間的時間差在合理的時間尺度(小時)內是可靠的。可能會發生重置為零的情況,在這種情況下,自上次事件以來的時間是未知的。如果裝置不提供此資訊,則驅動程式不得將其提供給使用者空間。

2.2.7. EV_LED

EV_LED 事件用於輸入和輸出,以設定和查詢裝置上各種 LED 的狀態。

2.2.8. EV_REP

EV_REP 事件用於指定自動重複事件。

2.2.9. EV_SND

EV_SND 事件用於向簡單的聲音輸出裝置傳送聲音命令。

2.2.10. EV_FF

EV_FF 事件用於初始化支援力反饋的裝置並使此類裝置進行反饋。

2.2.11. EV_PWR

EV_PWR 事件是一種特殊型別的事件,專門用於電源管理。其用法尚未明確定義。待稍後處理。

2.3. 裝置屬性

通常,使用者空間根據裝置發出的資料(即事件型別)來設定輸入裝置。如果兩個裝置發出相同的事件型別,則可以透過裝置屬性的形式提供附加資訊。

2.3.1. INPUT_PROP_DIRECT + INPUT_PROP_POINTER

INPUT_PROP_DIRECT 屬性表示裝置座標應直接對映到螢幕座標(不考慮簡單的變換,如縮放、翻轉和旋轉)。非直接輸入裝置需要非簡單的變換,例如觸控板的絕對到相對變換。典型的直接輸入裝置:觸控式螢幕、繪圖板;非直接裝置:觸控板、滑鼠。

INPUT_PROP_POINTER 屬性表示裝置不在螢幕上轉置,因此需要使用螢幕上的指標來跟蹤使用者的移動。典型的指標裝置:觸控板、數位板、滑鼠;非指標裝置:觸控式螢幕。

如果 INPUT_PROP_DIRECT 和 INPUT_PROP_POINTER 都沒有設定,則該屬性被視為未定義,並且應以傳統方式(使用發出的事件型別)推斷裝置型別。

2.3.2. INPUT_PROP_BUTTONPAD

對於按鈕位於表面下方,使得按下觸控板會導致按鈕點選的觸控板,應設定此屬性。這在 Clickpad 筆記型電腦和 2009 年及以後的 Macbooks 中很常見。

最初,buttonpad 屬性在 bcm5974 驅動程式版本欄位中被編碼為“整合按鈕”。為了向後相容,使用者空間中需要檢查這兩種方法。

2.3.3. INPUT_PROP_SEMI_MT

一些觸控板(在 2008 年至 2011 年間最常見)可以檢測到多個觸點的存在,但無法解析各個位置;只知道觸點數量和矩形形狀。對於此類觸控板,應設定 SEMI_MT 屬性。

根據裝置的不同,該矩形可能包圍所有觸控(如邊界框),或者只包圍其中一部分,例如最近的兩次觸控。這種多樣性使得矩形的使用受限,但通常可以從中提取一些手勢。

如果未設定 INPUT_PROP_SEMI_MT,則假定該裝置是真正的 MT 裝置。

2.3.4. INPUT_PROP_TOPBUTTONPAD

一些筆記型電腦,特別是聯想 40 系列,提供指點杆裝置,但沒有與指點杆裝置相關的物理按鈕。相反,觸控板的頂部區域被標記,以顯示用於指點杆的左、中、右按鈕的視覺/觸覺區域。

如果設定了 INPUT_PROP_TOPBUTTONPAD,使用者空間應相應地模擬按鈕。此屬性不影響核心行為。核心不為此類裝置提供按鈕模擬,但將其視為任何其他 INPUT_PROP_BUTTONPAD 裝置。

2.3.5. INPUT_PROP_ACCELEROMETER

此裝置上的方向軸(絕對和/或相對 x、y、z)表示加速度計資料。一些裝置還報告陀螺儀資料,這些裝置可以透過旋轉軸(絕對和/或相對 rx、ry、rz)報告。

所有其他軸保留其含義。裝置不得在同一事件節點上混合常規方向軸和加速度計軸。

2.4. 指南

以下指南確保了正確的單點觸控和多指功能。有關多點觸控功能的更多資訊,請參閱多點觸控 (MT) 協議文件。

2.4.1. 滑鼠

滑鼠移動時必須報告 REL_{X,Y}。必須使用 BTN_LEFT 來報告主按鈕按下。應使用 BTN_{MIDDLE,RIGHT,4,5,etc.} 來報告裝置的更多按鈕。如果可用,應使用 REL_WHEEL 和 REL_HWHEEL 來報告滾輪事件。

2.4.2. 觸控式螢幕

必須報告帶有觸控位置的 ABS_{X,Y}。必須使用 BTN_TOUCH 來報告螢幕上何時有觸控活動。不得將 BTN_{MOUSE,LEFT,MIDDLE,RIGHT} 作為觸控接觸的結果進行報告。在可能的情況下,應報告 BTN_TOOL_<name> 事件。

對於新硬體,應設定 INPUT_PROP_DIRECT。

2.4.3. 觸控板

僅提供相對位置資訊的傳統觸控板必須報告上述類似滑鼠的事件。

提供絕對觸控位置的觸控板必須報告觸控位置的 ABS_{X,Y}。應使用 BTN_TOUCH 來報告觸控板上何時有觸控活動。如果支援多指,應使用 BTN_TOOL_<name> 來報告觸控板上的活動觸控數量。

對於新硬體,應設定 INPUT_PROP_POINTER。

2.4.4. 數位板

當手寫筆或其他工具在數位板上處於活動狀態時,必須報告 BTN_TOOL_<name> 事件。必須報告帶有工具位置的 ABS_{X,Y}。應使用 BTN_TOUCH 來報告工具何時與數位板接觸。應使用 BTN_{STYLUS,STYLUS2} 來報告工具本身的按鈕。除了 BTN_{MOUSE,LEFT} 之外,任何按鈕都可用於數位板上的按鈕。BTN_{0,1,2,etc} 是未標記按鈕的通用程式碼。不要使用具有特定含義的按鈕,如 BTN_FORWARD,除非裝置上已為此目的標記了該按鈕。

對於新硬體,應同時設定 INPUT_PROP_DIRECT 和 INPUT_PROP_POINTER。