让 Razer BlackWidow 的宏键在 Linux 上运行

让 Razer BlackWidow 的宏键在 Linux 上运行

我拿起一个Razer BlackWidow Ultimate具有用于设置宏的附加键,可使用安装在 Windows 上的工具。我假设这些不是一些花哨的 joojoo 键并且应该像任何其他键一样发出扫描码。

首先,在 Linux 中是否有标准方法来检查这些扫描码?其次,如何设置这些键以在命令行和基于 X 的 Linux 设置中执行操作?我当前安装的 Linux 是 Xubuntu 10.10,但一旦修复了一些问题,我就会切换到 Kubuntu。理想情况下,答案应该是通用的和系统范围的。

到目前为止我尝试过的事情:

我需要尝试的事情

  • 史努比专业版+ 逆向工程(天哪)

  • Wireshark - 初步检查似乎表明,当我认为键盘受到监控并且按键被按下时,没有发出扫描码。可能表明其他按键是单独的设备或需要以某种方式初始化。

  • 需要将其与 Linux 的 lsusb 输出进行交叉引用,分为三种情况:独立、传递到未安装驱动程序的 Windows VM 以及相同情况。

  • LSUSB 仅在独立 Linux 安装上检测一个设备

  • 检查鼠标是否使用相同的 Razer Synapse 驱动程序可能会很有用,因为这意味着razer配置可能有效(未检测到,似乎只对老鼠有效)

我已经解决的问题:

  • 在装有驱动程序的Windows系统中,键盘被视为键盘指点设备。指点设备除了使用标准鼠标驱动程序外,还使用 ​​Razer Synapse 驱动程序。

  • evdev在 Linux 下也lsusb能看到鼠标驱动程序

  • 显然是 OS X 下的单一设备,但我还没有尝试lsusb

  • 在 OS X 中,使用驱动程序初始化后,键盘会进入脉冲背光模式。这可能表明在激活时会向键盘发送一些初始化序列。

  • 事实上,它们是花哨的 joojoo 钥匙。

稍微延伸一下这个问题:

我可以访问 Windows 系统,因此如果我需要使用任何工具来帮助回答问题,那没问题。我也可以在有和没有配置实用程序的系统上尝试。然而,预期的最终结果仍然是使这些密钥在 Linux 上可用。

我也意识到这是一个非常特殊的硬件系列。如果我有详细的说明,我愿意在 Linux 系统上测试任何有意义的东西 - 这应该会向那些拥有 Linux 技能但无法使用此键盘的人提出这个问题。

我要求的最低最终结果是:

我需要检测这些键并可用于任何在任何当前主流的图形化 Ubuntu 变体上都具有时尚感,而且自然必须与我的键盘配合使用。如果它是包装精美且可供普通用户使用的东西,那么虚拟 cookie 和疯狂道具。

我将需要在我的系统上运行的已编译代码,或者我可以编译的源代码(如果比 、 、 更复杂,则需要说明./configuremakemake install如果在回答时当前 LTS 或标准桌面版本的 Ubuntu 存储库中没有其他软件。我还需要足够的信息来复制并在自己的系统上成功使用密钥。

答案1

M1-M5 实际上是常规按键 - 只需要在按下它们之前特别启用它们就会生成扫描码。tux_mark_5 开发了一个小型 Haskell 程序,它会向 Razer 键盘发送正确的 SET_REPORT 消息以启用这些按键,并且 ex-parrot 将相同的代码移植到 Python。

在 Arch Linux 系统上,Python 端口已打包并可从https://aur.archlinux.org/packages.php?ID=60518

在 Debian 或 Ubuntu 系统上设置代码的 Python 端口相对容易。您需要安装 PyUSB 和 libusb(以 root 身份):

    aptitude install python-usb

blackwidow_enable.py然后从中获取文件http://finch.am/projects/blackwidow/并执行它(也以 root 身份):

    chmod +x blackwidow_enable.py
    ./blackwidow_enable.py

这将启用按键,直到键盘拔出或机器重新启动。要使此设置永久生效,请从您最喜欢的任何启动脚本样式调用脚本。有关如何在 Debian 中设置此设置的说明,请查看Debian 文档

要使用 tux_mark_5 的 Haskell 代码,您需要安装 Haskell 并自行编译代码。这些说明适用于类似 Debian 的系统(包括 Ubuntu)。

  1. 安装 GHC、libusb-1.0-0-dev 和 cabal (以 root 身份):

    aptitude install ghc libusb-1.0-0-dev cabal-install git pkg-config
    
  2. 获取包列表:

    cabal update
    
  3. 为 Haskell 安装 USB 绑定(无需 root):

    cabal install usb
    
  4. 下载实用程序:

    git clone git://github.com/tuxmark5/EnableRazer.git
    
  5. 构建实用程序:

    cabal configure
    cabal build
    
  6. 运行该实用程序(也以 root 身份运行):

    ./dist/build/EnableRazer/EnableRazer
    

此后,您可以将 EnableRazer 二进制文件复制到任何您想要的地方并在启动时运行它。

执行后,X 服务器应立即将 M1 视为 XF86Tools,将 M2 视为 XF86Launch5,将 M3 视为 XF86Launch6,将 M4 视为 XF86Launch7,将 M5 视为 XF86Launch8。FN 的事件也会发出。

这些键可以在 xbindkeys 或 KDE 的系统设置中绑定到任意操作。

由于您的键盘可能不同,您可能需要更改 Main.hs 第 64 行中的产品 ID:

withDevice 0x1532 0x<HERE GOES YOUR KEYBOARD's PRODUCT ID> $ \dev -> do

答案2

如今,Razer 似乎正在强迫所有用户使用基于云的 Synapse 2 配置器,同时固件升级至版本 2.*。一旦升级固件,您就无法返回(如果您尝试使用旧固件刷新键盘,键盘将完全变砖)。

Haskell 程序中的“魔法字节”tux_mark_5 的回答无法与最新固件配合使用。相反,驱动程序在初始化序列期间发送这些字节:“0200 0403”。这些字节启用了宏键,但键盘进入一种特殊模式,在该模式下,它发送 16 字节数据包而不是标准 HID 协议(可能是为了增加可以同时按下的键数)。Linux HID 系统无法完全应对这种情况,虽然大多数键都能正常工作,但宏键仍然无法识别:当按下宏键时,HID 驱动程序不会向输入层提供任何数据。

要使键盘进入传统模式(其中宏键发送 XF86Launch* 键码,FN 键发送键码 202),请发送以下字节:0200 0402。

完整数据包如下:

00000000 00020004 02000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 0400

下面是我用不太深奥的 Python 3 编写的一个非常粗糙和肮脏的程序来执行该任务。请注意 blackwidow.bwcmd() 中生成 Razer 控制数据包的代码以及 Razer 徽标 LED 命令作为奖励 :)

#!/usr/bin/python3

import usb
import sys

VENDOR_ID = 0x1532  # Razer
PRODUCT_ID = 0x010e  # BlackWidow / BlackWidow Ultimate

USB_REQUEST_TYPE = 0x21  # Host To Device | Class | Interface
USB_REQUEST = 0x09  # SET_REPORT

USB_VALUE = 0x0300
USB_INDEX = 0x2
USB_INTERFACE = 2

LOG = sys.stderr.write

class blackwidow(object):
  kernel_driver_detached = False

  def __init__(self):
    self.device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)

    if self.device is None:
      raise ValueError("Device {}:{} not found\n".format(VENDOR_ID, PRODUCT_ID))
    else:
      LOG("Found device {}:{}\n".format(VENDOR_ID, PRODUCT_ID))

    if self.device.is_kernel_driver_active(USB_INTERFACE):
      LOG("Kernel driver active. Detaching it.\n")
      self.device.detach_kernel_driver(USB_INTERFACE)
      self.kernel_driver_detached = True

    LOG("Claiming interface\n")
    usb.util.claim_interface(self.device, USB_INTERFACE)

  def __del__(self):
    LOG("Releasing claimed interface\n")
    usb.util.release_interface(self.device, USB_INTERFACE)

    if self.kernel_driver_detached:
      LOG("Reattaching the kernel driver\n")
      self.device.attach_kernel_driver(USB_INTERFACE)

    LOG("Done.\n")

  def bwcmd(self, c):
    from functools import reduce
    c1 = bytes.fromhex(c)
    c2 = [ reduce(int.__xor__, c1) ]
    b = [0] * 90
    b[5: 5+len(c1)] = c1
    b[-2: -1] = c2
    return bytes(b)

  def send(self, c):
    def _send(msg):
      USB_BUFFER = self.bwcmd(msg)
      result = 0
      try:
        result = self.device.ctrl_transfer(USB_REQUEST_TYPE, USB_REQUEST, wValue=USB_VALUE, wIndex=USB_INDEX, data_or_wLength=USB_BUFFER)
      except:
        sys.stderr.write("Could not send data.\n")

      if result == len(USB_BUFFER):
        LOG("Data sent successfully.\n")

      return result

    if isinstance(c, list):
      #import time
      for i in c:
        print(' >> {}\n'.format(i))
        _send(i)
        #time.sleep(.05)
    elif isinstance(c, str):
        _send(c)

###############################################################################

def main():
    init_new  = '0200 0403'
    init_old  = '0200 0402'
    pulsate = '0303 0201 0402'
    bright  = '0303 0301 04ff'
    normal  = '0303 0301 04a8'
    dim     = '0303 0301 0454'
    off     = '0303 0301 0400'

    bw = blackwidow()
    bw.send(init_old)

if __name__ == '__main__':
    main()

答案3

也许这可以阐明这个问题(来自 showkey 手册页):

在 2.6 内核中,原始模式或扫描码模式根本不是原始的。首先将扫描码转换为键码,当需要扫描码时,再将键码转换回来。这涉及各种转换,并且根本无法保证最终结果与键盘硬件发送的内容相对应。因此,如果您想知道各种键发送的扫描码,最好启动 2.4 内核。从 2.6.9 开始,还有启动选项 atkbd.softraw=0,它告诉 2.6 内核返回实际的扫描码。

原始扫描码仅在 AT 和 PS/2 键盘上可用,即使如此,除非使用 atkbd.softraw=0 内核参数,否则它们也会被禁用。当原始扫描码不可用时,内核使用固定的内置表从键码生成扫描码。因此,setkeycodes(8) 可以影响扫描码转储模式下 showkey 的输出。

我即将查看设置此启动选项后,showkey 是否会使用宏键转储任何内容。

编辑:重启后,没有成功,但我正在研究如何从 USB 设备本身捕获原始输入。有趣的是,我注意到了以下几点(我有 Razer Diamondback 和 BlackWidow):

[root@kestrel by-id]# pwd
/dev/input/by-id
[root@kestrel by-id]# ls
usb-Razer_Razer_BlackWidow_Ultimate-event-kbd    usb-Razer_Razer_Diamondback_Optical_Mouse-event-mouse
usb-Razer_Razer_BlackWidow_Ultimate-event-mouse  usb-Razer_Razer_Diamondback_Optical_Mouse-mouse
usb-Razer_Razer_BlackWidow_Ultimate-mouse
[root@kestrel by-id]#

但是,使用 dd 捕获原始输入在 diamondback 鼠标和 event-kbd 设备上均有效,但在 BlackWidow 鼠标设备上无效。

我猜它们可能直到被安装的驱动程序以某种方式激活后才会产生任何输出。但是我对 Linux USB 了解不多,所以我甚至不知道这是否有意义。也许它们需要先绑定?

好吧,所有三个黑寡妇设备都在 中列出/proc/bus/input/devices,但它们似乎没有在lsusb或中列出/proc/bus/usb/devices。我不确定如何访问这些设备以尝试绑定它们或以任何方式与它们交互。

event4似乎与实际键盘相对应,event6 带有宏键,但我仍然无法从它们捕获任何输入。希望对大家有所帮助。

   [root@kestrel input]# ls
devices  handlers
[root@kestrel input]# cat handlers
N: Number=0 Name=kbd
N: Number=1 Name=mousedev Minor=32
N: Number=2 Name=evdev Minor=64
N: Number=3 Name=rfkill
[root@kestrel input]# pwd
/proc/bus/input
[root@kestrel input]# cat devices
I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=PNP0C0C/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input0
U: Uniq=
H: Handlers=kbd event0 
B: EV=3
B: KEY=10000000000000 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1
U: Uniq=
H: Handlers=kbd event1 
B: EV=3
B: KEY=10000000000000 0

I: Bus=0017 Vendor=0001 Product=0001 Version=0100
N: Name="Macintosh mouse button emulation"
P: Phys=
S: Sysfs=/devices/virtual/input/input2
U: Uniq=
H: Handlers=mouse0 event2 
B: EV=7
B: KEY=70000 0 0 0 0
B: REL=3

I: Bus=0003 Vendor=1532 Product=010d Version=0111
N: Name="Razer Razer BlackWidow Ultimate"
P: Phys=usb-0000:00:12.1-3/input0
S: Sysfs=/devices/pci0000:00/0000:00:12.1/usb4/4-3/4-3:1.0/input/input4
U: Uniq=
H: Handlers=kbd event4 
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7

I: Bus=0003 Vendor=1532 Product=010d Version=0111
N: Name="Razer Razer BlackWidow Ultimate"
P: Phys=usb-0000:00:12.1-3/input1
S: Sysfs=/devices/pci0000:00/0000:00:12.1/usb4/4-3/4-3:1.1/input/input5
U: Uniq=
H: Handlers=kbd event5 
B: EV=1f
B: KEY=837fff002c3027 bf00444400000000 1 c040a27c000 267bfad941dfed 9e000000000000 0
B: REL=40
B: ABS=100000000
B: MSC=10

I: Bus=0003 Vendor=1532 Product=010d Version=0111
N: Name="Razer Razer BlackWidow Ultimate"
P: Phys=usb-0000:00:12.1-3/input2
S: Sysfs=/devices/pci0000:00/0000:00:12.1/usb4/4-3/4-3:1.2/input/input6
U: Uniq=
H: Handlers=mouse2 event6 
B: EV=17
B: KEY=70000 0 0 0 0
B: REL=103
B: MSC=10

I: Bus=0003 Vendor=1532 Product=0002 Version=0110
N: Name="Razer Razer Diamondback Optical Mouse"
P: Phys=usb-0000:00:12.1-2/input0
S: Sysfs=/devices/pci0000:00/0000:00:12.1/usb4/4-2/4-2:1.0/input/input9
U: Uniq=
H: Handlers=mouse1 event3 
B: EV=17
B: KEY=7f0000 0 0 0 0
B: REL=103
B: MSC=10

[root@kestrel input]# 

答案4

也许这个文档能帮到你:

Linux 键盘和控制台 HOWTO有用的程序

相关内容