ricardgb commented on issue #19435:
URL: https://github.com/apache/nuttx/issues/19435#issuecomment-4984633662
## Bug 6 — GET STATUS is never answered by the rp2040/rp23xx DCD (found
after the bug-5 fix still didn't satisfy macOS)
Status update on the macOS saga: the stall-queue fix (bug 5, previous
comment) is real and
held up, but the macOS retest still failed — and the failure log isolated
the remaining
piece, which turned out to be the "1 s EP0 timeout" loose end I flagged.
### Symptom
With bug 5 fixed, the macOS probe reaches the (BOT-legal) bulk-IN halt for
the failed
MODE SENSE(6) page-0 command. ~50 ms after the halt, macOS's storage stack
issues
**GetPipeStatus = GET STATUS (recipient: endpoint) on the halted pipe**
before deciding on
recovery. That control transfer times out after 1 s, macOS resets the
device, and the
familiar spiral follows (fConsecutiveResetCount 1→3, SET_ADDRESS failures,
port disabled
for "persistent enumeration failures").
### Root cause (deterministic, code-level)
In both `arch/arm/src/rp2040/rp2040_usbdev.c` and
`arch/arm/src/rp23xx/rp23xx_usbdev.c`,
the `USB_REQ_GETSTATUS` case in `*_ep0setup()` **validates the request but
never queues
the two-byte status response** — for all three recipients (device,
interface, endpoint).
EP0 therefore NAKs the host's data-IN stage forever and every GET STATUS
times out. Linux
does not issue GET STATUS in normal enumeration or usb-storage operation, so
the bug is
invisible there; any host (or userspace tool, e.g. `lsusb -v` device-status
query) that
sends GET STATUS hangs for its control timeout.
Silicon proof (raw usbfs, RP2350, firmware with bugs 1-3+5 fixed but not
this one):
```
GET_STATUS device: errno=110(ETIMEDOUT) (1.54s)
GET_STATUS interface 4: errno=110(ETIMEDOUT) (1.54s)
GET_STATUS ep 0x87: errno=110(ETIMEDOUT) (1.54s)
GET_STATUS ep 0x08: errno=110(ETIMEDOUT) (1.54s)
GET_STATUS ep0: errno=110(ETIMEDOUT) (1.54s)
```
### Fix
Build and transmit the 2-byte status in the GETSTATUS handler: endpoint
recipient reports
the halt bit from the endpoint state, device recipient reports self-powered,
interface
reports zeros; the response is sent with `*_epwrite(ep0, response, 2)` and
the status
stage (host's zero-length OUT) is armed by `*_handle_zlp()` exactly as for
class-dispatched IN transfers. Applied to both chips.
### Validation (same board, fixed firmware)
- All five GET STATUS variants above now answer `2B 0000` in <1 ms; on a
halted endpoint
the response is `0100` (halt bit) and returns to `0000` after CLEAR
FEATURE.
- **Post-stall delay sweep** replicating macOS's recovery order — data-IN
stall →
wait {0, 30, 50, 80, 150, 500, 1000} ms → GET STATUS(ep) (assert halted) →
CLEAR
FEATURE → GET STATUS (assert cleared) → CSW read (assert
signature/tag/status/residue):
**all delays pass**. (The 50 ms point is macOS's observed timing; the
earlier bug-5
validation used only a 1 s delay, which is why this hole survived it.)
- Full macOS-equivalent BOT probe replay ×5 cycles: zero failures.
- Regressions: failed-command CSW still delivered (bug-5 fix intact), MODE
SENSE 0x3F /
INQUIRY / REQUEST SENSE / READ CAPACITY good, GET MAX LUN + Bulk-Only
reset 10/10, FAT
drive mounts + full-reads, CDC-NCM and CDC-ACM functional, warm reboots
re-enumerate.
macOS mount retest of this build is pending and I will report the result.
Given that the
macOS failure log's three distinct signatures (LUN garbage, lost CSW, EP0
timeout) are now
each root-caused to a specific driver defect with silicon-validated fixes,
this should be
the last layer — but that has been said before in this saga, so: pending
confirmation.
For maintainers keeping score, the full stack found behind "macOS never
mounts a NuttX
composite MSC" is now: (1) wIndex vs ifnobase in usbmsc_setup
(composite-only), (2)
usbmsc_deferredresponse compiled out in composite mode, (3) gratuitous
bulk-IN stall on
short-data Hi>Di, (5) IN requests submitted while an endpoint is halted are
dropped by the
DCD (CSW loss; ARCH_USBDEV_STALLQUEUE now implemented), (6) GET STATUS never
answered by
the DCD. ((4) is the still-open lockup, no longer reachable via this path.)
## Disclosure
As above: this investigation and the fixes were performed by an AI agent
(Claude Code),
operated and directed by the submitter, and reviewed by the submitter before
posting.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]