Browse Source

Improve device detection

master
Martchus 5 years ago
parent
commit
ef7cfe38c5
  1. 12
      README.md
  2. 107
      blackwidowcontrol.py
  3. 3
      razer_blackwidow.rules

12
README.md

@ -1,16 +1,22 @@
# BlackWidow control
Python 3 script to enable macro keys of BlackWidow keyboard under GNU/Linux
It just enables the macro keys which can then be configured as hotkeys in your desktop environment. However it does not enable the ability to record macros and to switch between different configurations like the Windows driver does.
It just enables the macro keys which can then be configured as hotkeys in your desktop environment.
However it does not enable the ability to record macros and to switch between different configurations
like the Windows driver does.
## Supported devices
The script is know to work with the following BlackWidow editions:
- regular edition (the ceapest one which has no background light)
- the regular 2013 edition
The script likely works with the following BlackWidow editions:
- The script likely works with the 2014 version, too.
- The script likely works with the ultimate editions, too.
If you can confirm that those or other devices work or don't work, let me now by editing this file.
### Notes
- The script likely works with the ultimate editions, too. However, this has not
been tested yet.
- The script does not work with the 2016 editions (yet).
- The script has been tested using the firmware update from Razer Synapse 2.0.
Hence the script might not work when an older firmware version is used.

107
blackwidowcontrol.py

@ -4,72 +4,85 @@ from optparse import OptionParser
import usb
import sys
VENDOR_ID = 0x1532 # Razer
PRODUCT_ID_BLACK_WIDOW = 0x010e # BlackWidow / BlackWidow Ultimate
PRODUCT_ID_BLACK_WIDOW_2013 = 0x011b # BlackWidow 2013
USB_REQUEST_TYPE = 0x21 # Host To Device | Class | Interface
USB_REQUEST = 0x09 # SET_REPORT
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
VENDOR_ID = 0x1532 # Razer
PRODUCT_ID_BLACK_WIDOW = 0x010e # BlackWidow
PRODUCT_ID_BLACK_WIDOW_ULTIMATE = 0x011a # BlackWidow Ultimate
PRODUCT_ID_BLACK_WIDOW_2013 = 0x011b # BlackWidow 2013/2014
class blackwidow(object):
kernel_driver_detached = False
detected_keyboard = None
PRODUCTS = [("Black Widow", PRODUCT_ID_BLACK_WIDOW),
("Black Widow Ultimate", PRODUCT_ID_BLACK_WIDOW_ULTIMATE),
("Black Widow 2013/2014", PRODUCT_ID_BLACK_WIDOW_2013)]
LOG=sys.stderr.write
class BlackWidow(object):
def __init__(self):
self.device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID_BLACK_WIDOW)
self.kernel_driver_detached = False
self.interface_claimed = False
self.detected_keyboard = None
if self.device is None:
self.device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID_BLACK_WIDOW_2013)
if self.device is None:
LOG("No device found\n")
return
else:
LOG("Found device: Black Widow 2013\n")
detected_keyboard = PRODUCT_ID_BLACK_WIDOW_2013
else:
LOG("Found device: Black Widow\n")
detected_keyboard = PRODUCT_ID_BLACK_WIDOW
self.find_device()
if self.device_found():
self.claim_interface()
if self.device.is_kernel_driver_active(USB_INTERFACE):
LOG("Kernel driver active; detaching it\n")
def __del__(self):
if self.interface_claimed:
self.release_interface()
self.device.detach_kernel_driver(USB_INTERFACE)
self.kernel_driver_detached = True
def find_device(self):
for product_name, product_id in PRODUCTS:
self.device = usb.core.find(idVendor=VENDOR_ID, idProduct=product_id)
if self.device:
detected_keyboard = product_id
LOG("Found device: %s\n" % product_name)
break
LOG("Claiming interface\n")
usb.util.claim_interface(self.device, USB_INTERFACE)
def device_found(self):
return self.device is not None
def __del__(self):
if self.device_found():
def claim_interface(self):
try:
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)
self.interface_claimed = True
except:
LOG("Unable to claim interface. Ensure the script is running as root.\n")
raise
def release_interface(self):
if self.interface_claimed:
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):
def format_command(self, command):
from functools import reduce
c1 = bytes.fromhex(c)
c1 = bytes.fromhex(command)
c2 = [ reduce(int.__xor__, c1) ]
b = [0] * 90
b[5:5+len(c1)] = c1
b[-2:-1] = c2
return bytes(b)
def device_found(self):
return self.device is not None
def send(self, c):
def _send(msg):
USB_BUFFER = self.bwcmd(msg)
def send(self, command):
def internal_send(msg):
USB_BUFFER = self.format_command(command)
result = 0
try:
result = self.device.ctrl_transfer(USB_REQUEST_TYPE, USB_REQUEST, wValue=USB_VALUE, wIndex=USB_INDEX, data_or_wLength=USB_BUFFER)
@ -79,14 +92,15 @@ class blackwidow(object):
LOG("Data sent successfully\n")
return result
if isinstance(c, list):
for i in c:
if isinstance(command, list):
for i in command:
print(' >> {}\n'.format(i))
_send(i)
elif isinstance(c, str):
_send(c)
internal_send(i)
elif isinstance(command, str):
internal_send(command)
def main():
#
init_new = '0200 0403'
init_old = '0200 0402'
no_pulsate = '0303 0201 0400'
@ -103,7 +117,7 @@ def main():
parser.add_option("-g", "--set-game-mode", type="string", dest="gamemode", default="unmodified", help="sets whether the game mode is enabled (on/off)")
(options, args) = parser.parse_args()
bw = blackwidow()
bw = BlackWidow()
if bw.device_found():
# enable macro keys
if options.init == True:
@ -183,5 +197,8 @@ def main():
else:
LOG("Specified value for game mode is unknown and will be ignored.\n")
else:
LOG("No device found\n")
if __name__ == '__main__':
main()

3
razer_blackwidow.rules

@ -1,3 +1,4 @@
# udev rule to initiate BlackWidow keyboard when connected
# udev rule to initiate BlackWidow keyboards when connected
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1532", ATTR{idProduct}=="010e", RUN+="/usr/bin/blackwidowcontrol -i"
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1532", ATTR{idProduct}=="011a", RUN+="/usr/bin/blackwidowcontrol -i"
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1532", ATTR{idProduct}=="011b", RUN+="/usr/bin/blackwidowcontrol -i"

Loading…
Cancel
Save