firmware/ev3: allow buggy replies from EV3 bootloader

Add a hack to not fail if the EV3 bootloader sends an echo of the request
instead of the expected response. There is a known compatibility issue
with the EV3 bootloader USB and, e.g. Windows with USB 3.0 ports. This
apparently causes a race condition where commands that don't take long
to process before sending a response will have the request echoed back
instead of receiving the actual response. If this happens, we can
ignore it and assume the command was successful. It just won't work, e.g.
for the version command since that has a payload in the response.
This commit is contained in:
David Lechner
2026-01-24 16:16:02 -06:00
parent c8d7f6090b
commit 04697e9afa
+24 -7
View File
@@ -1107,16 +1107,33 @@ function* handleFlashEV3(action: ReturnType<typeof firmwareFlashEV3>): Generator
continue; // ignore empty reports
}
const length = event.data.getInt16(0, true);
let length = event.data.getInt16(0, true);
const replyNumber = event.data.getInt16(2, true);
const messageType = event.data.getUint8(4);
let messageType = event.data.getUint8(4);
const replyCommand = event.data.getUint8(5);
const status = event.data.getUint8(6);
const payload = event.data.buffer.slice(7, 7 + length + 2);
let status = event.data.getUint8(6);
let payload = event.data.buffer.slice(7, 7 + length + 2);
console.debug(
`EV3 reply: length=${length}, replyNumber=${replyNumber}, messageType=${messageType}, replyCommand=${replyCommand}, status=${status}, payload=${payload}`,
);
if (messageType === 0x01) {
// HACK: This works around a strange bug that can be triggered
// e.g. by USB 3.0 on Windows. Sometimes the EV3 bootloader will
// send the request back instead of the reply. In this case,
// fake the reply to avoid protocol errors. This seems to work
// as long as we aren't sending commands that have a reply
// with a payload (like reading version or checksum)
console.warn(
`Bad EV3 reply: length=${length}, replyNumber=${replyNumber}, messageType=${messageType}, replyCommand=${replyCommand}, status=${status}`,
);
length = 5;
messageType = 0x03;
status = 0x00;
payload = new ArrayBuffer(0);
console.info(
`Fixed EV3 reply: length=${length}, replyNumber=${replyNumber}, messageType=${messageType}, replyCommand=${replyCommand}, status=${status}`,
);
}
yield* put(
firmwareDidReceiveEV3Reply(