从Razer BlackWidow获取宏密钥以在Linux上工作


49

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

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

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

我需要尝试的事情

  • 史努比专业版 +逆向工程(亲爱的)

  • Wireshark-初步研究似乎表明当我似乎认为监控键盘和按下键时未发出扫描代码。可能表明其他键是一个单独的设备,或者需要以某种方式进行初始化。

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

  • LSUSB在独立的Linux安装中仅检测到一个设备

  • 检查小鼠是否使用相同的Razer Synapse驱动程序可能很有用,因为这意味着razercfg的某些变体可能有效(未检测到,仅对小鼠有效)

我已经解决的事情:

  • 在具有驱动程序的Windows系统中,键盘被视为键盘定点设备。除了您的沼泽标准鼠标驱动程序之外,定位设备还使用一种称为Razer Synapse的驱动程序。

  • 在Linux evdev以及以下版本lsusb中也可以看到的鼠标驱动程序

  • 显然,在OS X下可以使用单个设备,尽管我还没有尝试lsusb

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

  • 实际上,它们是花哨的joojoo键。

扩展这个问题:

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

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

我要求的最低最终结果:

我需要检测这些键,并且可以在任何当前的图形主流Ubuntu版本中以任何方式使用它们,并且自然必须与我的键盘一起使用。虚拟Cookie和疯狂道具(如果它们被普通用户很好地打包和使用)。

如果在当前版本的LTS或标准台式机发行时,Ubuntu存储库中没有其他软件,那么我将需要可以在我的系统上运行的已编译代码,或者需要一个可以编译的源(如果有比./configure,复杂的说明,请提供说明)。答案。我还将需要足够的信息来进行复制,并在自己的系统上成功使用密钥。makemake install


请使用任何解决方案进行更新,我很乐意实现相同的目标!
乔纳森·戴

我最近真的没有时间来研究它,但是我将用所做的任何事情来更新这个问题,直到得到答案。
Journeyman Geek

也许编辑提到大字体的500代表?否则,宣布该声明就没有多大意义(考虑到向系统注册的50名代表赏金)
丹尼尔·贝克

这仍然对您有用吗?(我说的是Sergey在下面提到的最新固件)
Adonis K. Kakoulidis

恐怕我还没有测试过它,我一直想尝试使用sergey的解决方案来查看它是否有效,但是过去几个月来我一直在运行Windows以进行功课。如果是这样,我会发表这样的评论
Journeyman Geek

Answers:


44

实际上,M1-M5是常规键-只需按特定键启用它们,然后按它们即可生成扫描代码。tux_mark_5开发了一个小型的Haskell程序,该程序将正确的SET_REPORT消息发送到Razer键盘以启用这些键,然后鹦鹉将相同的代码移植到Python。

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

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

    aptitude install python-usb

然后blackwidow_enable.pyhttp://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

这可行,进展顺利。如果系统允许,您将在一两天内获得500代表。我已随意添加pkg-config,这是将haskell usb软件包的必备组件安装到必备组件列表中所必需的。该软件可以在我的标准blackwidow Ultimate上进行任何修改,根据lsusb的产品ID为1532:010d。密钥在evtest上检测到并且似乎可用,因此这完全满足了问题的要求。
Journeyman Geek

此外,kde似乎没有密钥绑定选项,xbindkeys似乎可以正常工作
Journeyman Geek

ID 10e可以与我的标准blackwidow(非最终版)一起使用。我建议添加udev规则,这样它会自动启动,没有问题,例如,在其中创建一个文件99-enable-razer-keyboard.rules int /etc/udev/rules.d SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1532", ATTR{idProduct}=="010e", RUN+="/root/EnableRazer"(在这里您可能需要修改路径和ID再次)
flolo 2012年

显然,我编写的实用程序也适用于Razer Anansi。这是某人的博客文章:norgelinux.blogspot.com/2012/02/razer-anasi-on-arch-linux.html
tux_mark_5 2012年

1
我有Razer BlackWidow 2013(不是最终版本),当我执行blackwidow_enable.py脚本(带有和不带有root)时,我收到消息“找不到Blackwidow”。您能帮我调试一下吗?我在UbuntuGnome 13.04上。似乎Product_ID不同,更改产品ID后,我现在收到此错误:Could not select configuration endpoint.
Adonis K. Kakoulidis

22

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

tux_mark_5的答案中,Haskell程序中的“魔术字节” 不适用于最新固件。而是,驱动程序在初始化序列期间发送这些字节:'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()

我的键盘已经升级,但我还没有尝试过。当我再次拥有合适的linux系统时,我会试一试。不幸的是,我无法再为此提供赏金-部分是由于赏金系统的工作原理。如果可以的话,我可能会将正确答案切换到您的答案。
Journeyman Geek

显然我的系统上没有模块usb,所以这不起作用:/
Journeyman Geek

usb模块可能在pyusb软件包中(或python-usb或类似的东西,具体取决于发行版)。
谢尔盖

2
Sergey非常感谢您,它甚至适用于PRODUCT_ID = 0x011b的新型Razer BlackWidow 2013。我还没有尝试设置任何宏,但是我看到了来自/ dev / input / by-id / usb-Razer_Razer_Blackerid_2013-event-kbd和xev中的事件:)。
binary_runner 2014年

谢谢,太好了。我使用它已经好几年了,没有任何麻烦(最终获得了声誉:)。关于pyusb的一则评论:由于Ubuntu仍然没有为python 3发行pyusb,我不得不使用sudo python3 setup.py install
luator

8

也许这可以为这个问题提供一些启示(来自showkey手册页):

在2.6内核中,原始模式或scancode模式根本不是很原始。首先将扫描码转换为键码,然后在需要扫描码时,将键码转换回去。涉及各种转换,并且完全不能保证最终结果与键盘硬件发送的内容相对应。因此,如果您想知道各种键发送的扫描代码,最好引导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捕获原始输入在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]# 

我猜测系统必须与键盘进行通信才能对其进行初始化-在OS X中,我的键盘被置于“脉冲”点亮模式。键盘宏键起作用之前可能需要进行一些初始化
Journeyman Geek

我想知道的是如何将该信息发送到鼠标和事件鼠标设备。事件鼠标似乎负责,因为它绑定到键盘事件处理程序。我的意思是,从理论上讲,所有必须要做的就是初始化设备,并使用setkeycode设置正确的scancode-> keycode映射,然后将事件作为普通的击键操作。
srmaddox

也许我可以打开eclipse并编写一个程序,以允许从设备原始输入/输出。然后,反复试验可能会占上风。
srmaddox

jespersaur.com/drupal/book/export/html/21在过程中应该引起人们的兴趣。它远远超出了我的技能范围。
Journeyman Geek

7

我的解决方案适用于Razer BlackWidow 2013机械游戏键盘(型号:RZ03-0039),并在openSUSE 12.3上进行了测试。

我在此链接上使用了Google翻译。

基本上,它使用@Sergey答案的修改版本来解决此问题,但进行了简单的修改:

  1. 我的 PRODUCT_ID = 0x011b

  2. 在我的openSUSE 12.3,蟒蛇-USB不适用于Python 3中,所以我通过移除转换这个脚本与Python 2的工作bwcmd方法和确定的USB_BUFFER = ...作为链接@ tux_mark_5的答案


为了方便起见,这是我的内容/usr/local/sbin/init_blackwidow.py

#!/usr/bin/python

"""This is a patched version of Sergey's code form
https://superuser.com/a/474595/8647

It worked for my Razer BlackWidow 2013 Mechanical Gaming Keyboard
(Model Number: RZ03-0039).

"""
import usb
import sys

VENDOR_ID = 0x1532       # Razer
PRODUCT_ID = 0x011b      # BlackWidow 2013 Mechanical Gaming Keyboard

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

USB_VALUE = 0x0300
USB_INDEX = 0x2
USB_INTERFACE = 2

USB_BUFFER = b"\x00\x00\x00\x00\x00\x02\x00\x04\x02\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00"

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 send(self, c):
        def _send(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):
            for i in c:
                print(' >> {}\n'.format(i))
                _send(i)
        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()

...而我/etc/udev/rules.d/99-razer-balckwidow.rules是:

SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1532", ATTR{idProduct}=="011b", RUN+="/usr/local/sbin/init_blackwidow.py"

您在哪里找到了pyusb的副本usb.util
KayEss 2014年

@KayEss,我正在使用python-usb-1.0.0-21.1.noarch.rpm。IIRC是0penSUSE 12.3的标准存储库的一部分。据称rpm -qi,源位于sourceforge.net/projects/pyusb,包源位于obs://build.opensuse.org/devel:languages:python
Chen Levy

我在Ubuntu上,并且在python3上没有打包版本。然后我在将所有sudo,python3,pip和virtualenv排成一行时遇到了麻烦,但是现在已经进行了排序,并且我正在查看宏键的代码。
KayEss 2014年

1
@KayEss,对于Ubuntu 14.04,我使用了github.com/walac/pyusb中的说明。特别是:sudo apt-get install python libusb-1.0-0sudopip install pyusb --pre
Chen Levy

2

也许此文档将帮助您:

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


它是一个开始,值得赞扬。有趣的是,宏键根本没有显示在显示键中
Journeyman Geek

也许此宏密钥仅与另一个密钥结合发出scancode。像是macro-1的扫描码,等等?
ascobol 2011年

1
在Windows中配置后,它们似乎可以独立工作。我可能需要考虑一个较低级别的方法。我的猜测是,因为存在同一公司使用razercfg使用非标准扫描代码制作的鼠标的支持。呵呵。如果很简单,我想我会找到的;)
Journeyman Geek

该文档自2002年以来未进行过更新。它仍是最新的吗?
彼得·莫滕森

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.