/** Waits until the attached device is ready to accept data following a CBW, checking * to ensure that the device has not stalled the transaction. * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_WaitForDataReceived(void) { uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; /* Unfreeze the OUT pipe so that it can be checked */ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Wait until data received in the IN pipe */ while (!(Pipe_IsINReceived())) { /* Check to see if a new frame has been issued (1ms elapsed) */ if (USB_INT_HasOccurred(USB_INT_HSOFI)) { /* Clear the flag and decrement the timeout period counter */ USB_INT_Clear(USB_INT_HSOFI); TimeoutMSRem--; /* Check to see if the timeout period for the command has elapsed */ if (!(TimeoutMSRem)) return PIPE_RWSTREAM_Timeout; } Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the OUT pipe */ MassStore_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE); return PIPE_RWSTREAM_PipeStalled; } Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the IN pipe */ MassStore_ClearPipeStall(MASS_STORE_DATA_IN_PIPE); return PIPE_RWSTREAM_PipeStalled; } /* Check to see if the device was disconnected, if so exit function */ if (!(USB_IsConnected)) return PIPE_RWSTREAM_DeviceDisconnected; }; return PIPE_RWSTREAM_NoError; }
static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) { uint16_t TimeoutMSRem = MS_COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(MSInterfaceInfo->Config.DataOUTPipeNumber); return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(MSInterfaceInfo->Config.DataINPipeNumber); return PIPE_RWSTREAM_PipeStalled; } if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; }; Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_Freeze(); Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
uint8_t Pipe_WaitUntilReady(const uint8_t corenum) { /* #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_Host_GetFrameNumber();*/ for (;; ) { if (Pipe_IsReadWriteAllowed(corenum)) { return PIPE_READYWAIT_NoError; } if (Pipe_IsStalled(corenum)) { return PIPE_READYWAIT_PipeStalled; } else if (USB_HostState[corenum] == HOST_STATE_Unattached) { return PIPE_READYWAIT_DeviceDisconnected; } /*TODO no timeout yet */ /* uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return PIPE_READYWAIT_Timeout; }*/ } }
uint8_t Pipe_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 (Pipe_GetPipeToken() == PIPE_TOKEN_IN) { if (Pipe_IsINReceived()) return PIPE_READYWAIT_NoError; } else { if (Pipe_IsOUTReady()) return PIPE_READYWAIT_NoError; } if (Pipe_IsStalled()) return PIPE_READYWAIT_PipeStalled; else if (USB_HostState == HOST_STATE_Unattached) return PIPE_READYWAIT_DeviceDisconnected; if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); if (!(TimeoutMSRem--)) return PIPE_READYWAIT_Timeout; } } }
uint8_t Pipe_Write_Stream_LE(const void* Data, uint16_t Length #if !defined(NO_STREAM_CALLBACKS) , uint8_t (* const Callback)(void) #endif ) { uint8_t* DataStream = (uint8_t*)Data; uint8_t ErrorCode; while (Length) { if (!(Pipe_ReadWriteAllowed())) { Pipe_ClearCurrentBank(); #if !defined(NO_STREAM_CALLBACKS) if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) return ENDPOINT_RWSTREAM_ERROR_CallbackAborted; #endif if ((ErrorCode = Pipe_WaitUntilReady())) return ErrorCode; } Pipe_Write_Byte(*(DataStream++)); Length--; if (!(USB_IsConnected)) return PIPE_RWSTREAM_ERROR_DeviceDisconnected; else if (Pipe_IsStalled()) return PIPE_RWSTREAM_ERROR_PipeStalled; } return PIPE_RWSTREAM_ERROR_NoError; }
uint8_t USB_Host_WaitMS(uint8_t MS) { bool BusSuspended = USB_Host_IsBusSuspended(); uint8_t ErrorCode = HOST_WAITERROR_Successful; USB_INT_Clear(USB_INT_HSOFI); USB_Host_ResumeBus(); while (MS) { if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); MS--; } if ((USB_IsConnected == false) || (USB_CurrentMode == USB_MODE_DEVICE)) { ErrorCode = HOST_WAITERROR_DeviceDisconnect; break; } if (Pipe_IsError() == true) { Pipe_ClearError(); ErrorCode = HOST_WAITERROR_PipeError; break; } if (Pipe_IsStalled() == true) { Pipe_ClearStall(); ErrorCode = HOST_WAITERROR_SetupStalled; break; } } if (BusSuspended) USB_Host_SuspendBus(); return ErrorCode; }
uint8_t Pipe_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_Host_GetFrameNumber(); for (;;) { if (Pipe_GetPipeToken() == PIPE_TOKEN_IN) { if (Pipe_IsINReceived()) return PIPE_READYWAIT_NoError; } else { if (Pipe_IsOUTReady()) return PIPE_READYWAIT_NoError; } if (Pipe_IsStalled()) return PIPE_READYWAIT_PipeStalled; else if (USB_HostState == HOST_STATE_Unattached) return PIPE_READYWAIT_DeviceDisconnected; uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return PIPE_READYWAIT_Timeout; } } }
uint8_t Pipe_WaitUntilReady(void) { uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; USB_INT_Clear(USB_INT_HSOFI); while (!(Pipe_ReadWriteAllowed())) { if (Pipe_IsStalled()) return PIPE_READYWAIT_PipeStalled; else if (!(USB_IsConnected)) return PIPE_READYWAIT_DeviceDisconnected; if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); if (!(TimeoutMSRem--)) return PIPE_READYWAIT_Timeout; } } return PIPE_READYWAIT_NoError; }
uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, PIMA_Container_t* const PIMAHeader) { uint16_t TimeoutMSRem = SI_COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); if (CurrentFrameNumber != PreviousFrameNumber) { PreviousFrameNumber = CurrentFrameNumber; if (!(TimeoutMSRem--)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber); return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber); return PIPE_RWSTREAM_PipeStalled; } if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK); if (PIMAHeader->Type == PIMA_CONTAINER_ResponseBlock) { uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0)); if (ParamBytes) Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK); Pipe_ClearIN(); } Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
void USB_Host_ProcessNextHostState(void) { uint8_t ErrorCode = HOST_ENUMERROR_NoError; uint8_t SubErrorCode = HOST_ENUMERROR_NoError; static uint16_t WaitMSRemaining; static uint8_t PostWaitState; switch (USB_HostState) { case HOST_STATE_WaitForDevice: if (WaitMSRemaining) { if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) { USB_HostState = PostWaitState; ErrorCode = HOST_ENUMERROR_WaitStage; break; } if (!(--WaitMSRemaining)) USB_HostState = PostWaitState; } break; case HOST_STATE_Powered: WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS; USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle; break; case HOST_STATE_Powered_WaitForDeviceSettle: if (WaitMSRemaining--) { _delay_ms(1); break; } else { USB_Host_VBUS_Manual_Off(); USB_OTGPAD_On(); USB_Host_VBUS_Auto_Enable(); USB_Host_VBUS_Auto_On(); USB_HostState = HOST_STATE_Powered_WaitForConnect; } break; case HOST_STATE_Powered_WaitForConnect: if (USB_INT_HasOccurred(USB_INT_DCONNI)) { USB_INT_Clear(USB_INT_DCONNI); USB_INT_Clear(USB_INT_DDISCI); USB_INT_Clear(USB_INT_VBERRI); USB_INT_Enable(USB_INT_VBERRI); USB_Host_ResumeBus(); Pipe_ClearPipes(); HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset); } break; case HOST_STATE_Powered_DoReset: USB_Host_ResetDevice(); HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe); break; case HOST_STATE_Powered_ConfigPipe: Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE); if (!(Pipe_IsConfigured())) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; break; } USB_HostState = HOST_STATE_Default; break; case HOST_STATE_Default: USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), .bRequest = REQ_GetDescriptor, .wValue = (DTYPE_Device << 8), .wIndex = 0, .wLength = 8, }; uint8_t DataBuffer[8]; if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful) { ErrorCode = HOST_ENUMERROR_ControlError; break; } USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)]; USB_Host_ResetDevice(); HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset); break; case HOST_STATE_Default_PostReset: Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, USB_ControlPipeSize, PIPE_BANK_SINGLE); if (!(Pipe_IsConfigured())) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; break; } USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE), .bRequest = REQ_SetAddress, .wValue = USB_HOST_DEVICEADDRESS, .wIndex = 0, .wLength = 0, }; if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful) { ErrorCode = HOST_ENUMERROR_ControlError; break; } HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet); break; case HOST_STATE_Default_PostAddressSet: USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS); EVENT_USB_Host_DeviceEnumerationComplete(); USB_HostState = HOST_STATE_Addressed; break; } if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached)) { EVENT_USB_Host_DeviceEnumerationFailed(ErrorCode, SubErrorCode); USB_Host_VBUS_Auto_Off(); EVENT_USB_Host_DeviceUnattached(); USB_ResetInterface(); } } uint8_t USB_Host_WaitMS(uint8_t MS) { bool BusSuspended = USB_Host_IsBusSuspended(); uint8_t ErrorCode = HOST_WAITERROR_Successful; bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI); USB_INT_Disable(USB_INT_HSOFI); USB_INT_Clear(USB_INT_HSOFI); USB_Host_ResumeBus(); while (MS) { if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); MS--; } if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode != USB_MODE_Host)) { ErrorCode = HOST_WAITERROR_DeviceDisconnect; break; } if (Pipe_IsError() == true) { Pipe_ClearError(); ErrorCode = HOST_WAITERROR_PipeError; break; } if (Pipe_IsStalled() == true) { Pipe_ClearStall(); ErrorCode = HOST_WAITERROR_SetupStalled; break; } } if (BusSuspended) USB_Host_SuspendBus(); if (HSOFIEnabled) USB_INT_Enable(USB_INT_HSOFI); return ErrorCode; } static void USB_Host_ResetDevice(void) { bool BusSuspended = USB_Host_IsBusSuspended(); USB_INT_Disable(USB_INT_DDISCI); USB_Host_ResetBus(); while (!(USB_Host_IsBusResetComplete())); USB_Host_ResumeBus(); bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI); USB_INT_Disable(USB_INT_HSOFI); USB_INT_Clear(USB_INT_HSOFI); for (uint8_t MSRem = 10; MSRem != 0; MSRem--) { /* Workaround for powerless-pull-up devices. After a USB bus reset, all disconnection interrupts are suppressed while a USB frame is looked for - if it is found within 10ms, the device is still present. */ if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); USB_INT_Clear(USB_INT_DDISCI); break; } _delay_ms(1); } if (HSOFIEnabled) USB_INT_Enable(USB_INT_HSOFI); if (BusSuspended) USB_Host_SuspendBus(); USB_INT_Enable(USB_INT_DDISCI); }
/** Function to receive a PIMA response container from the attached still image device. * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ uint8_t SImage_ReceiveBlockHeader(void) { uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); /* Unfreeze the data IN pipe */ Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Wait until data received on the IN pipe */ while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); /* Check to see if a new frame has been issued (1ms elapsed) */ if (CurrentFrameNumber != PreviousFrameNumber) { /* Save the new frame number and decrement the timeout period */ PreviousFrameNumber = CurrentFrameNumber; TimeoutMSRem--; /* Check to see if the timeout period for the command has elapsed */ if (!(TimeoutMSRem)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the OUT pipe */ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); /* Return error code and break out of the loop */ return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the IN pipe */ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); /* Return error code */ return PIPE_RWSTREAM_PipeStalled; } /* Check to see if the device was disconnected, if so exit function */ if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } /* Load in the response from the attached device */ Pipe_Read_Stream_LE(&PIMA_ReceivedBlock, PIMA_COMMAND_SIZE(0), NULL); /* Check if the returned block type is a response block */ if (PIMA_ReceivedBlock.Type == PIMA_CONTAINER_ResponseBlock) { /* Determine the size of the parameters in the block via the data length attribute */ uint8_t ParamBytes = (PIMA_ReceivedBlock.DataLength - PIMA_COMMAND_SIZE(0)); /* Check if the device has returned any parameters */ if (ParamBytes) { /* Read the PIMA parameters from the data IN pipe */ Pipe_Read_Stream_LE(&PIMA_ReceivedBlock.Params, ParamBytes, NULL); } /* Clear pipe bank after use */ Pipe_ClearIN(); } /* Freeze the IN pipe after use */ Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
/** Waits until the attached device is ready to accept data following a CBW, checking * to ensure that the device has not stalled the transaction. * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ static uint8_t MassStore_WaitForDataReceived(void) { uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Wait until data received in the IN pipe */ while (!(Pipe_IsINReceived())) { uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); /* Check to see if a new frame has been issued (1ms elapsed) */ if (CurrentFrameNumber != PreviousFrameNumber) { /* Save the new frame number and decrement the timeout period */ PreviousFrameNumber = CurrentFrameNumber; TimeoutMSRem--; /* Check to see if the timeout period for the command has elapsed */ if (!(TimeoutMSRem)) return PIPE_RWSTREAM_Timeout; } Pipe_Freeze(); Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the OUT pipe */ USB_Host_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE); return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); /* Check if pipe stalled (command failed by device) */ if (Pipe_IsStalled()) { /* Clear the stall condition on the IN pipe */ USB_Host_ClearPipeStall(MASS_STORE_DATA_IN_PIPE); return PIPE_RWSTREAM_PipeStalled; } /* Check to see if the device was disconnected, if so exit function */ if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; }; Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Freeze(); Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE); Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }
static uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader) { uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); while (!(Pipe_IsReadWriteAllowed())) { if (USB_INT_HasOccurred(USB_INT_HSOFI)) { USB_INT_Clear(USB_INT_HSOFI); TimeoutMSRem--; if (!(TimeoutMSRem)) { return PIPE_RWSTREAM_Timeout; } } Pipe_Freeze(); Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber); return PIPE_RWSTREAM_PipeStalled; } Pipe_Freeze(); Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_Unfreeze(); if (Pipe_IsStalled()) { USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber); return PIPE_RWSTREAM_PipeStalled; } if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; } Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK); if (PIMAHeader->Type == CType_ResponseBlock) { uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0)); if (ParamBytes) Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK); Pipe_ClearIN(); PIMAHeader->Code &= 0x0000000F; } Pipe_Freeze(); return PIPE_RWSTREAM_NoError; }