Obtendo chaves de macro de um Razer BlackWidow para trabalhar no Linux

49

Eu peguei um Razer BlackWidow Ultimate que possui chaves adicionais para macros são definidos usando uma ferramenta instalada em Windows . Estou assumindo que estas não são algumas chaves joojoo e que devem emitir scancodes como qualquer outra tecla.

Primeiramente, existe uma maneira padrão de verificar esses scancodes no Linux? Em segundo lugar, como definir essas chaves para fazer as coisas na linha de comando e nas configurações do Linux baseadas em X? Minha instalação atual do Linux é o Xubuntu 10.10, mas vou mudar para o Kubuntu assim que tiver algumas coisas consertadas. Idealmente, a resposta deve ser genérica e em todo o sistema.

Coisas que tentei até agora:

Coisas que preciso tentar

  • pro snoopy + engenharia reversa (oh querida)

  • Wireshark - o futzing preliminar parece indicar que nenhum scancodes é emitido quando o que eu penso é que o teclado é monitorado e as teclas pressionadas. Pode indicar que chaves adicionais são um dispositivo separado ou precisam ser inicializadas de alguma forma.

  • É necessário fazer referência cruzada com a saída do lsusb do Linux, em três cenários: autônomo, passado para uma VM do Windows sem os drivers instalados e o mesmo com.

  • O LSUSB detecta apenas um dispositivo em uma instalação independente do Linux

  • Pode ser útil verificar se os mouses usam o mesmo driver Razer Synapse, já que isso significa alguma variação de razercfg pode funcionar (não detectado, parece funcionar apenas para ratos)

Coisas que trabalhei:

  • Em um sistema Windows com o driver, o teclado é visto como um teclado e um dispositivo apontador. O dispositivo apontador usa - além dos seus drivers de mouse padrão - um driver para algo chamado Razer Synapse.

  • Driver de mouse visto no Linux em evdev e lsusb

  • Dispositivo único no OS X aparentemente, embora eu ainda tenha que tentar o lsusb equivalente nesse

  • O teclado entra no modo de luz de fundo pulsante no OS X após a inicialização com o driver. Isso provavelmente deve indicar que há alguma seqüência de inicialização enviada ao teclado durante a ativação.

  • Eles são, na verdade, chaves joojoo de calças extravagantes.

Estendendo esta questão um pouco:

Eu tenho acesso a um sistema Windows, então se eu precisar usar quaisquer ferramentas para ajudar a responder a pergunta, tudo bem. Eu também posso tentar em sistemas com e sem o utilitário de configuração. O resultado final esperado ainda é tornar essas chaves utilizáveis no Linux.

Eu também percebo que esta é uma família muito específica de hardware. Eu estaria disposto a testar qualquer coisa que faça sentido em um sistema Linux se eu tiver instruções detalhadas - isso deve abrir a questão para as pessoas que têm habilidades com o Linux, mas sem acesso a este teclado.

O resultado final mínimo que eu preciso:

Eu preciso dessas chaves detectadas, e utilizáveis em qualquer moda em qualquer uma das variantes gráficas correntes do Ubuntu, e naturalmente tenho que trabalhar com o meu teclado. Biscoito virtual e acessórios loucos se for algo bem empacotado e utilizável pelo usuário comum.

Vou requerer código compilado que funcionará no meu sistema, ou uma fonte que eu possa compilar (com instruções se for mais complexo que ./configure , make , make install ) se software adicional não estiver nos repositórios do Ubuntu para a versão atual da LTS ou da área de trabalho padrão no momento da resposta. Também exigirei informações suficientes para replicar e usar com êxito as chaves em meu próprio sistema.

    
por Journeyman Geek 02.10.2011 / 06:07

6 respostas

42

M1-M5 são de fato chaves regulares - elas só precisam ser especificamente ativadas antes de pressioná-las geram um scancode. tux_mark_5 desenvolveu um pequeno programa Haskell que envia a mensagem correta SET_REPORT para os teclados Razer para habilitar essas chaves, e o ex-papiro portou o mesmo código para o Python.

Nos sistemas Arch Linux, a porta Python foi empacotada e está disponível no link .

Em sistemas Debian ou Ubuntu, a configuração da porta Python do código é relativamente fácil. Você precisa instalar o PyUSB e libusb (como root):

    aptitude install python-usb

Em seguida, pegue o arquivo blackwidow_enable.py do link e execute-o (também como root):

    chmod +x blackwidow_enable.py
    ./blackwidow_enable.py

Isso ativará as teclas até que o teclado seja desconectado ou a máquina seja reinicializada. Para fazer isso, chame o script de qualquer estilo de script de inicialização que você preferir. Para obter instruções sobre como configurar isso no Debian, dê uma olhada nos Documentação Debian .

Para usar o código Haskell do tux_mark_5, você precisará instalar o Haskell e compilar o código. Estas instruções são para um sistema semelhante ao Debian (incluindo o Ubuntu).

  1. Instale o GHC, libusb-1.0-0-dev e cabal (como root):

    aptitude install ghc libusb-1.0-0-dev cabal-install git pkg-config
    
  2. Buscar a lista de pacotes:

    cabal update
    
  3. Instale ligações USB para o Haskell (sem necessidade de root):

    cabal install usb
    
  4. Baixe o utilitário:

    git clone git://github.com/tuxmark5/EnableRazer.git
    
  5. Construa o utilitário:

    cabal configure
    cabal build
    
  6. Execute o utilitário (também como root):

    ./dist/build/EnableRazer/EnableRazer
    

Depois disso, você pode copiar o EnableRazer binary em qualquer lugar e executá-lo na inicialização.

Imediatamente após a execução, o servidor X deve ver M1 como XF86Tools, M2 como XF86Launch5, M3 como XF86Launch6, M4 como XF86Launch7 e M5 como XF86Launch8. Eventos para FN também são emitidos.

Essas chaves podem ser vinculadas dentro de xbindkeys ou configurações do sistema do KDE a ações arbitrárias.

Como o seu teclado pode ser diferente, talvez seja necessário alterar o ID do produto na linha 64 do Main.hs:

withDevice 0x1532 0x<HERE GOES YOUR KEYBOARD's PRODUCT ID> $ \dev -> do
    
por 31.01.2012 / 16:57
22

A Razer parece estar forçando seu configurador Synapse 2 baseado na nuvem em todos os usuários hoje em dia, com o acompanhamento da atualização do firmware para a versão 2. *. Uma vez que você tenha atualizado o firmware, você não pode voltar atrás (o teclado está completamente bloqueado se você tentar fazer o flash com firmware mais antigo).

Os 'bytes mágicos' do programa Haskell em a resposta do tux_mark_5 não funcionará com o firmware mais recente. Em vez disso, o driver envia esses bytes durante a sequência de inicialização: "0200 0403". Elas habilitam as teclas macro, mas o teclado entra em um modo peculiar no qual, em vez do protocolo HID padrão, ele envia pacotes de 16 bytes (presumivelmente para aumentar o número de teclas que podem ser pressionadas simultaneamente). O sistema Linux HID não consegue lidar com isso e, embora a maioria das teclas funcione conforme o esperado, as teclas macro não são reconhecidas: o driver HID não alimenta nenhum dado na camada de entrada quando eles são pressionados.

Para fazer o seu teclado entrar no modo legado (no qual as teclas macro enviam códigos de tecla XF86Launch *, e a tecla FN envia o código de tecla 202), envie estes bytes: 0200 0402.

O pacote completo será:

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

Aqui está um programa muito duro e sujo que eu escrevi em Python 3 menos esotérico para executar a tarefa. Observe o código para gerar os pacotes de controle Razer em blackwidow.bwcmd () e os comandos de LED do logotipo Razer como bônus:)

#!/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()
    
por 15.09.2012 / 19:12
8

Talvez isso possa lançar alguma luz sobre o problema (da página de manobras do showkey):

No modo raw dos kernels 2.6, ou no modo scancode, não é muito bruto. Os códigos de escaneamento são primeiramente traduzidos para os códigos-chave e, quando os scancodes são desejados, os códigos-chave são convertidos de volta. Várias transformações estão envolvidas, e não há nenhuma garantia de que o resultado final corresponda ao que o hardware do teclado enviou. Então, se você quiser conhecer os códigos de varredura enviados por várias chaves, é melhor inicializar um kernel 2.4. Desde o 2.6.9 também existe a opção de inicialização atkbd.softraw = 0 que diz ao kernel 2.6 para retornar os códigos de scan atuais.

Os códigos de varredura brutos estão disponíveis somente nos teclados AT e PS / 2, e mesmo assim eles são desabilitados, a menos que o parâmetro do kernel atkbd.softraw = 0 seja usado. Quando os códigos de varredura brutos não estão disponíveis, o kernel usa uma tabela interna fixa para produzir códigos de varredura a partir de códigos de teclas. Assim, setkeycodes (8) podem afetar a saída de showkey no modo de dump de código de varredura.

Eu estou prestes a ver se showkey vai despejar qualquer coisa com as teclas de macro depois que essa opção de inicialização estiver definida.

EDIT: Após a reinicialização, não houve sucesso, mas eu estava olhando para a captura de entrada bruta dos próprios dispositivos USB. Eu observei o seguinte, curiosamente (eu tenho um Razer Diamondback assim como o 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]#

No entanto, usando o dd para capturar entrada bruta funciona nos dois mouses diamondback, no dispositivo event-kbd, mas não nos dispositivos de mouse BlackWidow.

Eu estou supondo que talvez eles não gerem nenhuma saída até que, de alguma forma, sejam ativados pelos drivers que estão instalados. Eu não sei muito sobre o Linux USB, então eu nem sei se isso faz sentido. Talvez eles precisem estar ligados primeiro?

Bem, todos os três dispositivos de viúvas negras são anotados em /proc/bus/input/devices , mas eles não parecem ser enumerados em lsusb ou /proc/bus/usb/devices . Não sei como acessar esses dispositivos para tentar vinculá-los ou fazer interface com eles de qualquer maneira.

event4 parece corresponder ao teclado real, event6 com as teclas macro, mas ainda não consigo capturar nenhuma entrada deles. Espero que tudo tenha ajudado.

   [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]# 
    
por 23.11.2011 / 01:32
7

Minha solução é para o Razer BlackWidow 2013 Mechanical Gaming Keyboard (Número do Modelo: RZ03-0039) e foi testado no openSUSE 12.3.

Eu usei o Google Tradutor em este link .

Basicamente, ele usa a versão modificada da @ resposta do Sergey para essa pergunta, mas com modificações simples:

  1. Meu PRODUCT_ID = 0x011b

  2. No meu openSUSE 12.3, o python-usb não está disponível para o Python 3, então eu convertei esse script para trabalhar com o Python 2 removendo o método bwcmd e definindo o USB_BUFFER = ... como na link da resposta de tux_mark_5 .

Por conveniência, aqui está o conteúdo do meu /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()

... e meu /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"
    
por 03.01.2014 / 21:32
2

Talvez este documento ajude você:

O teclado e console do Linux HOWTO , Programas úteis

    
por 02.10.2011 / 08:41
1

Veja Razer Key Mapper para Linux .

Isso funciona com todas as macros do dispositivo Razer, devido a algumas modificações no código. Se você ainda não tiver uma solução e seu dispositivo não estiver listado, ficarei feliz em ajudar você a configurar seu dispositivo e adicioná-lo à minha lista de suporte.

    
por 04.04.2018 / 16:27