如何从键盘读取额外的键 (Steelseries APEX 300)

如何从键盘读取额外的键 (Steelseries APEX 300)

我尝试让 Steelseries APEX 300 的额外按键正常工作。主键和标准特殊键工作正常。

最后,我想编写一个小应用程序(C/C++ Qt)来为这些键分配一些命令。

为此我做了一些研究:

  1. 寻找设备:

    $ lsusb
    Bus 003 Device 004: ID 1038:1208 SteelSeries ApS 
    
  2. 查看内核日志:

    [ 1173.630363] usb 3-1.1: new full-speed USB device number 13 using xhci_hcd
    [ 1173.748310] usb 3-1.1: New USB device found, idVendor=1038, idProduct=1208
    [ 1173.748314] usb 3-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [ 1173.748316] usb 3-1.1: Product: SteelSeries Apex 300 Gaming Keyboard
    [ 1173.748317] usb 3-1.1: Manufacturer: SteelSeries
    [ 1173.750546]  0003:1038:1208.000D: hiddev0,hidraw0: USB HID v1.11 Device [SteelSeries SteelSeries Apex 300 Gaming Keyboard] on usb-0000:00:14.0-1.1/input0
    [ 1173.751418] input: SteelSeries SteelSeries Apex 300 Gaming Keyboard as /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.1/3-1.1:1.1/0003:1038:1208.000E/input/input32
    [ 1173.810811] hid-generic 0003:1038:1208.000E: input,hidraw2: USB HID v1.11 Keyboard [SteelSeries SteelSeries Apex 300 Gaming Keyboard] on usb-0000:00:14.0-1.1/input1
    [ 1173.812405] input: SteelSeries SteelSeries Apex 300 Gaming Keyboard as /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.1/3-1.1:1.2/0003:1038:1208.000F/input/input33
    [ 1173.870645] hid-generic 0003:1038:1208.000F: input,hidraw3: USB HID v1.11 Device [SteelSeries SteelSeries Apex 300 Gaming Keyboard] on usb-0000:00:14.0-1.1/input2
    
  3. 我看到了hidraw0hidraw2然后又hidraw3补充了。所以我最后查看了所有的hidraw*输出并发现使用sudo cat

    • hidraw0= ?
    • hidraw1= 鼠标
    • hidraw2= 标准键盘按键
    • hidraw3= 特殊功能键(音量...)
    • hidraw4= 鼠标
    • hidraw5= ?

也许这hidraw0就是关键。

  1. /dev/input/by-id/我找到了两个关于 APEX 的合适条目:

    $ls /dev/input/by-id/usb-SteelSeries_SteelSeries_Apex_300_*
    usb-SteelSeries_SteelSeries_Apex_300_Gaming_Keyboard-event-if02
    usb-SteelSeries_SteelSeries_Apex_300_Gaming_Keyboard-if01-event-kbd
    

    这里我再次尝试使用cat

    • *-event-if02: 没有什么
    • *-if01-event-kbd:标准键盘输入

我发现了一篇帖子(识别额外的键盘按键:Steelseries Apex)处理这个键盘,但我的 Haskell 知识太差了。我只知道APEX需要接收命令才能启用密钥。

你能给我一些提示从哪里开始吗?

答案1

只需浏览链接的 Haskell 代码:

put (CmdEnableExtraKeys) = do
  put32 [0x02, 0x00, 0x02]

是您需要发送的报告(3个字节),

withDevice 0x1038 [0x1200, 0x1202, 0x1208] $ \dev -> do
  withDeviceHandle dev $ \devHndl ->
  withDetachedKernelDriver devHndl 0 $
  withClaimedInterface devHndl 0 $ do ...

1038查找具有供应商 ID和设备 ID 12001202、的设备1208,分离内核驱动程序,并对其进行工作。

apexCtl :: DeviceHandle -> ByteString -> IO ()
apexCtl devHndl d = do
  putStrLn "WRITING SET_REPORT"
  writeControlExact devHndl controlSetup d noTimeout

进行实际写作;写控制精确来自System.USB,USB 控制进行写入,因此似乎绕过了 HID 层。这是一个猜测,因为我不熟悉这个库。

因此,我要么尝试运行 Haskell 程序(说明位于您链接的 git readme 上),要么使用您更熟悉的任何内容执行 USB 控制写入。

顺便说一句,您可以使用它evtest来更好地了解输入层上发生的情况,并查看 HID 报告以了解 HID 层

mount -t debugfs none /sys/kernel/debug
cat /sys/kernel/debug/hid/YOUR_DEVICE/rdesc

答案2

Apex 宏是另一个启用额外按键的程序。它是用 C 语言编写的,如果您不习惯 Haskell,可能会更清楚。

我怀疑这个功能应该作为设备怪癖添加到内核驱动程序中。


目前该键盘的功能是附加按键的基本功能。 ApexCtrl 和 Apex-Macros 程序只是向键盘发送一个命令,以像普通键一样报告键。一旦发送此命令,内核就会收到 L/M/MX 键的扫描码,并且可以正常定义:

  • hwdb 可以覆盖扫描码到特定键码的映射
  • XKB 可以覆盖键码到特定键符号的映射
  • 可以将应用程序配置为对这些键进行操作

我使用旧版本顶点控制,虽然我上次尝试编译失败。 hwdb 中的基本键定义和自定义 XKB 选项的组合允许我将额外的键设置为未使用的键符号,可以使用宏命令来使用xbindkeys.

ApexCtl 附带的 hwdb 是旧的 udev 格式,需要更新。我认为 Apex-Macros 使用相同的方法,因此 ApexCtl 的 hwdb 也应该对该工具有效。看ApexCtl 的文档哪些扫描码属于哪些硬件键,然后您可以相应地调整定义。

# original -- ApexCtl/config/90-apex.hwdb
keyboard:usb:v1038p120[02]*

# new format + my tweaks
evdev:input:b0003v1038p120[028]*
 KEYBOARD_KEY_0700a8=prog1
 KEYBOARD_KEY_0700a9=prog2
 KEYBOARD_KEY_0700ac=coffee
 KEYBOARD_KEY_0700ad=msdos
 KEYBOARD_KEY_0700e8=nextsong
 KEYBOARD_KEY_0700e9=playpause
 KEYBOARD_KEY_0700ea=previoussong
 KEYBOARD_KEY_0700eb=stopcd
 KEYBOARD_KEY_0700ec=record
 KEYBOARD_KEY_0700f4=f13
 KEYBOARD_KEY_0700f5=f14
 KEYBOARD_KEY_0700f6=f15
 KEYBOARD_KEY_0700f7=f16
 KEYBOARD_KEY_0700f8=f17
 KEYBOARD_KEY_0700f9=f18
 KEYBOARD_KEY_0700fa=f19
 KEYBOARD_KEY_0700fb=f20
 KEYBOARD_KEY_0700fc=f21
 KEYBOARD_KEY_0700fd=f22
 KEYBOARD_KEY_0700fe=f23
 KEYBOARD_KEY_0700ff=f24

通过 hwdb 中的这些键码定义,我使用此 XKB 符号文件根据需要设置选项。通常我使用元选项apexf13来引入多个选项。实际的覆盖是在一次处理一组键的小选项中完成的,因此可以覆盖它们而不影响其他键组。

// place in /usr/share/X11/xkb/symbols/apex
// or a custom location for use with setxkbmap -I
// modify /usr/share/X11/xkb/rules/evdev{,.lst,.xml} to use systemwide

// These are intended to be loaded after inet(evdev) to override
// its generic ideas.

// for use with Apex300
// L1-L2 as layout toggles
partial alphanumeric_keys
xkb_symbols "lkeys_grp" {
    key <I156> { [ ISO_Next_Group, ISO_First_Group ] };
    key <I157> { [ ISO_Prev_Group, ISO_Last_Group  ] };
}; // end of "lkeys_grp"

// for use with Apex300
// L1-L2 as VolUp-VolDown
partial alphanumeric_keys
xkb_symbols "lkeys_vol" {
    key <I156> { [ XF86AudioRaiseVolume ] };
    key <I157> { [ XF86AudioLowerVolume ] };
}; // end of "lkeys_vol"

// for use with Apex300
// Combo arrows mute
partial alphanumeric_keys
xkb_symbols "arrows_mute" {
    key <I160> { [ XF86AudioMicMute      ] };
    key <I159> { [ XF86AudioMute         ] };
}; // end of "arrows_mute"

// for use with Apex300
// Combo arrows as browser Back/Forward, shifted Stop/Reload
partial alphanumeric_keys
xkb_symbols "arrows_www" {
    key <I160> { [ XF86Back,    XF86Stop   ] };
    key <I159> { [ XF86Forward, XF86Reload ] };
}; // end of "arrows_www"

// for use with Apex300
// MX1-MX5 as media keys
partial alphanumeric_keys
xkb_symbols "mxkeys_media" {
    key <I171> { [ XF86AudioNext                   ] };
    key <I172> { [ XF86AudioPlay,   XF86AudioPause ] };
    key <I173> { [ XF86AudioPrev                   ] };
    key <I174> { [ XF86AudioStop,   XF86Eject      ] };
    key <I175> { [ XF86AudioRecord                 ] };
}; // end of "mxkeys_media"

// for use with Apex300
// MX1-MX5 as Launch1-5
partial alphanumeric_keys
xkb_symbols "mxkeys_prog" {
    key <I171> { [ XF86Launch1 ] };
    key <I172> { [ XF86Launch2 ] };
    key <I173> { [ XF86Launch3 ] };
    key <I174> { [ XF86Launch4 ] };
    key <I175> { [ XF86Launch5 ] };
}; // end of "mxkeys_prog"

// for use with Apex300
// M1-M4 as F13-F16
partial alphanumeric_keys
xkb_symbols "mkeys1_f13" {
    key <FK13> { [ F13      ] };
    key <FK14> { [ F14      ] };
    key <FK15> { [ F15      ] };
    key <FK16> { [ F16      ] };
}; // end of "mkeys1_f13"

// for use with Apex300
// M5-M8 as F17-F20
partial alphanumeric_keys
xkb_symbols "mkeys5_f17" {
    key <FK17> { [ F17      ] };
    key <FK18> { [ F18      ] };
    key <FK19> { [ F19      ] };
    key <FK20> { [ F20      ] };
}; // end of "mkeys5_f17"

// for use with Apex300
// M9-M12 as F21-F24
partial alphanumeric_keys
xkb_symbols "mkeys9_f21" {
    key <FK21> { [ F21      ] };
    key <FK22> { [ F22      ] };
    key <FK23> { [ F23      ] };
    key <FK24> { [ F24      ] };
}; // end of "mkeys9_f21"

// for use with Apex300
// M1-M12 as F13-F24
partial alphanumeric_keys
xkb_symbols "mkeys_f13" {
    include "apex(mkeys1_f13)"
    include "apex(mkeys5_f17)"
    include "apex(mkeys9_f21)"
}; // end of "mkeys_f13"

// for use with Apex300
// M5-M8 as Launch5-8
partial alphanumeric_keys
xkb_symbols "mkeys5_prog5" {
    key <FK17> { [ XF86Launch5 ] };
    key <FK18> { [ XF86Launch6 ] };
    key <FK19> { [ XF86Launch7 ] };
    key <FK20> { [ XF86Launch8 ] };
}; // end of "mkeys5_prog5"

// for use with Apex300
partial alphanumeric_keys
xkb_symbols "apexf13" {
    include "apex(mkeys_f13)"
    include "apex(lkeys_volmute)"
    include "apex(arrows_mute)"
    include "apex(mxkeys_media)"
}; // end of "apexf13"

// define other options here

加载修改后的 hwdb 和 xkb 符号后,您可以按照预期在应用程序中使用它们。唯一不可配置的键是 SteelSeries 徽标键,它本质上是一个硬连线Fn键(简要记录在XKB的Apex300几何结构)。

作为示例,我使用此配置i3wm将媒体键绑定到playerctl

#$mod+key activates playerctl thru dbus for MPRIS-capable players
bindsym $mod+XF86AudioRaiseVolume exec playerctl volume 0.05+
bindsym $mod+XF86AudioLowerVolume exec playerctl volume 0.05-
bindsym $mod+XF86AudioNext exec playerctl next
bindsym $mod+XF86AudioPrev exec playerctl previous
bindsym $mod+XF86AudioPlay exec playerctl play-pause
bindsym $mod+XF86AudioStop exec playerctl stop

相关内容