Last active
August 3, 2020 23:52
-
-
Save andreldm/367f0dba38da9c59e9f169fe0dd570fd to your computer and use it in GitHub Desktop.
Corsair Harpoon RGB Wireless basic protocol debugging, see https://github.com/andreldm/harpoond
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Setup: | |
# python -m venv env | |
# source env/bin/activate | |
# pip install pyusb | |
# | |
# Execute with: sudo python test.py | |
# See udev rule present in (2) if you want to avoid running as root. | |
# | |
# References: | |
# 1. https://wiki.wireshark.org/CaptureSetup/USB | |
# 2. https://slomkowski.eu/tutorials/eavesdropping-usb-and-writing-driver-in-python | |
# 3. https://mvidner.blogspot.com/2017/01/usb-communication-with-python-and-pyusb.html | |
# 4. https://github.com/Benzhaomin/pyrmi/blob/master/main.py | |
import sys | |
import usb.core | |
import usb.util | |
import sched, time | |
VENDOR_ID = 0x1b1c | |
WIRED_DEVICE_ID = 0x1b5e | |
DONGLE_DEVICE_ID = 0x1b65 | |
WIRED = True | |
COMMAND_PREFIX = 0x08 | |
dev = usb.core.find(idVendor=VENDOR_ID, idProduct=WIRED_DEVICE_ID) | |
if dev is None: | |
print("Wired default not found, looking for dongle...") | |
WIRED = False | |
COMMAND_PREFIX = 0x09 | |
dev = usb.core.find(idVendor=VENDOR_ID, idProduct=DONGLE_DEVICE_ID) | |
assert dev | |
interface = 1 # INTERFACE 1: Human Interface Device | |
reader = dev[0][(interface, 0)][0] # ENDPOINT 0x84: Interrupt IN | |
writer = dev[0][(interface, 0)][1] # ENDPOINT 0x04: Interrupt OUT | |
def write(data): | |
padding = [0x0]*(64 - len(data)) | |
writer.write(data + padding, timeout=100) | |
def read(): | |
data = reader.read(reader.bEndpointAddress, reader.wMaxPacketSize) | |
return bytes(data).hex() | |
def send(data): | |
write(data) | |
print(read()) | |
def grab_device(): | |
if dev.is_kernel_driver_active(interface): | |
try: | |
dev.detach_kernel_driver(interface) | |
usb.util.claim_interface(dev, interface) | |
except usb.core.USBError as e: | |
sys.exit("Could not detach kernel driver: %s" % str(e)) | |
def ungrab_device(): | |
usb.util.release_interface(dev, interface) | |
dev.attach_kernel_driver(interface) | |
grab_device() | |
# Init | |
send([0x08, 0x01, 0x03, 0x00, 0x02]) | |
if WIRED: | |
send([0x08, 0x0d, 0x00, 0x01]) | |
else: | |
send([0x09, 0x01, 0x03, 0x00, 0x02]) | |
send([0x09, 0x0d, 0x00, 0x01]) | |
# Set my configuration | |
send([COMMAND_PREFIX, 0x06, # Command to manipulate LEDs ? | |
0x00, 0x06, # ? | |
0x00, 0x00, 0x00, # ? | |
0x00, # Indicator LED's red | |
0x00, # Main LED's red | |
0xff, # Indicator LED's green | |
0x00, # Main LED's green | |
0x00, # Indicator LED's blue | |
0x00 # Main LED's blue | |
]) | |
#send([COMMAND_PREFIX, 0x01, 0x20, 0x00, 0xe8, 0x03]) # Set DPI to 1000 (3e8 = 1000) | |
#send([COMMAND_PREFIX, 0x01, 0x20, 0x00, 0xb8, 0x0b]) # Set DPI to 3000 (b8b = 2955) | |
send([COMMAND_PREFIX, 0x01, 0x20, 0x00, 0x08, 0x70]) # Set DPI to 1800 (708 = 1800) | |
ungrab_device() | |
s = sched.scheduler(time.time, time.sleep) | |
def keep_alive(sc): | |
grab_device() | |
send([COMMAND_PREFIX, 0x12]) # Keep alive, has to be sent every minute or mouse will reset to defaults | |
ungrab_device() | |
s.enter(55, 1, keep_alive, (sc,)) | |
s.enter(55, 1, keep_alive, (s,)) | |
s.run() | |
# Packets sent when iCue is initialized (captured with Wireshark) | |
# | |
# WIRED | |
# | |
# send([0x08, 0x02, 0x03]) # ? | |
# send([0x08, 0x01, 0x03, 0x00, 0x02]) # REQUIRED, if executed alone, Main LED freezes | |
# send([0x08, 0x02, 0x03]) # ? | |
# send([0x08, 0x02, 0x5f]) # ? | |
# send([0x08, 0x02, 0x01]) # ? | |
# send([0x08, 0x02, 0x03]) # ? | |
# send([0x08, 0x02, 0x13]) # ? | |
# send([0x08, 0x0d, 0x00, 0x05]) # ? | |
# send([0x08, 0x09]) # ? | |
# send([0x08, 0x08]) # ? | |
# send([0x08, 0x05, 0x01]) # ? | |
# send([0x08, 0x0d, 0x00, 0x27]) # ? | |
# send([0x08, 0x01, 0x03, 0x00, 0x02]) # ? | |
# send([0x08, 0x0d, 0x00, 0x05]) # ? | |
# send([0x08, 0x09]) # ? | |
# send([0x08, 0x08]) # ? | |
# send([0x08, 0x05, 0x01]) # ? | |
# send([0x08, 0x02, 0x0f]) # ? | |
# send([0x08, 0x02, 0x10]) # ? | |
# send([0x08, 0x02, 0x0b]) # ? | |
# send([0x08, 0x02, 0x0d]) # ? | |
# send([0x08, 0x02, 0x0e]) # ? | |
# send([0x08, 0x01, 0x02, 0x00, 0xe8, 0x03]) # ? | |
# send([0x08, 0x02, 0x15]) # ? | |
# send([0x08, 0x01, 0x20, 0x00, 0x90, 0x01]) # ? | |
# send([0x08, 0x0d, 0x00, 0x02]) # ? | |
# send([0x08, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01]) # ? | |
# send([0x08, 0x05, 0x01]) # ? | |
# send([0x08, 0x0d, 0x00, 0x02]) # ? | |
# send([0x08, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01]) # ? | |
# send([0x08, 0x05, 0x01]) # ? | |
# send([0x08, 0x01, 0x07]) # ? | |
# send([0x08, 0x0d, 0x00, 0x01]) # REQUIRED, ? | |
# send([0x08, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0x13, 0x00, 0x00, 0x00, 0xc5]) # Sets DPI Indicator LED to red | |
# send([0x08, 0x02, 0x15]) # ? | |
# Makes DPI Indicator LED oscillate between green and off twice | |
# for x in [ | |
# 0x04, 0x08, 0x0c, 0x10, 0x19, 0x1d, 0x21, 0x2a, 0x2e, 0x33, 0x3b, 0x3f, | |
# 0x44, 0x48, 0x4c, 0x51, 0x55, 0x59, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x73, | |
# 0x77, 0x7b, 0x80, 0x7e, 0x7a, 0x76, 0x71, 0x6d, 0x69, 0x64, 0x60, 0x5c, | |
# 0x57, 0x53, 0x4f, 0x4b, 0x46, 0x42, 0x3e, 0x39, 0x35, 0x31, 0x2d, 0x29, | |
# 0x24, 0x1f, 0x1b, 0x17, 0x13, 0x0e, 0x0a, 0x06, 0x01, 0x00, 0x04, 0x08, | |
# 0x0d, 0x11, 0x15, 0x1a, 0x1e, 0x22, 0x27, 0x2b, 0x2f, 0x33, 0x38, 0x3c, | |
# 0x40, 0x44, 0x49, 0x4d, 0x51, 0x56, 0x5a, 0x5f, 0x63, 0x67, 0x6b, 0x70, | |
# 0x74, 0x78, 0x7c, 0x80, 0x7d, 0x79, 0x74, 0x70, 0x6c, 0x67, 0x63, 0x5f, | |
# 0x5a, 0x56, 0x52, 0x4e, 0x49, 0x45, 0x41, 0x3b, 0x37, 0x32, 0x2e, 0x2a, | |
# 0x26, 0x21, 0x1d, 0x19, 0x14, 0x10, 0x0c, 0x08, 0x03, 0x00]: | |
# send([0x08, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x13, x, 0x00, 0x00, 0xc5]) | |
# send([0x08, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0x13, 0x00, 0x00, 0x00, 0xc5]) # Sets DPI Indicator LED to red | |
# | |
# DONGLE | |
# | |
# send([0x08, 0x02, 0x03]) # ? | |
# send([0x08, 0x01, 0x03, 0x00, 0x02]) # REQUIRED, if executed alone, Main LED freezes | |
# send([0x08, 0x02, 0x03]) # ? | |
# send([0x08, 0x02, 0x5f]) # ? | |
# send([0x08, 0x02, 0x01]) # ? | |
# send([0x08, 0x02, 0x03]) # ? | |
# send([0x08, 0x02, 0x13]) # ? | |
# send([0x08, 0x02, 0x14]) # ?, this is different from the sequence of Wired initialization | |
# send([0x08, 0x0d, 0x00, 0x05]) # ? | |
# send([0x08, 0x09]) # ? | |
# send([0x08, 0x08]) # ? | |
# send([0x08, 0x05, 0x01]) # ? | |
# send([0x08, 0x0d, 0x00, 0x27]) # ? | |
# send([0x08, 0x01, 0x03, 0x00, 0x02]) # ? | |
# send([0x08, 0x0d, 0x00, 0x05]) # ? | |
# send([0x08, 0x09]) # ? | |
# send([0x08, 0x08]) # ? | |
# send([0x08, 0x05, 0x01]) # ? | |
# send([0x08, 0x02, 0x36]) # ?, at this point the sequence diverges from Wired initialization | |
# send([0x09, 0x02, 0x11]) # ? | |
# send([0x09, 0x02, 0x12]) # ? | |
# send([0x09, 0x02, 0x03]) # ? | |
# send([0x09, 0x01, 0x03, 0x00, 0x02]) # REQUIRED, ? | |
# send([0x09, 0x02, 0x03]) # ? | |
# send([0x09, 0x02, 0x5f]) # ? | |
# send([0x09, 0x02, 0x01]) # ? | |
# send([0x09, 0x02, 0x03]) # ? | |
# send([0x09, 0x02, 0x13]) # ? | |
# send([0x09, 0x02, 0x14]) # ? | |
# send([0x09, 0x0d, 0x00, 0x05]) # ? | |
# send([0x09, 0x09]) # ? | |
# send([0x09, 0x08]) # ? | |
# send([0x09, 0x05, 0x01]) # ? | |
# send([0x09, 0x0d, 0x00, 0x27]) # ? | |
# send([0x09, 0x0d, 0x00, 0x05]) # ? | |
# send([0x09, 0x09]) # ? | |
# send([0x09, 0x08]) # ? | |
# send([0x09, 0x05, 0x01]) # ? | |
# send([0x09, 0x02, 0x15]) # ? | |
# send([0x09, 0x02, 0x0f]) # ? | |
# send([0x09, 0x02, 0x10]) # ? | |
# send([0x09, 0x02, 0x0b]) # ? | |
# send([0x09, 0x02, 0x0d]) # ? | |
# send([0x09, 0x02, 0x0e]) # ? | |
# send([0x09, 0x01, 0x02, 0x00, 0xe8, 0x03]) # ? | |
# send([0x09, 0x02, 0x15]) # ? | |
# send([0x09, 0x0d, 0x00, 0x02]) # ? | |
# send([0x09, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01]) # ? | |
# send([0x09, 0x05, 0x01]) # ? | |
# send([0x09, 0x05, 0x07]) # ? | |
# send([0x09, 0x0d, 0x00, 0x02]) # ? | |
# send([0x09, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01]) # ? | |
# send([0x09, 0x05, 0x01]) # ? | |
# send([0x09, 0x02, 0x0f]) # ? | |
# send([0x09, 0x02, 0x10]) # ? | |
# send([0x09, 0x01, 0x02, 0x00, 0xe8, 0x03]) # ? | |
# send([0x09, 0x02, 0x15]) # ? | |
# send([0x09, 0x0d, 0x00, 0x02]) # ? | |
# send([0x09, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01]) # ? | |
# send([0x09, 0x05, 0x01]) # ? | |
# send([0x09, 0x01, 0x07]) # ? | |
# send([0x09, 0x0d, 0x00, 0x02]) # ? | |
# send([0x09, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01]) # ? | |
# send([0x09, 0x05, 0x01]) # ? | |
# send([0x09, 0x01, 0x20, 0x00, 0x40, 0x06]) # ? | |
# send([0x09, 0x02, 0x40]) # ? | |
# send([0x09, 0x02, 0x0b]) # ? | |
# send([0x09, 0x02, 0x0d]) # ? | |
# send([0x09, 0x02, 0x0e]) # ? | |
# send([0x09, 0x0d, 0x00, 0x01]) # REQUIRED, ? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Solid work
I wanna detect screen dimming with Python so I can dim the mouse with it and other things. Haven't been able to find anything either kde focused or in general.