配置路線
鍵值變化路徑:
ScanCode --> Keycode Lable --> KeyCode Layout --> KeyLable --> Keycode – > KeyEvent
文件映射路徑:
*.dtsi --> input-event-codes.h --> *.kl --> InputEventLable.h --> kecodes.h --> PhoneWindowManager.java
一、獲取Scancode
當一個紅外遙控器的某個按鍵未適配時,有多種方法查看這個按鍵的scancode。
- 在控制臺輸入
logcat
查看log,如:
meson-ir fe084040.ir: scancode 76 undefined
meson-ir fe084040.ir: no valid key to handle
如果已經適配了就會顯示如下信息:
RemoteIME: keycode: 20, realAction: false
RemoteIME: keycode: 20, realAction: true
- 在控制臺輸入
dmesg -c
:
[ 3195.358431] meson-ir fe084040.ir: scancode 76 undefined
[ 3195.358479] meson-ir fe084040.ir: no valid key to handle
輸入之后再按下按鍵,然后再輸入一次dmesg -c就會顯示上面的內容,如果適配了這個按鍵則不會有任何顯示
3. 在控制臺輸入echo 8 > /proc/sys/kernel/printk
略
可以看到我上面未定義的物理碼值是76,轉換成十六進制后是4c
二、獲取Customcode
不同款式的遙控器有不同的用戶碼,使用cat /sys/devices/virtual/remote/amremote/customcode
命令進行查看遙控器用戶碼,在串口執行該命令后,按下遙控器的任意鍵,再次執行該命令就可以看到你使用這款遙控器的用戶碼了。我這款遙控器的用戶碼為0x7984
三、Scancode和Customcode的映射文件DTSI
path:common/arch/arm64/boot/dts/amlogic/meson-ir-map.dtsi
按照里面原本的內容的樣子添加,注意customcode改成你的遙控器的,里面面的映射如下:
customcode = <0x7984>;
release_delay = <80>;
size = <31>; /*keymap size*/
keymap = <REMOTE_KEY(0x12, KEY_POWER)
REMOTE_KEY(0x06, KEY_HOME)
REMOTE_KEY(0x1A, KEY_BACK)
REMOTE_KEY(0x10, KEY_VOLUMEUP)
前面的這個十六進制數就是scancode的十六進制,當然我們也可以看遙控器的規格書,上面會直接標注好scancode
后面的KEY_XXX需要在linux-event-codes.h文件中定義。
Path: external/u-boot/include/dt-bindings/input/linux-event-codes.h
#define KEY_BACK 158 /* AC Back */
#define KEY_FORWARD 159 /* AC Forward */
這個文件中后面那一列的數字則會在.kl文件中定義
進行到這里的時候,使用getevent -l再按下按鍵就已經能有相應的反饋了。
四、kl文件
4.1 getevent -l
無論是藍牙遙控器還是紅外遙控器,都需要確定其使用的kl (KeyLayoutFile)文件。在安卓shell 環境(串口控制臺)執行命令確認kl 文件:getevent -l
。
首先會顯示當前適配的遙控器列表
add device 1: /dev/input/event1name: "cec_input"
add device 2: /dev/input/event4name: "ir_keypad"
add device 3: /dev/input/event5name: "ir_keypad1"
add device 4: /dev/input/event3name: "gpio_keypad"
add device 5: /dev/input/event2name: "vad_keypad"
add device 6: /dev/input/event0name: "input_btrcu"
add device 7: /dev/input/event6name: "adc_keypad"
以上內容代表了適配了七套遙控器,名稱分別是"cec_input" “ir_keypad” 等
下面我們按下遙控器的某一個按鍵會出現下面的內容
/dev/input/event4: EV_KEY KEY_RIGHT DOWN
/dev/input/event4: EV_SYN SYN_REPORT 00000000
/dev/input/event4: EV_KEY KEY_RIGHT UP
/dev/input/event4: EV_SYN SYN_REPORT 00000000
前兩行表示按鍵被按下,后兩行表示按鍵被釋放
EV_SYN: 用作分隔事件的標記。 事件可以在時間或空間上分開,例如使用多點觸控協議。
EV_KEY: 用于描述鍵盤,按鈕或其他類似鍵的設備的狀態更改。
根據這里顯示顯示的event4我們可以知道我們的遙控設備為"ir_keypad"
4.2 dumpsys input
在前面我們看到我們按下按鍵時相應的是event4,我們可以使用cat /proc/bus/input/devices查看我們系統中連接的輸入設備的詳細信息。
I: Bus=0010 Vendor=0001 Product=0001 Version=0100
N: Name="ir_keypad"
P: Phys=keypad/input0
S: Sysfs=/devices/platform/fe084040.ir/input/input4
U: Uniq=
H: Handlers=rfkill mouse0 event4
B: PROP=0
B: EV=7
B: KEY=ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 0 0 70000 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe
B: REL=103
從我們之前監聽到的按鍵事件我們可以看到處理該按鍵的事件是event4,這里我們對應上的設備名應該是 “ir_keypad”
然后在(串口控制臺)執行命令 dumpsys input,可以根據所連接的遙控器的名稱找到遙控器對應的kl文件。
根據這個IR遙控器設備ir_keypad的設備名,我們找到了下面這段內容:
ir_keypadClasses: 0x00000029Path: /dev/input/event4Enabled: trueDescriptor: d2c52ff0f656fac4cd7b7a118d575e0109a9fe1cLocation: keypad/input0ControllerNumber: 0UniqueId:Identifier: bus=0x0010, vendor=0x0001, product=0x0001, version=0x0100KeyLayoutFile: /vendor/usr/keylayout/Vendor_0001_Product_0001.klKeyCharacterMapFile: /system/usr/keychars/Generic.kcmConfigurationFile:HaveKeyboardLayoutOverlay: falseVideoDevice: <none>
可以看到這里所用到的Android層映射文件為/vendor/usr/keylayout/Vendor_0001_Product_0001.kl
(這里的usr對于不同項目是不一樣的)
我這里是device/amlogic/common/products/mbox/Vendor_0001_Product_0001.kl
4.3 踩過的坑請注意
當我找到我的device/amlogic/common/products/mbox/
目錄下之后發現有多個kl文件
按理說應該是Vendor_0001_Product_0001.kl才對,但是實際上使用的卻是Vendor_0001_Product_0002.kl文件,經過多方排查發現是因為在編譯的時候mk文件對他進行了改動:
path:device/amlogic/common/products/mbox/sc2/device.mk
#use tv remote layout for mbox if livetv is built
ifeq ($(TARGET_BUILD_LIVETV), true)PRODUCT_COPY_FILES += \device/amlogic/common/products/mbox/Vendor_0001_Product_0002.kl:$(TARGET_COPY_OUT_VENDOR)/usr/keylayout/Vendor_0001_Product_0001.kl
elsePRODUCT_COPY_FILES += \device/amlogic/common/products/mbox/Vendor_0001_Product_0001.kl:$(TARGET_COPY_OUT_VENDOR)/usr/keylayout/Vendor_0001_Product_0001.kl
endif
這里由于變量TARGET_BUILD_LIVETV的值為true,所以將Vendor_0001_Product_0002.kl文件的內容拷貝到了Vendor_0001_Product_0001.kl里面,所以雖然用的是0001但是其實改動需要在0002中進行。
4.4 改動kl文件
patch: device/amlogic/common/products/mbox/Vendor_0001_Product_0002.kl
key 158 BACKkey 139 MENUkey 102 HOME
前面的值是DTSI中的值,后面的是有底層文件與之相對應的。
進行到這里,按鍵功能就已經生效了,一般做到這里也就可以了。
繼續往下追查這個值是在KeyLabel文件中定義的
五、KeyLabel文件
- Path:
frameworks/native/include/input/InputEventLabels.h
- Content:
DEFINE_KEYCODE(BACK),
再往下就是Keycode值的對應
六、Keycode
包含以下三個文件:
- Native
- Path:
frameworks/native/include/android/keycodes.h
- Content:
- Path:
AKEYCODE_BACK = 4,
- Java
- Path:
frameworks/base/core/java/android/view/KeyEvent.java
- Content
- Path:
public static final int KEYCODE_BACK = 4;
- Res
- Path:
frameworks/base/core/res/res/values/attrs.xml
- Content:
- Path:
<enum name="KEYCODE_BACK" value="4" />
現在,當你使用logcat -s RemoteIME命令就能夠看到控制臺輸出了keycode,這個值就和我們上面的值對應上了
七、KeyEvent
當按鍵傳到 fromworks 我們只需要更改 KeyEvent.java 來完成最后的按鍵定義,之后就是到 PhoneWindowManager.java 來實現按鍵功能實現攔截或繼續傳遞。
- Path:
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
- Content:
onKeyDowncase KeyEvent.KEYCODE_YOUR_PRIVATE_KEY: {//do sthreturn true;
}
總之
一般情況下按照dtsi–>linux-event-codes.h–>kl 的順序來改就可以了,如果還出現其他問題則繼續查看。