Repository navigation
Description
MSC host gaps found while reviewing #3968 and #4009. All of them already exist on master, and neither PR makes them worse. They were found by reading the code and have not been reproduced on hardware.
1. No BOT reset recovery. tuh_msc_reset() is #if 0 (src/class/msc/msc_host.c:296). If a stage transfer fails to submit, msch_xfer_cb() hits a TU_ASSERT and the command never completes. #4009 fixes that: it completes the command with a synthesized PHASE_ERROR CSW, and after that tuh_msc_scsi_command() and tuh_msc_ready() refuse the interface until the device re-enumerates. Refusing is required: without it, the next CBW reaches a device that is still mid-transfer, and on a TinyUSB device a failed WRITE10 then receives that CBW as data. The missing piece is Bulk-Only Mass Storage Reset plus Clear Feature HALT on both bulk endpoints (BOT 1.0 §5.3.4), which would let the interface recover without re-enumerating.
2. msc_file_explorer hangs when a submit fails. examples/host/msc_file_explorer/src/msc_app.c:225-226, 242-243, 393-394 set _disk_busy and then ignore a false return from tuh_msc_read10/tuh_msc_write10. No completion ever arrives, so disk_wait (line 193) spins forever. The freertos variant already handles this (examples/host/msc_file_explorer_freertos/src/msc_app.c:455-458: clear _disk_busy and report the error). A non-PASSED CSW could also map to RES_ERROR.
3. A failed enumeration step never finishes set-config. In msc_host.c, the config_*_complete chain (lines 488-535) returns early through TU_ASSERT when a Request Sense or Read Capacity CSW is not PASSED (lines 513, 521) or when a re-issue fails. The TUR return in config_get_maxlun_complete is also ignored. On all of these paths usbh_driver_set_config_complete() never runs, and usbh keeps its single enumeration slot until the device is removed. It needs one explicit abort path for every failure.
4. A CBW that completes with an error hangs the command. This is point 1's sibling: the CBW was submitted, but its transfer completes with an error (a STALL, say) or a short length. msch_xfer_cb() checks that with TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)) in MSC_STAGE_CMD (master src/class/msc/msc_host.c:337) and returns without completing the command, so the caller waits forever. #4009's completion and fencing cover only a failed submit. The recovery is the same as point 1's BOT reset.
5. The TUR / Request Sense retry during enumeration has no bound. config_test_unit_ready_complete() answers every failed Test Unit Ready with Request Sense, and config_request_sense_complete() issues TUR again (master msc_host.c:471-499, // TODO limit number of retries). A device that never becomes ready loops forever: usbh_driver_set_config_complete() never runs, and usbh keeps its enumeration slot, as in point 3. A bare retry count would also give up on slow devices that work today, so the bound should be time-based, or a count with a delay between tries, and then end the configuration unmounted.
Deferred from #3968, which is limited to 16-bit transfer-length wraps, and from #4009, which is limited to stage submit failures.
Activity