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]

Reply via email to