我在Fedora 25(内核:)上使用Apple Magic Keyboard(带LiIon电池的蓝牙无线网络,用于充电和系留连接的Lightning端口)时遇到问题4.8.15-300.fc25.x86_64
。
问题在于,在无线模式下使用时,Fn密钥似乎没有注册。我尝试过xev
,该键本身不会触发任何事件,并且与另一个键所按下的键相比,按下另一个键所导致的触发事件也不会引起任何不同。我想使用该Fn键的原因是因为我想分别将Fn+ ←/映射→到Home和,End并且还使用默认情况下现在是功能键的多媒体键。
有趣的是,当我用闪电电缆将其连接到计算机时,该键盘可以用作普通的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
奇怪的是,释放后有时会打印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十六进制01
,一个电池状态报告的ID十六进制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个键按压simultanously。VA
并且VB
是特定于供应商的。假设在上一个示例中您Fn按住并刚刚按下并释放F2
,我的猜测是in中的位1VB
代表Fn(或至少与之相关的)修饰符。
使用hexdump -e '10/1 "%02X ""\n"'
得到9个字节每行输出,并结合检验这一假设Fn与几个键,包括你到底想要重新定义的组合。
更新:为了完整性和将来的参考,尽管我认为在这种情况下它不再重要:可以使用UHID注入HID事件,请参见Documentation/hid/uhid.txt
andsamples/uhid/uhid-example.c
在内核中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句