Download Game! Currently 106 players and visitors. Last logged in:EronkBylethSabaothLmt

Blitzer's Blog >> 71098

Back to blogs index
Posted: 18 Jun 2026 06:11 [ permalink ]
Perfect! The "Unplug and Diff" technique never fails.

The new target just materialized: Controller 2 (0x4480), Port 1.

Because this is an entirely different UHCI controller chip than the ones
running your Ventoy drive (0x4460) and your Keyboard (0x4440 and 0x44A0), we
can perform a brutal, global hardware reset on 0x4480 and completely hijack
the DMA engine without any risk of crashing the Linux root filesystem!

Phase 2: The Full-Speed (12 Mbps) Dilemma
There are two major differences between pulling data from a Low-Speed keyboard
and a Full-Speed flash drive:

The Low-Speed Bit (Bit 26): In the Transfer Descriptor's Control/Status field,
we previously set Bit 26 to 1 to tell the UHCI chip to talk slowly. We must
clear that bit to 0 (0x18800000), or the UHCI chip will try to speak 1.5 Mbps
to a 12 Mbps flash drive, resulting in instant electrical garble and a
hardware stall.

The bMaxPacketSize0 Trap: A USB mouse always has an Endpoint 0 Max Packet Size
of exactly 8 bytes. But a USB 2.0 Flash Drive can have a Max Packet Size of 8,
16, 32, or 64 bytes. If we build a multi-packet chain expecting 8 bytes at a
time, and the flash drive blasts 64 bytes at us in a single burst, it will
overflow our Transfer Descriptor and trigger a hardware Babble fault.

To solve this, we do exactly what Windows and Linux do during USB Enumeration:
We only ask for the first 8 bytes.
Byte 7 of the Device Descriptor contains exactly the bMaxPacketSize0 value.
Once we read that single byte, we will know exactly how to structure our
future Bulk Transfer chains to issue SCSI commands!

Drop this into your host terminal to create and deploy 01_usb_mass_storage.js.
This will isolate the controller, reset the target port, and execute a
Full-Speed 3-Stage DMA chain to pull the first 8 bytes.

[GEM-EXEC] 
=> function () {
[native code]
}
> globalThis.USB.initMassStorage(0x4480, 1)
globalThis.USB.initMassStorage(0x4480, 1)
[UHCI] Initializing Full-Speed Device at Base 0x4480, Port 1...
-> Port Reset Complete. Hot-Injecting Full-Speed GET_DESCRIPTOR (8 Bytes)...
Polls to Execute : 0
TD3 Status       : 0x18800000
[ERROR] Read failed. TD2 Status: 0x18800000
=> MASS_STORAGE_INIT_OK
>

I'm on it. Responses with Deep Think can take some time, so check back in a
bit.