Skip to content

Commit cd4f51c

Browse files
committed
usbd: Theoretically handle resets and bad CBWs better in msc
1 parent 83364c0 commit cd4f51c

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

micropython/usbd/msc.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ def from_binary(self, binary):
8585
) = ustruct.unpack("<LLLBBB16s", binary)
8686

8787

88+
class BadCbw(RuntimeError):
89+
pass
90+
91+
8892
class CSW:
8993
"""Command Status Wrapper - handles status messages from the device to the host"""
9094

@@ -194,7 +198,8 @@ def try_to_prepare_cbw(self, args=None):
194198
"""
195199
try:
196200
self.prepare_cbw()
197-
except KeyError:
201+
except (KeyError, RuntimeError):
202+
# RuntimeError is raised when the device isn't open yet, so let's just retry
198203
self.timer.init(mode=Timer.ONE_SHOT, period=2000, callback=self.try_to_prepare_cbw)
199204

200205
def handle_interface_control_xfer(self, stage, request):
@@ -221,13 +226,13 @@ def handle_interface_control_xfer(self, stage, request):
221226
return False
222227

223228
def reset(self):
224-
"""Theoretically reset, in reality just break things a bit at the moment"""
229+
"""Perform a Reset Revovery"""
225230
self.log("reset()")
226-
# This doesn't work properly at the moment, needs additional
227-
# functionality in the C side
228231
self.stage = type(self).MSC_STAGE_CMD
229232
self.transferred_length = 0
230233
self.storage_device.reset()
234+
self.set_ep_stall(self.ep_in, False)
235+
self.set_ep_stall(self.ep_out, False)
231236
self.prepare_cbw()
232237
return True
233238

@@ -296,7 +301,14 @@ def handle_cbw(self):
296301
self.csw.dCSWDataResidue = 0
297302
self.csw.bCSWStatus = CSW.STATUS_PASSED
298303

299-
status = int(self.validate_cbw())
304+
try:
305+
status = int(self.validate_cbw())
306+
except BadCbw as exc:
307+
self.log(str(exc))
308+
self.set_ep_stall(self.ep_in, True)
309+
self.set_ep_stall(self.ep_out, True)
310+
return False
311+
300312
if status != CSW.STATUS_PASSED:
301313
self.log(f"Didn't pass: {status}")
302314
self.prepare_for_csw(status=status)
@@ -388,22 +400,17 @@ def validate_cbw(self) -> bool:
388400
return CSW.STATUS_PHASE_ERROR
389401

390402
if len(self.rx_data) != 31:
391-
self.log("Wrong length")
392-
return CSW.STATUS_FAILED
403+
raise BadCbw("Invalid: Wrong CBW length")
393404

394405
if self.cbw.dCBWSignature != type(self).CBW_SIGNATURE:
395-
self.log("Wrong sig")
396-
self.log(str(self.cbw.dCBWSignature))
397-
return CSW.STATUS_FAILED
406+
raise BadCbw(f"Invalid: Wrong sig: {str(self.cbw.dCBWSignature)}")
398407

399408
# Meaningful checks (6.2.2)
400409
if self.cbw.bCBWLUN > 15 or not 0 < self.cbw.bCBWCBLength < 17:
401-
self.log("Wrong length")
402-
return CSW.STATUS_FAILED
410+
raise BadCbw("Not meaningful: Wrong length command or invalid LUN")
403411

404412
if self.cbw.bCBWLUN != self.lun:
405-
self.log("Wrong LUN")
406-
return CSW.STATUS_FAILED
413+
raise BadCbw("Not meaningful: Wrong LUN")
407414

408415
# Check if this is a valid SCSI command
409416
try:

0 commit comments

Comments
 (0)