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]

Reply via email to