藍牙 Apple 妙控鍵盤的 Fn 鍵 (2015)
我在 Fedora 25(核心:)上使用Apple 妙控鍵盤(帶鋰離子電池的藍牙無線、用於充電和連接使用的 Lightning 埠)時遇到問題
4.8.15-300.fc25.x86_64
。問題是在無線模式下使用時,
Fn
密鑰似乎沒有註冊。我試過xev
了,鍵本身不會觸發任何事件,與另一個鍵按下的鍵也不會導致觸發的事件與單獨按下另一個鍵相比有任何不同。我想使用該Fn
鍵的原因是因為我想分別將Fn
+←
/映射→
到Home
andEnd
並且還使用現在預設為功能鍵的多媒體鍵。有趣的是,當我用閃電電纜將它連接到電腦時,這個鍵盤充當普通的 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
。這是
F2
和Fn
+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 為 hex
01
的電池狀態報告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.txt
和samples/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