Skip to content

Instantly share code, notes, and snippets.

@arisada
Created December 24, 2022 13:56
Show Gist options
  • Save arisada/b33d3cf068080ee2387e0b5674dac7f4 to your computer and use it in GitHub Desktop.
Save arisada/b33d3cf068080ee2387e0b5674dac7f4 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import usb.core
import usb.util
import usb.control
import time
cmd_calibrate = [0x03, 0x7e, 0x5a, 0x01, 0x01]
#bidirectional
cmd_setpos_bi = [0x03, 0x7e, 0x5a, 0x01, 0x3]
#unidirectional
cmd_setpos_uni = [0x03, 0x7e, 0x5a, 0x01, 0x2]
#getalias
cmd_getalias = [0x03, 0x7e, 0x5a, 0x02, 0x0d] + [0] * 11
cmd_setalias = [0x03, 0x7e, 0x5a, 0x0d] # + 12 bytes
cmd_open = [0x03, 0x7e, 0x5a, 0x02, 0x04]
cmd_getserialnumber = [0x03, 0x7e, 0x5a, 0x02, 0x0c]
cmd_read_wheel_status = [0x03, 0x7e, 0x5a, 0x02, 0x01]
# it's executed in case or error??
cmd_reset = [0x03, 0x7e, 0x5a, 0x01, 0x0f]
class EFW():
def __init__(self):
dev = usb.core.find(idVendor=0x03c3, idProduct=0x1f01)
if dev is None:
raise ValueError('Device not found')
print("Device found")
if dev.is_kernel_driver_active(0):
print("kernel driver active")
dev.detach_kernel_driver(0)
dev.set_configuration()
print("Device configured")
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
ep = usb.util.find_descriptor(
intf,
# match the first OUT endpoint
custom_match = \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT)
if ep is None:
raise ValueError("No out descriptor")
self.dev=dev
def hex(self, data):
return " ".join(bytes((i,)).hex() for i in data)
def send_report(self, data, reply=False):
#reqtype = 0x21, bReq=0x09 wVal=0x303 wIndex=0
self.dev.ctrl_transfer(0x21, 0x09, 0x303, 0, data)
if reply:
time.sleep(0.2)
result = self.dev.ctrl_transfer(0xA1, 0x01, 0x0301, 0, 17)
return bytes(result)
def open(self):
reply = self.send_report(cmd_open, reply=True)
v6 = reply[4] * 100 + reply[5] * 10 + reply[6]
print("v6:", v6)
name = reply[8:].strip(b'\x00')
return name
def getAlias(self):
self.open()
reply = self.send_report(cmd_getalias, reply=True)
print(reply[4:])
def getSerialNumber(self):
self.open()
reply = self.send_report(cmd_getserialnumber, reply=True)
print(bytes(reply[4:10]).hex(), bytes(reply[10:]).hex())
sn = (reply[4] * 16 + reply[5],
reply[6] * 16 + reply[7],
reply[8] * 16 + reply[9],
(reply[10] * 16) & 0xff + reply[11] >> 4,
(reply[11] * 16) & 0xf0 + reply[12] >> 4,
(reply[12] * 16) & 0xf0 + reply[13] >> 4,
(reply[13] * 16) & 0xf0 + reply[14] >> 4,
(reply[14] * 16) & 0xf0 + reply[15])
#sn = [i & 0xff for i in sn]
return bytes(sn).hex()
def clearError(self):
result = self.send_report(cmd_read_wheel_status, reply=True)
self.wheel_status_buf = bytes(result)
print(self.hex(result))
if self.wheel_status_buf[4] == 6:
print("Error condition?")
print("state:", self.wheel_status_buf[4], self.wheel_status_buf[5])
print("status[8]", self.wheel_status_buf[8])
print("status[12]", self.wheel_status_buf[12])
print("Current wheel position status[6]", self.wheel_status_buf[6])
print("wheel total positions status[9]:", self.wheel_status_buf[9])
def setPosition(self, pos, unidirectional=False):
if unidirectional:
self.send_report(cmd_setpos_uni + [pos % 6])
else:
self.send_report(cmd_setpos_bi + [pos % 6])
efw = EFW()
name = efw.open()
efw.setPosition(5, False)
efw.clearError()
# #dev.ctrl_transfer(0x21, 0x09, 0x0, 0, cmd_calibrate)
# time.sleep(0.2)
# result = dev.ctrl_transfer(0xA1, 0x01, 0x0301, 0, 17)
# print(result)
# dev.ctrl_transfer(0x21, 0x09, 0x303, 0, cmd_getalias)
# time.sleep(0.2)
# result = dev.ctrl_transfer(0xA1, 0x01, 0x0301, 0, 17)
# print(list(result))
# print("Done")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment