ricardgb commented on issue #19435:
URL: https://github.com/apache/nuttx/issues/19435#issuecomment-4983796003
## Update: fix confirmed on macOS + two more composite-USBMSC bugs found
beneath it
**The `devinfo.ifnobase` fix above is confirmed working on macOS** — the
stalled GET MAX
LUN (and the "Max LUNs reported as 28" garbage read) is gone from the kernel
log.
However, the disk still does not mount on macOS, and peeling that onion
exposed **two more
generic composite-mode bugs in `drivers/usbdev/usbmsc*`** (plus an arch
crash under
investigation). Posting them here since they are all in the same probe path
and were masked
by this issue's bug; happy to split into separate issues if preferred.
### Bug 2: `usbmsc_deferredresponse()` is a compile-time no-op in composite
mode
The entire body of `usbmsc_deferredresponse()` (drivers/usbdev/usbmsc.c) is
wrapped in
`#ifndef CONFIG_USBMSC_COMPOSITE`. The deferred EP0 status-stage responses
for
**Bulk-Only Mass Storage Reset** and SET_INTERFACE are made through this
function by the
SCSI worker thread — so in composite mode **the MSRESET status stage is
never sent** and
the host's BOT reset recovery **times out**. macOS log:
```
endpoint 0x87: status 0xe0005000 (pipe stalled)
endpoint 0x00: status 0xe00002d6 (timeout) <- MSRESET never answered
USB device ... BOT reset completed with kIOReturnTimeout
IOUSBMassStorageDriver: ... usb reset ... <- full device reset,
probe loop, gives up
```
(Before the ifnobase fix this path was unreachable — MSRESET was stalled by
the
wrong-interface check — which is presumably why it was never seen.)
Fix: compile the body in composite mode as well. `EP_SUBMIT(dev->ep0,
ctrlreq)` is correct
there for these class requests (equivalent to `composite_ep0submit()` for
anything but
SETCONFIGURATION), and additionally the worker must NOT send the deferred
response for
`USBMSC_EVENT_CFGCHANGE` in composite mode — the composite driver already
answers
SETCONFIGURATION itself (that is exactly what the `composite_ep0submit()`
filter exists
for), and a duplicate ZLP would corrupt EP0.
### Bug 3: gratuitous bulk-IN STALL when the host allocation exceeds the
response (Hi > Di)
For any Data-In command whose response is shorter than the host's requested
transfer
length, `usbmsc_cmdfinishstate()` (drivers/usbdev/usbmsc_scsi.c) submits the
short
response and then **also stalls the bulk-IN endpoint** because `residue >
0`. The stall is
permitted by BOT 6.7.2, but it is unnecessary — the short packet has already
terminated
the host's data phase — and it is harmful in practice: macOS answers any
bulk-IN halt
during device probing with the full BOT-reset sequence (which then ran into
bug 2 above).
Linux is only unaffected because its SCSI probe happens not to issue Hi > Di
transfers;
it can be reproduced on Linux trivially:
```
$ sudo sg_raw -r 192 /dev/sg0 1a 00 3f 00 c0 00 # MODE SENSE(6), alloc
0xC0
# usbmon: 16-byte short data-in, then CSW read STALLed (-EPIPE),
# clear-halt, CSW retry succeeds with dCSWDataResidue=0xB0
```
`CONFIG_USBMSC_NOT_STALL_BULKEP` exists as a config-level workaround for
exactly this
area (it suppresses the stall but also fakes the MODE SENSE length and
zeroes the
residue, i.e. it lies in the CSW).
Fix: in `usbmsc_cmdfinishstate()`, only stall when the data phase was
**not** terminated —
i.e. when no response data was submitted at all (the request is submitted
with
`USBDEV_REQFLAGS_NULLPKT`, so a submitted response always ends in a short
packet or ZLP).
When the short response was sent, proceed directly to the CSW and report the
residue in
`dCSWDataResidue`, which is the BOT-correct behavior. `NOT_STALL_BULKEP`
then becomes
unnecessary for correctness.
### Under investigation: the BOT reset crashes the firmware (RP2350)
With the two bugs above still in place, SWD inspection of the wedged device
(Pico 2 W,
plugged into the macOS host, after the probe loop gave up) found core 0 in
ARM **lockup**
(pc=0xEFFFFFFE, CFSR=0x00080001 = instruction-access violation escalated to
HardFault,
HFSR=FORCED), with the last received SETUP packet in DPSRAM being `21 ff 00
00 04 00 00 00`
(Bulk-Only Mass Storage Reset). I.e. the repeated MSRESET/reset recovery
sequence does not
just time out — it eventually takes a wild jump in the USB interrupt path
and kills the
firmware until power-cycle (this is why the macOS log ends with SET_ADDRESS
failures and
"disabling port"). Root-cause in progress with a debug probe; will report
separately
(likely an rp23xx/rp2040 arch issue or a request-cancellation race, related
to this
issue's driver family).
### Status
- Fixes for bugs 2 and 3 are implemented and build clean; silicon validation
(Linux
usbmon + macOS mount test) is in progress and I will confirm results here.
## 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]