通俗易通講解Android藍牙鍵值適配

以下圖中TV VOD兩個按鍵為例,文章中所涉及到的文件隻寫文件名,因每個方案的路徑各不相同,請自行全局搜索文件。

 1.獲取按鍵的掃描碼

android設備串口或adb shell下執行getevent -l(小寫的L),然後按下按鍵(以VOD鍵為例),打印結果如下:

getevent顯示結果中的三個有效信息:

  • 1)000c006b   前四位000c為鍵值類型(詳情請跳到2與閱讀hid.h),後四位為藍牙鍵值;
  • 2)KEY_BLUE  如果在linux_key.h中有此按鍵的定義,此處就會顯示,如果linux_key.h中沒有對此鍵的定義就會顯示KEY_UNKNOWN.
  • 3)/dev/input/event4: 設備節點,可以通過dumpsys input命令查看此節點使用KeyLayoutFile(即映射鍵值的.kl的文件)
console:/ # getevent -l                                                        
add device 1: /dev/input/event4
  name:     "語音助手"
could not get driver version for /dev/input/mouse2, Not a typewriter
add device 2: /dev/input/event3
  name:     "Hi Keypad"
could not get driver version for /dev/input/mouse1, Not a typewriter
add device 3: /dev/input/event1
  name:     "Hi mouse"
could not get driver version for /dev/input/mice, Not a typewriter
add device 4: /dev/input/event0
  name:     "Hi keyboard"
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 5: /dev/input/event2
  name:     "qwerty"
/dev/input/event4: EV_MSC       MSC_SCAN             000c006b            
/dev/input/event4: EV_KEY       KEY_BLUE             DOWN                
/dev/input/event4: EV_SYN       SYN_REPORT           00000000            
/dev/input/event4: EV_MSC       MSC_SCAN             000c006b            
/dev/input/event4: EV_KEY       KEY_BLUE             UP                  
/dev/input/event4: EV_SYN       SYN_REPORT           00000000    

2.hid-input.c

從getevent -l時已知VOD按鍵為000c006b,前四位詳細定義可以參考kernel下的hid.h,此處隻列舉幾個:

#define HID_UP_KEYBOARD         0x00070000
#define HID_UP_LED              0x00080000
#define HID_UP_BUTTON           0x00090000
#define HID_UP_ORDINAL          0x000a0000
#define HID_UP_TELEPHONY        0x000b0000
#define HID_UP_CONSUMER         0x000c0000

在hid-input.c中有個函數hidinput_configure_usage,會根據不同的hid執行不同的代碼,為0007(HID_UP_KEYBOARD)時會處理hid_keyboard[256]的數組,把掃描碼轉換為10進制後就是該數組的下標,數組下標的數組元素就是linux鍵值,我的鍵值前面是000c所以跳過前面說的,case走的是HID_UP_CONSUMER,此case下已有對0x6b的處理,意思就是此鍵在linux中代表的是KEY_BLUE。

static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
				     struct hid_usage *usage)
{
 
	/**省略**/
	switch (usage->hid & HID_USAGE_PAGE) {
	case HID_UP_UNDEFINED:
		goto ignore;
    /**省略**/
    /**省略**/
	case HID_UP_KEYBOARD:
		set_bit(EV_REP, input->evbit);
 
		if ((usage->hid & HID_USAGE) < 256) {
			if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
			map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
		} else
			map_key(KEY_UNKNOWN);
 
		break;
    
 
	case HID_UP_CONSUMER:	/* USB HUT v1.12, pages 75-84 */
		switch (usage->hid & HID_USAGE) {
		case 0x06a: map_key_clear(KEY_GREEN);		break;
		case 0x06b: map_key_clear(KEY_BLUE);		break;
		case 0x06c: map_key_clear(KEY_YELLOW);		break;
		case 0x06d: map_key_clear(KEY_ZOOM);		break;
 
    /**省略**/
    /**省略**/
}

那KEY_BLUE的鍵值是多少呢?

{"KEY_BLUE", 0x191},

我們來查閱linux_key.h,搜索KEY_BLUE,我的sdk中KEY_BLUE的值為0x191,轉換為十進制值為401。

3.KeyLayoutFile  –> .kl

getevent -l時已知設備節點為/dev/input/event4,那我們執行下dumpsys input,結果如下:

5: 語音助手
      Classes: 0x8000012b
      Path: /dev/input/event4
      Enabled: true
      Descriptor: e0cab5a5e7db45d100777208b12fb1c21978adca
      Location: 
      ControllerNumber: 0
      UniqueId: 18:11:18:24:33:18
      Identifier: bus=0x0005, vendor=0x2b54, product=0x1600, version=0x0101
      KeyLayoutFile: /vendor/usr/keylayout/Vendor_2b54_Product_1600.kl
      KeyCharacterMapFile: /vendor/usr/keychars/Generic.kcm
      ConfigurationFile: 
      HaveKeyboardLayoutOverlay: false

結果中可以看出我的藍牙遙控器的vendor=2b54,product=1600,所以系統優先加載的我自己加到ROM中的kl(.kl命名規則與加載優先級請自行百度),有的可能找不到,會加載Generic.kl等文件,請根據KeyLayoutFile:後的路徑的文件修改映射關系,如果為默認的Generic.kl時,建議不要修改此文件,可以根據vendor與product規則自己新建一個文件。

那我們打開指向的這個kl文件,內容如下:

#key 222 "KEY_RED"                                                                                                
# key 400 "KEY_YELLOW"                                                    
key 401 PROG_GREEN                                                              
key 402   CHANNEL_UP
key 403   CHANNEL_DOWN

kl文件格式簡單解析(詳解與其它使用方法自行搜索):

key 可以理解成固定格式 

222/401等數字對應的就是linux的鍵值

PROG_GREEN 這裡對應的就是Android層的鍵值(此字符串要與InputEventLabels.h中的保持一致,否則會報Expected key code label異常,然後就加載其它默認的kl文件瞭,5.0以前是KeycodeLabels.h或KeyCodeLabels.h)

既然都理清楚瞭,那處理按鍵豈不是很簡單瞭?

已知前面linux_key.h中查詢VOD的linux鍵值為401,如果你想讓此按鍵生效,把前面的#號去掉重啟設備,使其映射關系生效即可,如果你想改變鍵值的功能,可以直接在此kl中把401對應的android層的KEY_BLUE改為你想要的鍵就可以瞭。(當然也可以修改linux的鍵值,但不提倡這麼做.)

總結:

  • 1.通過getevent -l獲取鍵值設備節點;
  • 2.hid-input.c中添加或修改你的鍵值;
  • 3.通過設備節點找到對應的kl文件;
  • 4.添加或修改映射關系;

以上所述是小編給大傢介紹的Android藍牙鍵值適配,希望對大傢有所幫助。在此也非常感謝大傢對WalkonNet網站的支持!

推薦閱讀: