@@ -308,18 +308,20 @@ def _recover_idle(self) -> None:
308308 else :
309309 break
310310
311- def _wait_while_busy (self ) -> dict :
311+ def _wait_while_busy (self , timeout_s : float = 30.0 ) -> dict :
312312 busy = {
313313 self .STATE_DFU_DNLOAD_SYNC ,
314314 self .STATE_DFU_DNLOAD_BUSY ,
315315 self .STATE_DFU_MANIFEST_SYNC ,
316316 self .STATE_DFU_MANIFEST ,
317317 }
318- while True :
318+ deadline = time .monotonic () + timeout_s
319+ while time .monotonic () < deadline :
319320 st = self .get_status ()
320321 if st ["state" ] not in busy :
321322 return st
322323 time .sleep (max (st ["poll_timeout_ms" ] / 1000.0 , 0.005 ))
324+ raise TimeoutError (f"USB DFU device stuck in busy state after { timeout_s :.0f} s" )
323325
324326 def _dnload (self , block_num : int , payload : bytes ) -> dict :
325327 self ._recover_idle ()
@@ -328,8 +330,10 @@ def _dnload(self, block_num: int, payload: bytes) -> dict:
328330 self .DFU_DNLOAD , block_num , bytes (payload ) if payload else b""
329331 )
330332 except _usb_core .USBError as e :
331- if "timeout" not in str (e ).lower ():
333+ # errno 110 = ETIMEDOUT (libusb); swallow only genuine transfer timeouts
334+ if e .errno != 110 :
332335 raise
336+ logger .debug ("_dnload timeout on block %d, polling status anyway: %s" , block_num , e )
333337 return self ._wait_while_busy ()
334338
335339 def _set_address (self , address : int ) -> None :
@@ -456,8 +460,14 @@ def _exchange(self, payload: bytes, read_len: int,
456460 f"I2C passthrough exchange failed (addr=0x{ self ._addr :02X} , "
457461 f"want_rx={ read_len } )"
458462 )
459- return bytes (r .data [:read_len ]) if (r .data and len (r .data ) >= read_len ) \
460- else bytes (read_len )
463+ actual = len (r .data ) if r .data else 0
464+ if actual < read_len :
465+ raise RuntimeError (
466+ f"I2C passthrough exchange returned too few bytes: "
467+ f"expected { read_len } , got { actual } "
468+ f"(addr=0x{ self ._addr :02X} )"
469+ )
470+ return bytes (r .data [:read_len ])
461471
462472 # --- DFU protocol commands ---
463473
0 commit comments