/** Returns the filled Command Status Wrapper back to the host via the bulk data IN endpoint, waiting for the host to clear any * stalled data endpoints as needed. */ static void ReturnCommandStatus(void) { /* Select the Data Out endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); /* While data pipe is stalled, wait until the host issues a control request to clear the stall */ while (Endpoint_IsStalled()) { /* Check if the current command is being aborted by the host */ if (IsMassStoreReset) return; } /* Select the Data In endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); /* While data pipe is stalled, wait until the host issues a control request to clear the stall */ while (Endpoint_IsStalled()) { /* Check if the current command is being aborted by the host */ if (IsMassStoreReset) return; } /* Write the CSW to the endpoint */ Endpoint_Write_Stream_LE(&CommandStatus, sizeof(CommandStatus), StreamCallback_AbortOnMassStoreReset); /* Check if the current command is being aborted by the host */ if (IsMassStoreReset) return; /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); }
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); while (Endpoint_IsStalled()) { #if !defined(INTERRUPT_CONTROL_ENDPOINT) USB_USBTask(); #endif if (MSInterfaceInfo->State.IsMassStoreReset) return; } Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); while (Endpoint_IsStalled()) { #if !defined(INTERRUPT_CONTROL_ENDPOINT) USB_USBTask(); #endif if (MSInterfaceInfo->State.IsMassStoreReset) return; } CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset; if (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus, sizeof(MS_CommandStatusWrapper_t), StreamCallback_MS_Device_AbortOnMassStoreReset)) { return; } Endpoint_ClearIN(); }
uint8_t Endpoint_WaitUntilReady(void) { #if (USB_STREAM_TIMEOUT_MS < 0xFF) uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #else uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #endif for (;;) { if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN) { if (Endpoint_IsINReady()) return ENDPOINT_READYWAIT_NoError; } else { if (Endpoint_IsOUTReceived()) return ENDPOINT_READYWAIT_NoError; } if (USB_DeviceState == DEVICE_STATE_Unattached) return ENDPOINT_READYWAIT_DeviceDisconnected; else if (Endpoint_IsStalled()) return ENDPOINT_READYWAIT_EndpointStalled; if (USB_INT_HasOccurred(USB_INT_SOFI)) { USB_INT_Clear(USB_INT_SOFI); if (!(TimeoutMSRem--)) return ENDPOINT_READYWAIT_Timeout; } } }
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); while (Endpoint_IsStalled()) { #if !defined(INTERRUPT_CONTROL_ENDPOINT) USB_USBTask(); #endif if (MSInterfaceInfo->State.IsMassStoreReset) return; } Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); while (Endpoint_IsStalled()) { #if !defined(INTERRUPT_CONTROL_ENDPOINT) USB_USBTask(); #endif if (MSInterfaceInfo->State.IsMassStoreReset) return; } uint16_t BytesProcessed = 0; while (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus, sizeof(MS_CommandStatusWrapper_t), &BytesProcessed) == ENDPOINT_RWSTREAM_IncompleteTransfer) { #if !defined(INTERRUPT_CONTROL_ENDPOINT) USB_USBTask(); #endif if (MSInterfaceInfo->State.IsMassStoreReset) return; } Endpoint_ClearIN(); }
/** Returns the filled Command Status Wrapper back to the host via the bulk data IN endpoint, waiting for the host to clear any * stalled data endpoints as needed. */ static void ReturnCommandStatus(void) { uint16_t BytesTransferred; /* Select the Data Out endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPADDR); /* While data pipe is stalled, wait until the host issues a control request to clear the stall */ while (Endpoint_IsStalled()) { /* Check if the current command is being aborted by the host */ if (IsMassStoreReset) return; } /* Select the Data In endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPADDR); /* While data pipe is stalled, wait until the host issues a control request to clear the stall */ while (Endpoint_IsStalled()) { /* Check if the current command is being aborted by the host */ if (IsMassStoreReset) return; } /* Write the CSW to the endpoint */ BytesTransferred = 0; while (Endpoint_Write_Stream_LE(&CommandStatus, sizeof(CommandStatus), &BytesTransferred) == ENDPOINT_RWSTREAM_IncompleteTransfer) { /* Check if the current command is being aborted by the host */ if (IsMassStoreReset) return; } /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); }
uint8_t Endpoint_WaitUntilReady(void) { #if (USB_STREAM_TIMEOUT_MS < 0xFF) uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #else uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; #endif uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber(); for (;;) { if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN) { if (Endpoint_IsINReady()) return ENDPOINT_READYWAIT_NoError; } else { if (Endpoint_IsOUTReceived()) return ENDPOINT_READYWAIT_NoError; } uint8_t USB_DeviceState_LCL = USB_DeviceState; if (USB_DeviceState_LCL == DEVICE_STATE_Unattached) return ENDPOINT_READYWAIT_DeviceDisconnected; else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended) return ENDPOINT_READYWAIT_BusSuspended; else if (Endpoint_IsStalled()) return ENDPOINT_READYWAIT_EndpointStalled; uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return ENDPOINT_READYWAIT_Timeout; } } }
/* * The Linux and OSX call the configuration changed entry each time * a transaction is started (e.g., multiple runs of cbmctrl status). * We need to reset the endpoints before reconfiguring them, otherwise * we get a hang the second time through. * * We keep the original endpoint selected after returning. */ void USB_ResetConfig() { static uint8_t endpoints[] = { XUM_BULK_IN_ENDPOINT, XUM_BULK_OUT_ENDPOINT, 0, }; uint8_t lastEndpoint, *endp; lastEndpoint = Endpoint_GetCurrentEndpoint(); for (endp = endpoints; *endp != 0; endp++) { Endpoint_SelectEndpoint(*endp); Endpoint_ResetFIFO(*endp); Endpoint_ResetDataToggle(); if (Endpoint_IsStalled()) Endpoint_ClearStall(); } Endpoint_SelectEndpoint(lastEndpoint); }
static void USB_Device_GetStatus(void) { uint8_t CurrentStatus = 0; switch (USB_ControlRequest.bmRequestType) { #if !defined(NO_DEVICE_SELF_POWER) || !defined(NO_DEVICE_REMOTE_WAKEUP) case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE): #if !defined(NO_DEVICE_SELF_POWER) if (USB_Device_CurrentlySelfPowered) CurrentStatus |= FEATURE_SELFPOWERED_ENABLED; #endif #if !defined(NO_DEVICE_REMOTE_WAKEUP) if (USB_Device_RemoteWakeupEnabled) CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED; #endif break; #endif #if !defined(CONTROL_ONLY_DEVICE) case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT): Endpoint_SelectEndpoint((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK); CurrentStatus = Endpoint_IsStalled(); Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); break; #endif default: return; } Endpoint_ClearSETUP(); Endpoint_Write_16_LE(CurrentStatus); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); }
uint8_t Endpoint_WaitUntilReady(void) { uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; USB_INT_Clear(USB_INT_SOFI); while (!(Endpoint_ReadWriteAllowed())) { if (!(USB_IsConnected)) return ENDPOINT_READYWAIT_DeviceDisconnected; else if (Endpoint_IsStalled()) return ENDPOINT_READYWAIT_EndpointStalled; if (USB_INT_HasOccurred(USB_INT_SOFI)) { USB_INT_Clear(USB_INT_SOFI); if (!(TimeoutMSRem--)) return ENDPOINT_READYWAIT_Timeout; } } return ENDPOINT_READYWAIT_NoError; }
static bool USB_BulkWorker() { uint8_t cmdBuf[XUM_CMDBUF_SIZE], statusBuf[XUM_STATUSBUF_SIZE]; int8_t status; /* * If we are not connected to the host or a command has not yet * been sent, no more processing is required. */ if (USB_DeviceState != DEVICE_STATE_Configured) return false; Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT); if (!Endpoint_IsReadWriteAllowed()) return false; #ifdef DEBUG // Dump the status of both endpoints before getting the command Endpoint_SelectEndpoint(XUM_BULK_IN_ENDPOINT); DEBUGF(DBG_INFO, "bsti %x %x %x %x %x %x %x %x\n", Endpoint_GetCurrentEndpoint(), Endpoint_BytesInEndpoint(), Endpoint_IsEnabled(), Endpoint_IsReadWriteAllowed(), Endpoint_IsConfigured(), Endpoint_IsINReady(), Endpoint_IsOUTReceived(), Endpoint_IsStalled()); Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT); DEBUGF(DBG_INFO, "bsto %x %x %x %x %x %x %x %x\n", Endpoint_GetCurrentEndpoint(), Endpoint_BytesInEndpoint(), Endpoint_IsEnabled(), Endpoint_IsReadWriteAllowed(), Endpoint_IsConfigured(), Endpoint_IsINReady(), Endpoint_IsOUTReceived(), Endpoint_IsStalled()); #endif // Read in the command from the host now that one is ready. if (!USB_ReadBlock(cmdBuf, sizeof(cmdBuf))) { board_set_status(STATUS_ERROR); return false; } // Allow commands to leave the extended status untouched memset(statusBuf, 0, sizeof(statusBuf)); /* * Decode and process the command. * usbHandleBulk() stores its extended result in the output buffer, * up to XUM_STATUSBUF_SIZE. * * Return values: * >0: completed ok, send the return value and extended status * 0: completed ok, don't send any status * -1: error, no status */ status = usbHandleBulk(cmdBuf, statusBuf); if (status > 0) { statusBuf[0] = status; USB_WriteBlock(statusBuf, sizeof(statusBuf)); } else if (status < 0) { DEBUGF(DBG_ERROR, "usbblk err\n"); board_set_status(STATUS_ERROR); Endpoint_StallTransaction(); return false; } return true; }