@@ -53,9 +53,16 @@ impl Buffers {
5353
5454unsafe impl Sync for Buffers { }
5555
56+ #[ derive( Copy , Clone ) ]
57+ enum TransferState {
58+ NoTransfer ,
59+ Started ( u16 ) ,
60+ }
61+
5662#[ derive( Copy , Clone ) ]
5763struct EP0State {
5864 direction : UsbDirection ,
65+ in_transfer_state : TransferState ,
5966}
6067
6168/// USB device implementation.
@@ -101,6 +108,7 @@ impl<'c> Usbd<'c> {
101108 iso_out_used : false ,
102109 ep0_state : Mutex :: new ( Cell :: new ( EP0State {
103110 direction : UsbDirection :: Out ,
111+ in_transfer_state : TransferState :: NoTransfer ,
104112 } ) ) ,
105113 _clocks : & ( ) ,
106114 } )
@@ -478,6 +486,13 @@ impl UsbBus for Usbd<'_> {
478486 w. ep0datadone_ep0status ( ) . clear_bit ( )
479487 }
480488 } ) ;
489+
490+ // Hack: send status stage if the IN transfer is not acknowledged after a few frames
491+ let frame_counter = regs. framecntr . read ( ) . framecntr ( ) . bits ( ) ;
492+ let ep0_state = self . ep0_state . borrow ( cs) ;
493+ let mut state = ep0_state. get ( ) ;
494+ state. in_transfer_state = TransferState :: Started ( frame_counter) ;
495+ ep0_state. set ( state) ;
481496 }
482497
483498 // Clear ENDEPIN[i] flag
@@ -647,6 +662,25 @@ impl UsbBus for Usbd<'_> {
647662 }
648663 }
649664
665+ if regs. events_sof . read ( ) . events_sof ( ) . bit_is_set ( ) {
666+ regs. events_sof . reset ( ) ;
667+
668+ // Check if we have a timeout for EP0 IN transfer
669+ let ep0_state = self . ep0_state . borrow ( cs) ;
670+ let mut state = ep0_state. get ( ) ;
671+ if let TransferState :: Started ( counter) = state. in_transfer_state {
672+ let frame_counter = regs. framecntr . read ( ) . framecntr ( ) . bits ( ) ;
673+ if frame_counter. wrapping_sub ( counter) >= 5 {
674+ // Send a status stage to ACK a pending OUT transfer
675+ regs. tasks_ep0status . write ( |w| w. tasks_ep0status ( ) . set_bit ( ) ) ;
676+
677+ // reset the state
678+ state. in_transfer_state = TransferState :: NoTransfer ;
679+ ep0_state. set ( state) ;
680+ }
681+ }
682+ }
683+
650684 // Check for any finished transmissions.
651685 let mut in_complete = 0 ;
652686 let mut out_complete = 0 ;
@@ -657,6 +691,12 @@ impl UsbBus for Usbd<'_> {
657691 regs. events_ep0datadone . reset ( ) ;
658692
659693 in_complete |= 1 ;
694+
695+ // Reset a timeout for the IN transfer
696+ let ep0_state = self . ep0_state . borrow ( cs) ;
697+ let mut state = ep0_state. get ( ) ;
698+ state. in_transfer_state = TransferState :: NoTransfer ;
699+ ep0_state. set ( state) ;
660700 } else {
661701 // Do not clear OUT events, since we have to continue reporting them until the
662702 // buffer is read.
0 commit comments