void USBDEP_Ep0Handler( USBD_Device_TypeDef *device ) { int status; USBD_Ep_TypeDef *ep; static uint32_t xferred; static USB_XferCompleteCb_TypeDef callback; #ifdef __MBED__ (void)xferred; (void)status; ep = &device->ep[ 0 ]; if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) ) { ep->state = D_EP_IDLE; if ( ep->xferCompleteCb ) { callback = ep->xferCompleteCb; ep->xferCompleteCb = NULL; callback( USB_STATUS_OK, ep->xferred, ep->remaining ); } USBDHAL_StartEp0Setup( dev ); } else { device->callbacks->setupCmd(device->setup); } #else ep = &device->ep[ 0 ]; switch ( ep->state ) { case D_EP_IDLE: ep->zlp = 0; ep->remaining = 0; callback = NULL; status = USBDCH9_SetupCmd( device ); if ( status == USB_STATUS_REQ_ERR ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP packet*/ } else /* ( Status == USB_STATUS_OK ) */ { if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) ) { callback = ep->xferCompleteCb; } if ( ep->state != D_EP_RECEIVING ) { if ( ep->remaining ) { /* Data will be sent to host, check if a ZLP must be appended */ if ( ( ep->remaining < device->setup->wLength ) && ( ep->remaining % ep->packetSize == 0 ) ) { ep->zlp = 1; } } else { /* No data stage, a ZLP may have been sent. If not, send one */ xferred = 0; if ( ep->zlp == 0 ) { ep->state = D_EP_IDLE; USBD_Write( 0, NULL, 0, NULL ); /* ACK to host */ ep->state = D_EP0_IN_STATUS; } } } } break; case D_EP_RECEIVING: if ( ep->remaining ) { ep->in = false; USBD_ReArmEp0( ep ); } else { status = USB_STATUS_OK; if ( callback != NULL ) { status = callback( USB_STATUS_OK, ep->xferred, 0 ); callback = NULL; } if ( status != USB_STATUS_OK ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP pkt. */ ep->state = D_EP_IDLE; } else { USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP packet*/ ep->state = D_EP_IDLE; /* USBD_Write() sets state back */ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); ep->state = D_EP0_IN_STATUS; } } break; case D_EP_TRANSMITTING: if ( ep->remaining ) { ep->in = true; USBD_ReArmEp0( ep ); } else { if ( ep->zlp == 1 ) { xferred = ep->xferred; ep->state = D_EP_IDLE; /* USBD_Write() sets state back */ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP */ ep->zlp = 2; } else { if ( ep->zlp == 0 ) { xferred = ep->xferred; } ep->state = D_EP_IDLE; USBD_Read( 0, NULL, 0, NULL ); /* Get ZLP packet (ACK) from host */ ep->state = D_EP0_OUT_STATUS; } } break; case D_EP0_IN_STATUS: if ( ( USB->DOEP0CTL & USB_DOEP0CTL_EPENA ) == 0 ) { /* Prepare for more SETUP Packets */ USBDHAL_StartEp0Setup( dev ); } if ( callback != NULL ) { callback( USB_STATUS_OK, xferred, 0 ); } ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ break; case D_EP0_OUT_STATUS: USBDHAL_StartEp0Setup( dev ); /* Prepare for more SETUP Packets */ if ( callback != NULL ) { callback( USB_STATUS_OK, xferred, 0 ); } ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ break; } #endif /* __MBED__ */ }
void USBDEP_Ep0Handler( USBD_Device_TypeDef *device ) { int status; USBD_Ep_TypeDef *ep; static bool statusIn; static uint32_t xferred; static USB_XferCompleteCb_TypeDef callback; ep = &device->ep[ 0 ]; #ifdef __MBED__ (void)xferred; (void)statusIn; (void)status; USB_PRINTF("USBDEP: ep0 %s, rem %ld, z %d\n", epStatusStr[ep->state], ep->remaining, ep->zlp); if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) ) { ep->state = D_EP_IDLE; if ( ep->xferCompleteCb ) { callback = ep->xferCompleteCb; ep->xferCompleteCb = NULL; callback( USB_STATUS_OK, ep->xferred, ep->remaining ); } USBDHAL_ReenableEp0Setup(device); } else { device->callbacks->setupCmd(device->setup); } #else /* not __MBED__ */ switch ( ep->state ) { case D_EP_IDLE: ep->remaining = 0; ep->zlp = 0; callback = NULL; statusIn = false; status = USBDCH9_SetupCmd( device ); if ( status == USB_STATUS_REQ_ERR ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP packet*/ } else /* ( Status == USB_STATUS_OK ) */ { if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) ) { callback = ep->xferCompleteCb; } if ( ep->state != D_EP_RECEIVING ) { if ( ep->remaining ) { /* Data will be sent to host, check if a ZLP must be appended */ if ( ( ep->remaining < device->setup->wLength ) && ( ep->remaining % ep->packetSize == 0 ) ) { ep->zlp = 1; } } else { /* Prepare for next SETUP packet*/ USBDHAL_ReenableEp0Setup( device ); /* No data stage, a ZLP may have been sent. If not, send one */ xferred = 0; if ( ep->zlp == 0 ) { USBD_Write( 0, NULL, 0, NULL ); /* ACK to host */ ep->state = D_EP0_IN_STATUS; } else { ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ } } } } break; case D_EP_RECEIVING: if ( ep->remaining ) { /* There is more data to receive */ USBD_ReArmEp0( ep ); } else { status = USB_STATUS_OK; if ( callback != NULL ) { status = callback( USB_STATUS_OK, ep->xferred, 0 ); callback = NULL; } if ( status != USB_STATUS_OK ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP pkt. */ ep->state = D_EP_IDLE; } else /* Everything OK, send a ZLP (ACK) to host */ { USBDHAL_ReenableEp0Setup( device );/* Prepare for next SETUP packet*/ ep->state = D_EP_IDLE; /* USBD_Write() sets state back*/ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); ep->state = D_EP0_IN_STATUS; } } break; case D_EP_TRANSMITTING: if ( ep->remaining ) { /* There is more data to transmit */ USBD_ReArmEp0( ep ); } else { /* All data transferred, is a ZLP packet needed ? */ if ( ep->zlp == 1 ) { xferred = ep->xferred; ep->state = D_EP_IDLE; /* USBD_Write() sets state back */ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP */ ep->zlp = 2; } else { if ( ep->zlp == 0 ) { xferred = ep->xferred; } ep->state = D_EP_IDLE; USBD_Read( 0, NULL, 0, NULL ); /* Get ZLP packet (ACK) from host */ statusIn = true; ep->state = D_EP0_OUT_STATUS; } } break; case D_EP0_IN_STATUS: case D_EP0_OUT_STATUS: if ( statusIn ) { USBDHAL_ReenableEp0Setup( device ); } if ( callback != NULL ) { callback( USB_STATUS_OK, xferred, 0 ); } ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ break; default: EFM_ASSERT( false ); break; } #endif /* __MBED__ */ }
/***************************************************************************//** * @brief Handles Endpoint 0 transfer interrupt ******************************************************************************/ static void handleUsbEp0Int(void) { USB_SetIndex(0); if (USB_Ep0SentStall() || USB_GetSetupEnd()) { USB_Ep0ClearSentStall(); USB_ServicedSetupEnd(); myUsbDevice.ep0.state = D_EP_IDLE; myUsbDevice.ep0.misc.c = 0; } if (USB_Ep0OutPacketReady()) { if (myUsbDevice.ep0.misc.bits.waitForRead == true) { myUsbDevice.ep0.misc.bits.outPacketPending = true; } else if (myUsbDevice.ep0.state == D_EP_IDLE) { myUsbDevice.ep0String.c = USB_STRING_DESCRIPTOR_UTF16LE; USB_ReadFIFOSetup(); // Vendor unique, Class or Standard setup commands override? #if SLAB_USB_SETUP_CMD_CB if (USBD_SetupCmdCb(&myUsbDevice.setup) == USB_STATUS_REQ_UNHANDLED) { #endif if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD) { USBDCH9_SetupCmd(); } else { SendEp0Stall(); } #if SLAB_USB_SETUP_CMD_CB } else { // If in-packet but callback didn't setup a USBD_Read and we are expecting a data byte then // we need to wait for the read to be setup and nack packets till USBD_Read is called. if ((myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_OUT) && (myUsbDevice.ep0.state != D_EP_RECEIVING) && (myUsbDevice.setup.wLength) ) { myUsbDevice.ep0.misc.bits.waitForRead = true; } } #endif } else if (myUsbDevice.ep0.state == D_EP_RECEIVING) { handleUsbEp0Rx(); } else { myUsbDevice.ep0.misc.bits.outPacketPending = true; } } if ((myUsbDevice.ep0.state == D_EP_TRANSMITTING) && (USB_Ep0InPacketReady() == 0)) { handleUsbEp0Tx(); } }