Regression. OpenIPC/PixelPilot#6 is back: no video on MediaTek Android devices (Dimensity 810 report, 2026-07-19, PixelPilot master build). PixelPilot#104 bumped its devourer submodule from bbc7385 to 73f1cb4.
History. On some MediaTek Android xhci/usbfs stacks (Dimensity 810, Helio G99, MT6765) a bulk-IN read larger than 16 KB never completes — LIBUSB_ERROR_TIMEOUT forever, zero RX with a green init. @floppyhammer's #19 (bbc7385) fixed this with two halves:
- device-side USB RX aggregation capped ≤16 KB (
rxagg_usb_size/timeout: USB3 0x7/0x1a → 0x3/0x01, USB2 0x5/0x20 → 0x1/0x01)
- host-side reads capped at 16 KB (
infinite_read buffer 65000 → 16 KB)
What regressed. The RX rewrites (#158/#164/#168) and the #213 transport split (40e3a2a, which deleted RtlUsbAdapter.cpp) kept the aggregation half (RtlAdapter.cpp:43-49) but lost the host-side half: the async RX ring posts 32 KB URBs on all 11ac generations. No Android host ever ran the async ring before PixelPilot#104 shipped it.
Fix.
- 16 KB URB default on Jaguar1/2/3 (
DeviceConfig::Rx::urb_bytes, env DEVOURER_RX_URB_BYTES). Free on healthy hosts: device aggregates are capped ≤16 KB, so a 32 KB URB never filled past 16 KB anyway — each aggregate ends its URB via short packet.
- Jaguar2/3 halmac agg page-threshold
0x05 (20 KB) → 0x03 (≤12 KB) so an aggregate can never span two URBs and break the next_offset walk.
- Kestrel unchanged: the 8852C RXAGG LEN_TH (~20 KB) requires its 32 KB ring; not in PixelPilot's build scope.
Validation. ctest 36/36 green; desktop bench (regress.py 2×2 + goodput A/B 32K-vs-16K) pending; on-device MTK confirmation via PixelPilot#6 volunteers (both prior reporters offered to test).
Regression. OpenIPC/PixelPilot#6 is back: no video on MediaTek Android devices (Dimensity 810 report, 2026-07-19, PixelPilot master build). PixelPilot#104 bumped its devourer submodule from
bbc7385to73f1cb4.History. On some MediaTek Android xhci/usbfs stacks (Dimensity 810, Helio G99, MT6765) a bulk-IN read larger than 16 KB never completes —
LIBUSB_ERROR_TIMEOUTforever, zero RX with a green init. @floppyhammer's #19 (bbc7385) fixed this with two halves:rxagg_usb_size/timeout: USB30x7/0x1a → 0x3/0x01, USB20x5/0x20 → 0x1/0x01)infinite_readbuffer 65000 → 16 KB)What regressed. The RX rewrites (#158/#164/#168) and the #213 transport split (40e3a2a, which deleted
RtlUsbAdapter.cpp) kept the aggregation half (RtlAdapter.cpp:43-49) but lost the host-side half: the async RX ring posts 32 KB URBs on all 11ac generations. No Android host ever ran the async ring before PixelPilot#104 shipped it.Fix.
DeviceConfig::Rx::urb_bytes, envDEVOURER_RX_URB_BYTES). Free on healthy hosts: device aggregates are capped ≤16 KB, so a 32 KB URB never filled past 16 KB anyway — each aggregate ends its URB via short packet.0x05(20 KB) →0x03(≤12 KB) so an aggregate can never span two URBs and break thenext_offsetwalk.Validation. ctest 36/36 green; desktop bench (regress.py 2×2 + goodput A/B 32K-vs-16K) pending; on-device MTK confirmation via PixelPilot#6 volunteers (both prior reporters offered to test).