@@ -62,6 +62,7 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2];
6262typedef struct {
6363 // EP0 transfers are limited to 1 packet - larger sizes has to be split
6464 uint16_t ep0_pending [2 ]; // Index determines direction as tusb_dir_t type
65+ bool ep0_out_zlp_armed ; // EP0 OUT ZLP transfer is armed and waiting for completion
6566 uint16_t dfifo_top ; // top free location in DFIFO in words
6667
6768 // Number of IN endpoints active
@@ -665,6 +666,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
665666 // EP0 can only handle one packet
666667 if (epnum == 0 ) {
667668 _dcd_data .ep0_pending [dir ] = total_bytes ;
669+ if (dir == TUSB_DIR_OUT ) {
670+ _dcd_data .ep0_out_zlp_armed = (total_bytes == 0 );
671+ }
668672 }
669673
670674 // Schedule packets to be sent within interrupt
@@ -744,6 +748,9 @@ static void handle_bus_reset(uint8_t rhport) {
744748
745749 tu_memclr (xfer_status , sizeof (xfer_status ));
746750
751+ _dcd_data .ep0_pending [TUSB_DIR_OUT ] = 0 ;
752+ _dcd_data .ep0_pending [TUSB_DIR_IN ] = 0 ;
753+ _dcd_data .ep0_out_zlp_armed = false;
747754 _dcd_data .sof_en = false;
748755 _dcd_data .allocated_epin_count = 0 ;
749756
@@ -949,12 +956,16 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe
949956 xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , TUSB_DIR_OUT );
950957 const bool ep0_status_complete_before_setup = (epnum == 0 ) && doepint_bm .setup_phase_done &&
951958 doepint_bm .xfer_complete &&
959+ _dcd_data .ep0_out_zlp_armed &&
952960 (_dcd_data .ep0_pending [TUSB_DIR_OUT ] == 0 ) &&
953961 (xfer -> total_len == 0 );
954962
955963 if (doepint_bm .setup_phase_done ) {
956964 if (ep0_status_complete_before_setup ) {
965+ _dcd_data .ep0_out_zlp_armed = false;
957966 dcd_event_xfer_complete (rhport , epnum , 0 , XFER_RESULT_SUCCESS , true);
967+ } else if (epnum == 0 ) {
968+ _dcd_data .ep0_out_zlp_armed = false;
958969 }
959970
960971 // Cleanup previous pending EP0 IN transfer if any
@@ -976,6 +987,9 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe
976987 // EP0 can only handle one packet, Schedule another packet to be received.
977988 edpt_schedule_packets (rhport , epnum , TUSB_DIR_OUT );
978989 } else {
990+ if (epnum == 0 ) {
991+ _dcd_data .ep0_out_zlp_armed = false;
992+ }
979993 dcd_event_xfer_complete (rhport , epnum , xfer -> total_len , XFER_RESULT_SUCCESS , true);
980994 }
981995 }
@@ -1017,12 +1031,16 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
10171031 xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , TUSB_DIR_OUT );
10181032 const bool ep0_status_complete_before_setup = (epnum == 0 ) && doepint_bm .setup_phase_done &&
10191033 doepint_bm .xfer_complete &&
1034+ _dcd_data .ep0_out_zlp_armed &&
10201035 (_dcd_data .ep0_pending [TUSB_DIR_OUT ] == 0 ) &&
10211036 (xfer -> total_len == 0 );
10221037
10231038 if (doepint_bm .setup_phase_done ) {
10241039 if (ep0_status_complete_before_setup ) {
1040+ _dcd_data .ep0_out_zlp_armed = false;
10251041 dcd_event_xfer_complete (rhport , epnum , 0 , XFER_RESULT_SUCCESS , true);
1042+ } else if (epnum == 0 ) {
1043+ _dcd_data .ep0_out_zlp_armed = false;
10261044 }
10271045
10281046 // Cleanup previous pending EP0 IN transfer if any
@@ -1058,6 +1076,9 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
10581076 dma_setup_prepare (rhport );
10591077 }
10601078
1079+ if (epnum == 0 ) {
1080+ _dcd_data .ep0_out_zlp_armed = false;
1081+ }
10611082 dcd_dcache_invalidate (xfer -> buffer , xfer -> total_len );
10621083 dcd_event_xfer_complete (rhport , epnum , xfer -> total_len , XFER_RESULT_SUCCESS , true);
10631084 }
0 commit comments