Fix USB read length to match official tool protocol
The XVF3800 expects exact wLength: count * type_size + 1 (status byte). Requesting wrong length caused stale/corrupted responses when polling. Split _read into _read_uint16 and _read_float matching official format. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
30
xvf3800.py
30
xvf3800.py
@@ -53,17 +53,25 @@ class XVF3800:
|
|||||||
# don't call set_configuration() or detach_kernel_driver(),
|
# don't call set_configuration() or detach_kernel_driver(),
|
||||||
# the audio driver needs to keep its interface.
|
# the audio driver needs to keep its interface.
|
||||||
|
|
||||||
def _read(self, resid: int, cmdid: int, length: int) -> bytes:
|
def _read_uint16(self, resid: int, cmdid: int, count: int) -> bytes:
|
||||||
"""Read parameter via USB control transfer.
|
"""Read uint16 parameters. Returns raw bytes including 1-byte status header."""
|
||||||
wValue = cmdid | 0x80 (read flag), wIndex = resid."""
|
|
||||||
try:
|
try:
|
||||||
|
length = count * 2 + 1 # +1 for status byte
|
||||||
data = self.dev.ctrl_transfer(
|
data = self.dev.ctrl_transfer(
|
||||||
CTRL_REQUEST_TYPE_IN, 0,
|
CTRL_REQUEST_TYPE_IN, 0,
|
||||||
0x80 | cmdid, # wValue: cmdid with read bit
|
0x80 | cmdid, resid, length, timeout=1000)
|
||||||
resid, # wIndex: resource ID
|
return bytes(data)
|
||||||
length * 4, # bytes to read (length is in words)
|
except Exception as e:
|
||||||
timeout=1000
|
logger.debug("USB read error (resid=%d, cmd=%d): %s", resid, cmdid, e)
|
||||||
)
|
return b""
|
||||||
|
|
||||||
|
def _read_float(self, resid: int, cmdid: int, count: int) -> bytes:
|
||||||
|
"""Read float32 parameters. Returns raw bytes including 1-byte status header."""
|
||||||
|
try:
|
||||||
|
length = count * 4 + 1 # +1 for status byte
|
||||||
|
data = self.dev.ctrl_transfer(
|
||||||
|
CTRL_REQUEST_TYPE_IN, 0,
|
||||||
|
0x80 | cmdid, resid, length, timeout=1000)
|
||||||
return bytes(data)
|
return bytes(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug("USB read error (resid=%d, cmd=%d): %s", resid, cmdid, e)
|
logger.debug("USB read error (resid=%d, cmd=%d): %s", resid, cmdid, e)
|
||||||
@@ -88,10 +96,10 @@ class XVF3800:
|
|||||||
def read_doa(self) -> tuple[int, bool]:
|
def read_doa(self) -> tuple[int, bool]:
|
||||||
"""Read Direction of Arrival. Returns (angle 0-359, vad True/False).
|
"""Read Direction of Arrival. Returns (angle 0-359, vad True/False).
|
||||||
Response format: 1 status byte + 2 uint16 words (angle, vad)."""
|
Response format: 1 status byte + 2 uint16 words (angle, vad)."""
|
||||||
data = self._read(GPO_RESID, DOA_VALUE_CMD, 2) # 2 uint16 words
|
data = self._read_uint16(GPO_RESID, DOA_VALUE_CMD, 2)
|
||||||
if len(data) < 5: # 1 header + 4 data bytes
|
if len(data) < 5:
|
||||||
return 0, False
|
return 0, False
|
||||||
angle, vad = struct.unpack_from("<HH", data, 1) # skip 1-byte header
|
angle, vad = struct.unpack_from("<HH", data, 1) # skip status byte
|
||||||
return angle % 360, bool(vad)
|
return angle % 360, bool(vad)
|
||||||
|
|
||||||
# --- LEDs ---
|
# --- LEDs ---
|
||||||
|
|||||||
Reference in New Issue
Block a user