Fedora

藍牙 Apple 妙控鍵盤的 Fn 鍵 (2015)

  • September 4, 2017

我在 Fedora 25(核心:)上使用Apple 妙控鍵盤(帶鋰離子電池的藍牙無線、用於充電和連接使用的 Lightning 埠)時遇到問題4.8.15-300.fc25.x86_64

問題是在無線模式下使用時,Fn密鑰似乎沒有註冊。我試過xev了,鍵本身不會觸發任何事件,與另一個鍵按下的鍵也不會導致觸發的事件與單獨按下另一個鍵相比有任何不同。我想使用該Fn鍵的原因是因為我想分別將Fn+ /映射HomeandEnd並且還使用現在預設為功能鍵的多媒體鍵。

有趣的是,當我用閃電電纜將它連接到電腦時,這個鍵盤充當普通的 Apple 有線鍵盤,我認為這是由於未使用藍牙無線電並求助於 USB 硬體/驅動程序(也許它已註冊)與原始 Apple 鋁製鍵盤不同的 USB 設備 ID,我沒有驗證)。這樣做允許使用功能鍵以及預設情況下您在 Internet 上找到的所有技巧,例如功能鍵或多媒體鍵。

但是,我希望將其用作藍牙鍵盤時具有相同的功能。我會盡可能地修補核心,但不知道從哪裡開始以及如何測試和調試(顯然我想先嘗試不那麼“侵入性”的方法)。

歡迎任何有關如何解決此問題的想法。

更新

當我從 閱讀時/dev/hidraw0,我在按鍵時得到了一些活動Fn,所以這可能意味著fn按鍵已被系統註冊,但在途中某個地方失去了……

更新2

evtest``Fn按下鍵時不顯示任何事件,並且/dev/input/event4(這是妙控鍵盤的事件設備)不觸發事件(其他鍵會)。所以我認為問題在於Fn密鑰被系統讀取(通過/dev/hidraw0顯示數據暗示)但它沒有傳遞給/dev/input/event4. 但這只是猜測,因為我不知道使用者輸入數據流是如何在 Linux 中工作的。

更新 3

這是幾個fn按鍵(按下+釋放)產生的結果:

> sudo cat /dev/hidraw2 | hexdump
0000000 0001 0000 0000 0000 0000 0001 0000 0000
0000010 0000 0200 0001 0000 0000 0000 0000 0001
0000020 0000 0000 0000 0200 0001 0000 0000 0000
0000030 0000 0001 0000 0000 0000 0200 0001 0000
0000040 0000 0000 0000 0001 0000 0000 0000 0200
0000050 0001 0000 0000 0000 0000 0001 0000 0000
0000060 0000 0200 0001 0000 0000 0000 0000 0001
0000070 0000 0000 0000 0200 0001 0000 0000 0000
0000080 0000 0001 0000 0000 0000 0200 0001 0000
0000090 0000 0000 0000 0001 0000 0000 0000 0200
00000a0 0001 0000 0000 0000 0000 0001 0000 0000
00000b0 0000 0200 0001 0000 0000 0000 0000 0001
00000c0 0000 0000 0000 0200 0001 0000 0000 0000
00000d0 0000 0001 0000 0000 0000 0200 0001 0000
00000e0 0000 0000 0000 0001 0000 0000 0000 0200
00000f0 0001 0000 0000 0000 0000 0001 0000 0000
0000100 0000 0200 0001 0000 0000 0000 0000 0001
0000110 0000 0000 0000 0200 0001 0000 0000 0000
0000120 0000 0001 0000 0000 0000 0200 0001 0000
0000130 0000 0000 0000 0001 0000 0000 0000 0200
0000140 0001 0000 0000 0000 0000 0001 0000 0000
0000150 0000 0200 0001 0000 0000 0000 0000 0001
0000160 0000 0000 0000 0200 0001 0000 0000 0000
0000170 0000 0001 0000 0000 0000 0200 0001 0000
0000180 0000 0000 0000 0001 0000 0000 0000 0200
0000190 0001 0000 0000 0000 0000 0001 0000 0000
00001a0 0000 0200 0001 0000 0000 0000 0000 0001
00001b0 0000 0000 0000 0200 0001 0000 0000 0000
00001c0 0000 0001 0000 0000 0000 0200 0001 0000
00001d0 0000 0000 0000 0001 0000 0000 0000 0200
00001e0 0001 0000 0000 0000 0000 0001 0000 0000
00001f0 0000 0200 0001 0000 0000 0000 0000 0001
0000200 0000 0000 0000 0200 0001 0000 0000 0000
0000210 0000 0001 0000 0000 0000 0200 0001 0000
0000220 0000 0000 0000 0001 0000 0000 0000 0200
0000230 0001 0000 0000 0000 0000 0001 0000 0000

奇怪的是,有時會在 release 後列印 2 行,但主要是 1 行fn

這是F2Fn+F2分別的樣子:

sudo cat /dev/hidraw2 | hexdump
0000000 0001 0000 0000 0000 0000 0001 3b00 0000
^[OQ0000010 0000 0000 0001 0000 0000 0000 0000 0001
^[OQ0000020 3b00 0000 0000 0000 0001 0000 0000 0000
^[OQ0000030 0000 0001 3b00 0000 0000 0000 0001 0000
0000040 0000 0000 0000 0001 3b00 0000 0000 0000
^[OQ0000050 0001 0000 0000 0000 0000 0001 3b00 0000
^[OQ0000060 0000 0000 0001 0000 0000 0000 0000 0001
^[OQ0000070 3b00 0000 0000 0000 0001 0000 0000 0000
0000080 0000 0101 0000 0000 0000 0000 0101 0600
^C

Fn+F2:

> sudo cat /dev/hidraw2 | hexdump
0000000 0001 0000 0000 0000 0000 0001 0000 0000
^[OQ0000010 0000 0200 0001 3b00 0000 0000 0200 0001
0000020 0000 0000 0000 0200 0001 3b00 0000 0000
^[OQ0000030 0200 0001 0000 0000 0000 0200 0001 3b00
^[OQ0000040 0000 0000 0200 0001 0000 0000 0000 0200
^[OQ0000050 0001 3b00 0000 0000 0200 0001 0000 0000
^[OQ0000060 0000 0200 0001 3b00 0000 0000 0200 0001
0000070 0000 0000 0000 0200 0001 3b00 0000 0000
^[OQ0000080 0200 0001 0000 0000 0000 0200 0001 3b00
^[OQ0000090 0000 0000 0200 0001 0000 0000 0000 0200
^[OQ00000a0 0001 3b00 0000 0000 0200 0001 0000 0000
00000b0 0000 0200 0001 0000 0000 0000 0000 0101
00000c0 0000 0000 0000 0000 0101 0600 0000 0000
^C

更新 4

根據@dirkt 的要求,這是報告描述符資訊(我無法根據評論執行該行,所以這是完整的轉儲;還請注意,現在hidraw2我必須更換鍵盤):

> sudo ./hid-desc /dev/hidraw2
Report Descriptor Size: 171
Report Descriptor:
05 01 09 06 a1 01 85 01 05 07 15 00 25 01 19 e0 29 e7 75 01 95 08 81 02 95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 03 95 08 75 01 15 00 25 01 06 00 ff 09 03 81 03 95 06 75 08 15 00 25 65 05 07 19 00 29 65 81 00 95 01 75 01 15 00 25 01 05 0c 09 b8 81 02 95 01 75 01 06 00 ff 09 03 81 02 95 01 75 06 81 03 06 02 ff 09 55 85 55 15 00 26 ff 00 75 08 95 40 b1 a2 c0 06 00 ff 09 14 a1 01 85 90 05 84 75 01 95 03 15 00 25 01 09 61 05 85 09 44 09 46 81 02 95 05 81 01 75 08 95 01 15 00 26 ff 00 09 65 81 02 c0 00 

Raw Name: Magic Keyboard
Raw Phys: 00:c2:c6:f7:eb:57
Raw Info:
   bustype: 5 (Bluetooth)
   vendor: 0x004c
   product: 0x0267

部分答案:理解 HID 基礎設施和 HID 原始數據

(免責聲明:我只為 USB 做了所有這些,但我想它會以相同或類似的方式應用於藍牙)。

HID 設備可以以明確定義的格式發送和接收報告。特定設備的格式由HID 描述符給出,對於 USB,它與其他 USB 描述符非常相似(例如lsusb,如果它們未綁定,則可以列出它們)。詳細資訊(適用於 USB)可在人機介面設備 (HID) PDF 文件的設備類定義中找到。

可以找到 HID 的核心文件Documentation/hid。如前所述hiddev.txt,事件的數據流如下所示:

usb.c --> hid-core.c --> hid-input.c --> input-subsystem

drivers/hid/hid-input.c中,特別是在常式中hidinput_configure_usage,根據 HID 描述符解析報告。

所以如果你看不到Fn鑰匙,那就是問題所在。

看到的輸出hidraw0看起來很可疑,好像有幾種具有不同 ID 的報告(此報告的 ID 為 1,普通鍵盤報告的 ID 為 0)。

但要確保,我們需要 HID 描述符。HID 描述符可通過hidraw設備上的 ioctl 獲得。例如,您可以使用https://github.com/DIGImend/usbhid-dump獲取描述符(僅限 USB)並https://github.com/DIGImend/hidrd對其進行解析。核心原始碼中還有一個/samples/hidraw/hid-example.c文件顯示瞭如何通過 ioctl 獲取 HID 描述符;可以輕鬆修改它以生成類似於usbhid-dump. 你必須將它用於藍牙,所以我把它放在一個pastebin中。用 編譯make

(如果你不習慣編譯外部項目:下載兩個zip文件,解壓到一個空目錄,,,,。./bootstrap現在你可以直接使用二進製文件,添加它們等)./configure``make``$PATH

現在您可以使用解析描述符

sudo ./hid-desc /dev/hidraw0 | tail -n+3 | head -1 | hidrd-convert -ihex -ospec

除了提供此輸出(或 hexdump,如果有任何東西不起作用)之外,請測試hidraw如果您按下Fn與其他各種鍵(字母、箭頭)組合時會發生什麼。還要測試正常按鍵會發生什麼。

如果無法讓核心辨識特殊報告,我不確定最好的方法。也許最簡單的方法是編寫一個 C 程序來分析來自的事件hidraw並生成額外的輸入事件,類似於input-create

更新:HID 描述符最後包含一個額外00的內容。如果你刪除它,它會解析為

Usage Page (Desktop),                           ; Generic desktop controls (01h)
Usage (Keyboard),                               ; Keyboard (06h, application collection)
Collection (Application),
   Report ID (1),                      ; +00 report id
   Usage Page (Keyboard),                      ; Keyboard/keypad (07h)
   Logical Minimum (0),
   Logical Maximum (1),
   Usage Minimum (KB Leftcontrol),             ; Keyboard left control (E0h, dynamic value)
   Usage Maximum (KB Right GUI),               ; Keyboard right GUI (E7h, dynamic value)
   Report Size (1),
   Report Count (8),
   Input (Variable),                   ; +01 modifier
   Report Count (5),
   Report Size (1),
   Usage Page (LED),                           ; LEDs (08h)
   Usage Minimum (01h),
   Usage Maximum (05h),
   Output (Variable),
   Report Count (1),
   Report Size (3),
   Output (Constant, Variable),
   Report Count (8),
   Report Size (1),
   Logical Minimum (0),
   Logical Maximum (1),
   Usage Page (FF00h),                         ; FF00h, vendor-defined
   Usage (03h),
   Input (Constant, Variable),         ; +02 vendor
   Report Count (6),
   Report Size (8),
   Logical Minimum (0),
   Logical Maximum (101),
   Usage Page (Keyboard),                      ; Keyboard/keypad (07h)
   Usage Minimum (None),                       ; No event (00h, selector)
   Usage Maximum (KB Application),             ; Keyboard Application (65h, selector)
   Input,                              ; +03 6 keysym bytes
   Report Count (1),
   Report Size (1),
   Logical Minimum (0),
   Logical Maximum (1),
   Usage Page (Consumer),                      ; Consumer (0Ch)
   Usage (Eject),                              ; Eject (B8h, one-shot control)
   Input (Variable),                   : +09.0
   Report Count (1),
   Report Size (1),
   Usage Page (FF00h),                         ; FF00h, vendor-defined
   Usage (03h),
   Input (Variable),                   ; +09.1
   Report Count (1),
   Report Size (6),
   Input (Constant, Variable),         : +09.2-7
   Usage Page (FF02h),                         ; FF02h, vendor-defined
   Usage (55h),
   Report ID (85),
   Logical Minimum (0),
   Logical Maximum (255),
   Report Size (8),
   Report Count (64),
   Feature (Variable, No Preferred, Volatile),
End Collection,
Usage Page (FF00h),                             ; FF00h, vendor-defined
Usage (14h),
Collection (Application),
   Report ID (144),
   Usage Page (Power Device),                  ; Power device (84h, power page)
   Report Size (1),
   Report Count (3),
   Logical Minimum (0),
   Logical Maximum (1),
   Usage (61h),
   Usage Page (Power Batsys),                  ; Power battery system (85h, power page)
   Usage (44h),
   Usage (46h),
   Input (Variable),
   Report Count (5),
   Input (Constant),
   Report Size (8),
   Report Count (1),
   Logical Minimum (0),
   Logical Maximum (255),
   Usage (65h),
   Input (Variable),
End Collection

有一份 id 為 hex 的輸入事件報告,一份 id 為 hex01的電池狀態報告90,一份用於照常設置 LED 的輸出,以及一份供應商特定的功能控制。

我標記了輸入事件報告的字節。有幾個供應商定義的欄位,我們不知道他們在做什麼,不得不猜測。

輸入事件報告由 10 個字節組成,您的範例解碼如下:

ID MM VA K1 K2 K3 K4 K5 K6 VB

01 00 00 00 00 00 00 00 00 02  ; press? Fn 
01 00 00 00 00 00 00 00 00 00  ; release? Fn

01 00 00 3b 00 00 00 00 00 00  ; press F2
01 00 00 00 00 00 00 00 00 00  ; release

01 00 00 00 00 00 00 00 00 00  ;
01 00 00 00 00 00 00 00 00 02  ; press Fn?
01 00 00 3b 00 00 00 00 00 02  ; press F2
01 00 00 00 00 00 00 00 00 02  ; release F2 (but not Fn?)

ID是報吧。MM是標準的 8 個修飾符位,沒有空間放置Fn鍵。K1最多K6可同時按下 6 個鍵。VA並且VB是特定於供應商的。假設您在上一個範例中Fn按住並剛剛按下並釋放F2,我的猜測是位 1 inVB代表修飾符Fn(或至少與它相關的東西)。

用於hexdump -e '10/1 "%02X ""\n"'獲取每行 9 個字節的輸出,並通過結合Fn幾個鍵來檢驗這個假設,包括你想要在最後重新定義的那些組合。

更新:為了完整性和將來的參考,儘管我認為它與這種特殊情況不再相關:可以使用 UHID 注入 HID 事件,請參閱核心中的Documentation/hid/uhid.txtsamples/uhid/uhid-example.c

在上述提示的幫助下,a 能夠創建一個更新檔,使 Fn 鍵在 Apple 妙控鍵盤通過藍牙連接時工作。

部分問題是妙控鍵盤顯示的供應商 ID 為 0x004c(Apple 的藍牙供應商 ID),而 hid-apple 僅查找 0x05ac(Apple USB 供應商 ID),因此使用了 hid-generic 模組而不是 hid-apple。

第二個問題apple_input_mapping最初來自hidinput_configure_usage根據 git log 中的程式碼。

更新檔發佈在這裡:https ://bugzilla.kernel.org/show_bug.cgi?id=99881#c41

引用自:https://unix.stackexchange.com/questions/334068