/** * This function starts the Zero-Length Packet for the IN status phase * of a 2 stage control transfer. */ static void do_setup_in_status_phase( pcd_struct_t *_pcd) { dwc_ep_t *ep0 = &g_dwc_eps[0]; if (_pcd->ep0state == EP0_STALL){ return; } _pcd->ep0state = EP0_STATUS; DBG( "EP0 IN ZLP\n"); ep0->xfer_len = 0; ep0->xfer_count = 0; ep0->is_in = 1; dwc_otg_ep_start_transfer( ep0 ); /* Prepare for more SETUP Packets */ ep0_out_start(); }
/** * This interrupt occurs when a USB Reset is detected. When the USB * Reset Interrupt occurs the device state is set to DEFAULT and the * EP0 state is set to IDLE. * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) * -# Unmask the following interrupt bits * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint) * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint) * - DOEPMSK.SETUP = 1 * - DOEPMSK.XferCompl = 1 * - DIEPMSK.XferCompl = 1 * - DIEPMSK.TimeOut = 1 * -# Program the following fields in the endpoint specific registers * for Control OUT EP 0, in order to receive a setup packet * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back * setup packets) * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back * to back setup packets) * - In DMA mode, DOEPDMA0 Register with a memory address to * store any setup packets received * At this point, all the required initialization, except for enabling * the control 0 OUT endpoint is done, for receiving SETUP packets. */ int32_t dwc_otg_pcd_handle_usb_reset_intr(void) { depctl_data_t doepctl = { 0}; daint_data_t daintmsk = { 0}; doepmsk_data_t doepmsk = { 0}; diepmsk_data_t diepmsk = { 0}; dcfg_data_t dcfg = { 0 }; depctl_data_t diepctl = { 0}; depctl_data_t diepctl_rd = { 0}; grstctl_t resetctl = { 0 }; dctl_data_t dctl = { 0 }; int i = 0; gintsts_data_t gintsts; DBG("\nUSB RESET\n"); /* Clear the Remote Wakeup Signalling */ dctl.b.rmtwkupsig = 1; dwc_modify_reg32( DWC_REG_DCTL,dctl.d32, 0 ); /* Disable all active IN EPs */ diepctl.b.epdis = 1; diepctl.b.snak = 1; for (i=0; i < NUM_EP; i++) { diepctl_rd.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(i)); if (diepctl_rd.b.epena) { dwc_write_reg32(DWC_REG_IN_EP_REG(i),diepctl.d32 ); } } /* Set NAK for all OUT EPs */ doepctl.b.snak = 1; for (i=0; i < NUM_EP; i++) { dwc_write_reg32(DWC_REG_OUT_EP_REG(i), doepctl.d32 ); } /* Flush the NP Tx FIFO */ dwc_otg_flush_tx_fifo( 0 ); /* Flush the Learning Queue */ resetctl.b.intknqflsh = 1; dwc_write_reg32( DWC_REG_GRSTCTL, resetctl.d32); daintmsk.b.inep0 = 1; daintmsk.b.outep0 = 1; dwc_write_reg32( DWC_REG_DAINTMSK, daintmsk.d32 ); doepmsk.b.setup = 1; doepmsk.b.xfercompl = 1; doepmsk.b.ahberr = 1; doepmsk.b.epdisabled = 1; dwc_write_reg32( DWC_REG_DOEPMSK, doepmsk.d32 ); diepmsk.b.xfercompl = 1; diepmsk.b.timeout = 1; diepmsk.b.epdisabled = 1; diepmsk.b.ahberr = 1; dwc_write_reg32( DWC_REG_DIEPMSK, diepmsk.d32 ); /* Reset Device Address */ dcfg.d32 = dwc_read_reg32( DWC_REG_DCFG); dcfg.b.devaddr = 0; dwc_write_reg32( DWC_REG_DCFG, dcfg.d32); /* setup EP0 to receive SETUP packets */ ep0_out_start(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.usbreset = 1; dwc_write_reg32 ( DWC_REG_GINTSTS, gintsts.d32); flush_cpu_cache(); return 1; }