Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
import sys
import hid
from time import sleep
from keycode_converter import keycode, step
vendor_id = 0xfeed
product_id = 0x0000
usage_page = 0xFF60
usage = 0x61
report_length = 32
fragment_payload_size = 27
ENCODER_COMMAND = 0
COMMAND = 1
REPEAT_COMMAND = 2
def get_raw_hid_interface():
device_interfaces = hid.enumerate(vendor_id, product_id)
raw_hid_interfaces = [i for i in device_interfaces if i['usage_page'] == usage_page and i['usage'] == usage]
if len(raw_hid_interfaces) == 0:
return None
interface = hid.Device(path=raw_hid_interfaces[0]['path'])
print(f"Manufacturer: {interface.manufacturer}")
print(f"Product: {interface.product}")
return interface
def send_raw_report(data):
interface = get_raw_hid_interface()
if interface is None:
print("No device found")
sys.exit(1)
request_data = [0x00] * (report_length + 1)
request_data[1:len(data) + 1] = data
request_report = bytes(request_data)
print("Request:")
print(request_report)
try:
interface.write(request_report)
finally:
interface.close()
def build_macro_update(layer, macro_index, macro_steps):
payload = [layer, macro_index, len(macro_steps)]
for step in macro_steps:
payload.append(len(step))
for keycode in step:
payload.append((keycode >> 8) & 0xFF)
payload.append(keycode & 0xFF)
return payload
def send_fragmented_report(transaction_id, payload):
chunks = [payload[i:i + fragment_payload_size] for i in range(0, len(payload), fragment_payload_size)]
total_fragments = len(chunks)
for fragment_index, chunk in enumerate(chunks):
send_raw_report([COMMAND, transaction_id, total_fragments, fragment_index, len(chunk)] + chunk)
def send_fragmented_macro_update(layer, macro_index, macro_steps):
payload = build_macro_update(layer, macro_index, macro_steps)
transaction_id = 1
send_fragmented_report(transaction_id, payload)
def build_encoder_update(layer, clockwise_action, counterclockwise_action):
return [
ENCODER_COMMAND,
layer,
(clockwise_action >> 8) & 0xFF,
clockwise_action & 0xFF,
(counterclockwise_action >> 8) & 0xFF,
counterclockwise_action & 0xFF,
]
def send_encoder_update(layer, clockwise_action, counterclockwise_action):
payload = build_encoder_update(layer, clockwise_action, counterclockwise_action)
send_raw_report(payload)
def build_repeating_macro_update(layer, macro_index, repeat_interval):
return [
REPEAT_COMMAND,
layer,
macro_index,
(repeat_interval >> 8) & 0xFF,
repeat_interval & 0xFF,
0,
]
def send_repeating_macro_update(layer, macro_index, repeat_interval):
payload = build_repeating_macro_update(layer, macro_index, repeat_interval)
send_raw_report(payload)
if __name__ == '__main__':
# On layer 0, key 4 goes to layer 5.
send_fragmented_macro_update(
layer=0,
macro_index=4,
macro_steps=[step("SWITCH_LAYER_5")],
)
# On layer 5, key 5 sends Ctrl+C.
send_fragmented_macro_update(
layer=5,
macro_index=5,
macro_steps=[step("LCTL(KC_C)")],
)
# Configure the encoder for layer 5 to control screen brightness.
send_encoder_update(
layer=5,
clockwise_action=keycode("KC_A"),
counterclockwise_action=keycode("KC_B"),
)
# On layer 5, key 4 returns to layer 0.
send_fragmented_macro_update(
layer=5,
macro_index=4,
macro_steps=[step("SWITCH_LAYER_0")],
)
# Make layer 5 key 6 repeat its macro every 100ms until pressed again.
send_repeating_macro_update(
layer=5,
macro_index=5,
repeat_interval=100,
)
953c8afbeThis file is pinned to the selected release. Download the original to open it in your design tool.