web-dev-qa-db-ja.com

Bluetooth用のFnキーApple Magic Keyboard(2015)

Apple Magic Keyboard (LiIonバッテリーを搭載したBluetoothワイヤレス、充電用のLightningポート、テザー使用)をFedora 25(カーネル:4.8.15-300.fc25.x86_64)で使用できません。

問題は、ワイヤレスモードで使用すると、 Fn キーが登録されていないようです。 xevを試しましたが、キー自体はイベントをトリガーしません。また、別のキーでキーを押すと、トリガーされたイベントが、それ自体で押された他のキーと異なることはありません。使用したい理由 Fn キーはマップしたいからです Fn/ に Home そして End それぞれ、デフォルトでファンクションキーになっているマルチメディアキーも使用します。

興味深いのは、このキーボードが通常のApple有線キーボードとして、稲妻ケーブルでコンピューターに接続したときに機能することです。これは、Bluetoothラジオが使用されておらず、 USBハードウェア/ドライバー(おそらく、元のAppleアルミニウムキーボード、確認していません)とは異なるUSBデバイスIDで登録されています)。そうすることで、ファンクションキーの使用とファンクションキーなどのすべてのトリックが可能になります。または、インターネット上にあるデフォルトのマルチメディアキー。

ただし、Bluetoothキーボードとして使用する場合と同じ機能を利用できるようにしたいと思います。カーネルにパッチを適用するところまで行きますが、どこから始めて、どのようにテストおよびデバッグするかがわかりません(明らかに、「侵襲性の低い」手段を最初に試してみたいと思います)。

この問題に対処する方法についてのアイデアは大歓迎です。

更新

/dev/hidraw0から読み取ると、を押すとアクティビティが発生します Fn キー、つまりこれは fn キー押下はシステムによって登録されますが、途中でどこかで失われます...

Update2

evtestは、を押してもイベントを表示しません Fn キーと/dev/input/event4(Magic Keyboardのイベントデバイス)はイベントをトリガーしません(他のキーはトリガーします)。だから私は問題は 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

奇妙なことに、リリース後に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
3
orange

部分的な回答:HIDインフラストラクチャとHID生データを理解する

(免責事項:私はこれをすべてUSBに対して行っただけですが、Bluetoothと同じまたは同様の方法で適用されると思います)。

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を使用して記述子を解析できます。カーネルソースには、ioctlを介してHID記述子を取得する方法を示す/samples/hidraw/hid-example.cファイルもあります。 usbhid-dumpと同様の16進ダンプを生成するように簡単に変更できます。これはBluetoothに使用する必要があるので、 Pastebin に入れます。 makeでコンパイルします。

(外部プロジェクトのコンパイルに慣れていない場合:両方のZipファイルをダウンロードし、それぞれを空のディレクトリ./bootstrap./configuremakeに解凍します。これで、バイナリを直接使用して、$PATHなどを追加できます。)

これで、を使用して記述子を解析できます

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

この出力(または、何かが機能しない場合はhexdump)を提供することに加えて、を押した場合にhidrawで何が起こるかをテストしてください。 Fn 他のさまざまなキー(アルファベット、矢印)と組み合わせて。また、通常のキー押下で何が起こるかをテストします。

カーネルに特別なレポートを認識させることができない場合、続行するための最良の方法がわかりません。おそらく最も簡単な方法は、 input-create と同様に、hidrawからのイベントを分析し、追加の入力イベントを生成するCプログラムを作成することです。

Update: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 01の入力イベントレポートが1つ、ID hex 90のバッテリーステータスレポートが1つ、LEDを通常どおりに設定するための出力が1つ、ベンダー固有の機能制御が1つあります。

入力イベントレポートのバイトをマークしました。ベンダーが定義したフィールドがいくつかあり、それらが何をするのかわからず、推測する必要があります。

入力イベントレポートは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を押して放したところ、VBのビット1は次の修飾子を表していると思います。 Fn (または少なくともそれに関連する何か)。

hexdump -e '10/1 "%02X ""\n"'を使用して1行あたり9バイトの出力を取得し、組み合わせてこの仮説をテストします Fn 最終的に再定義したい組み合わせを含む、いくつかのキーを使用します。

Update:完全性と将来の参照のために、この特定のケースにはもう関係ないと思いますが:UHIDを使用してHIDイベントを挿入することは可能です。Documentation/hid/uhid.txtとを参照してください。カーネル内のsamples/uhid/uhid-example.c

2
dirkt

上記のヒントの助けを借りて、AppleマジックキーボードがBluetooth経由で接続されているときにFnキーを機能させるパッチを作成することができました。

問題の一部は、MagicKeyboardがベンダーID0x004c(AppleのBluetoothベンダーID)とhid-Appleが0x05ac(Apple USBベンダーID)のみを検索するため、hid-Appleの代わりにhid-genericモジュールが使用されたことでした。

2番目の問題はApple_input_mappingにありました。これは、元々はgitlogによるとhidinput_configure_usageのコードに由来します。

パッチはここに投稿されています: https://bugzilla.kernel.org/show_bug.cgi?id=99881#c41

2
Natanael Copa