/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they * contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command. */ void MassStorage_Task(void) { /* Device must be connected and configured for the task to run */ if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Process sent command block from the host if one has been sent */ if (ReadInCommandBlock()) { /* Indicate busy */ LEDs_SetAllLEDs(LEDMASK_USB_BUSY); /* Check direction of command, select Data IN endpoint if data is from the device */ if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN) Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); /* Decode the received SCSI command, set returned status code */ CommandStatus.Status = SCSI_DecodeSCSICommand() ? Command_Pass : Command_Fail; /* Load in the CBW tag into the CSW to link them together */ CommandStatus.Tag = CommandBlock.Tag; /* Load in the data residue counter into the CSW */ CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength; /* Stall the selected data pipe if command failed (if data is still to be transferred) */ if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue)) Endpoint_StallTransaction(); /* Return command status block to the host */ ReturnCommandStatus(); /* Indicate ready */ LEDs_SetAllLEDs(LEDMASK_USB_READY); } /* Check if a Mass Storage Reset occurred */ if (IsMassStoreReset) { /* Reset the data endpoint banks */ Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM); Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM); Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); /* Clear the abort transfer flag */ IsMassStoreReset = false; } }
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { if (USB_DeviceState != DEVICE_STATE_Configured) return; Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); if (Endpoint_IsReadWriteAllowed()) { if (MS_Device_ReadInCommandBlock(MSInterfaceInfo)) { if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN) Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); MSInterfaceInfo->State.CommandStatus.Status = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail; MSInterfaceInfo->State.CommandStatus.Signature = MS_CSW_SIGNATURE; MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag; MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength; if ((MSInterfaceInfo->State.CommandStatus.Status == MS_SCSI_COMMAND_Fail) && (MSInterfaceInfo->State.CommandStatus.DataTransferResidue)) { Endpoint_StallTransaction(); } MS_Device_ReturnCommandStatus(MSInterfaceInfo); } } if (MSInterfaceInfo->State.IsMassStoreReset) { Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataOUTEndpointNumber); Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataINEndpointNumber); Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); MSInterfaceInfo->State.IsMassStoreReset = false; } }
/* * 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); }