49

Я выбрал Razer BlackWidow Ultimate, в котором есть дополнительные ключи для макросов, которые устанавливаются с помощью инструмента, установленного в Windows. Я предполагаю, что это не какие-то причудливые ключи joojoo, и они должны генерировать сканкоды, как и любые другие ключи.

Во-первых, существует ли стандартный способ проверки этих скан-кодов в Linux? Во-вторых, как мне настроить эти ключи для работы в командной строке и X-based Linux? Моя текущая установка Linux - Xubuntu 10.10, но я перейду на Kubuntu, как только я исправлю некоторые вещи. В идеале ответ должен быть общим и общесистемным.

Вещи, которые я пробовал до сих пор:

Что мне нужно попробовать

  • Snoopy Pro + обратный инжиниринг (о дорогой)

  • Wireshark - предварительное возмущение указывает на отсутствие кодов сканирования, когда, как мне кажется, контролируется клавиатура и нажимаются клавиши. Может означать, что дополнительные ключи являются отдельным устройством или должны быть как-то инициализированы.

  • Нужно сделать перекрестную ссылку, чтобы при выводе lsusb из Linux в трех сценариях: автономный, передаваемый на виртуальную машину Windows без установленных драйверов и то же самое с.

  • LSUSB обнаруживает только одно устройство в автономной установке Linux

  • Может быть полезно проверить, используют ли мыши один и тот же драйвер Razer Synapse, так как это означает, что может работать некоторая вариация razercfg (не обнаружено, кажется, работает только для мышей)

Вещи, которые я разработал:

  • В системе Windows с драйвером клавиатура рассматривается как клавиатура и указательное устройство. Указывающее устройство использует, в дополнение к стандартным драйверам мыши, драйвер для чего-то, называемого Razer Synapse.

  • Драйвер мыши, видимый в Linux под evdev и lsusb также

  • Одиночное устройство под OS X, видимо, хотя мне еще предстоит попробовать эквивалент lsusb на этом

  • Клавиатура переходит в режим импульсной подсветки в OS X при инициализации с драйвером. Это, вероятно, должно указывать на то, что при активации на клавиатуре посылается последовательность инициализации.

  • На самом деле, они представляют собой необычные штаны-джу-джу.

Продолжим этот вопрос немного:

У меня есть доступ к системе Windows, поэтому, если мне нужно использовать какие-либо инструменты для ответа на вопрос, это нормально. Я также могу попробовать это на системах с и без утилиты конфигурации. Ожидаемый конечный результат все еще должен сделать эти ключи пригодными для использования в Linux.

Я также понимаю, что это очень специфическое семейство аппаратных средств. Я хотел бы протестировать все, что имеет смысл в системе Linux, если у меня есть подробные инструкции - это должно открыть вопрос для людей, которые имеют навыки работы с Linux, но не имеют доступа к этой клавиатуре.

Минимальный конечный результат, который мне требуется:

Мне нужно, чтобы эти клавиши были обнаружены и могли использоваться любым способом на любом из текущих графических основных вариантов Ubuntu, и, естественно, я должен работать с моей клавиатурой. Виртуальные куки и безумные реквизиты, если это что-то красиво упакованное и используемое обычным пользователем.

Мне потребуется скомпилированный код, который будет работать в моей системе, или источник, который я могу скомпилировать (с инструкциями, если он сложнее, чем ./configure , make , make install), если дополнительное программное обеспечение отсутствует в репозиториях Ubuntu для текущего LTS или стандарта. настольный релиз на момент ответа. Мне также потребуется достаточно информации для репликации и успешного использования ключей в моей собственной системе.

6 ответов6

42

M1-M5 на самом деле являются обычными клавишами - их просто нужно специально включить, прежде чем нажимать их, чтобы генерировать скан-код. tux_mark_5 разработал небольшую программу на Haskell, которая отправляет правильное сообщение SET_REPORT на клавиатуры Razer для включения этих клавиш, и 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.

Чтобы использовать код Haskell в tux_mark_5, вам нужно установить 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. Установите привязки USB для Haskell (без рута):

    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:

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

В настоящее время Razer, похоже, навязывает свой облачный конфигуратор Synapse 2 всем пользователям, сопровождая обновление прошивки до версии 2.*. После того, как вы обновили прошивку, вы не сможете вернуться назад (клавиатура полностью заглушена, если вы пытаетесь прошить ее более старой прошивкой).

«Волшебные байты» из программы на Haskell в ответе tux_mark_5 не будут работать с последней прошивкой. Вместо этого драйвер отправляет эти байты во время последовательности инициализации: «0200 0403». Они активируют макроклавиши, но клавиатура входит в особый режим, в котором вместо стандартного протокола HID она отправляет 16-байтовые пакеты (предположительно, для увеличения количества клавиш, которые могут быть нажаты одновременно). Система 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 для выполнения этой задачи. Обратите внимание на код для генерации управляющих пакетов Razer в blackwidow.bwcmd() и команды LED Razer logo в качестве бонуса :)

#!/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()
8

Возможно, это могло бы пролить некоторый свет на проблему (с man-страницы showkey):

В ядре 2.6 режим raw или режим скан-кода совсем не очень сырой. Сканированные коды сначала переводятся в коды клавиш, а когда требуются коды сканирования, коды клавиш переводятся обратно. Различные преобразования происходят, и нет никакой гарантии, что конечный результат соответствует тому, что выслало аппаратное обеспечение клавиатуры. Итак, если вы хотите узнать коды сканирования, отправленные различными ключами, лучше загрузить ядро 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]# 
7

Мое решение предназначено для механической игровой клавиатуры Razer BlackWidow 2013 (номер модели: RZ03-0039) и протестировано на openSUSE 12.3.

Я использовал Google Translate по этой ссылке.

В основном он использует измененную версию ответа @ Sergey на этот вопрос, но с простыми изменениями:

  1. Мой PRODUCT_ID = 0x011b

  2. В моем openSUSE 12.3 python-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"
2

Может быть, этот документ поможет вам:

Клавиатура и консоль Linux HOWTO, Полезные программы

1

Смотрите Razer Key Mapper для Linux.

Это работает со всеми макросами устройства Razer, учитывая некоторую модификацию кода. Если у вас все еще нет решения, а ваше устройство отсутствует в списке, я буду рад помочь вам настроить его и добавить в список поддерживаемых.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .