X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/9a97f16b07ea15e327b0d01be238b06623b033d6..77a9df36a77d2523dd2bc24fa17f9f04c6c175c5:/Demos/Device/LowLevel/MassStorage/MassStorage.c diff --git a/Demos/Device/LowLevel/MassStorage/MassStorage.c b/Demos/Device/LowLevel/MassStorage/MassStorage.c index 93b7c6102..7f2d86610 100644 --- a/Demos/Device/LowLevel/MassStorage/MassStorage.c +++ b/Demos/Device/LowLevel/MassStorage/MassStorage.c @@ -1,21 +1,21 @@ /* LUFA Library - Copyright (C) Dean Camera, 2010. - + Copyright (C) Dean Camera, 2011. + dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com + www.lufa-lib.org */ /* - Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - Permission to use, copy, modify, distribute, and sell this + Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in + without fee, provided that the above copyright notice appear in all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the software without specific, written prior permission. The author disclaim all warranties with regard to this @@ -38,13 +38,13 @@ #include "MassStorage.h" /** Structure to hold the latest Command Block Wrapper issued by the host, containing a SCSI command to execute. */ -CommandBlockWrapper_t CommandBlock; +MS_CommandBlockWrapper_t CommandBlock; /** Structure to hold the latest Command Status Wrapper to return to the host, containing the status of the last issued command. */ -CommandStatusWrapper_t CommandStatus = { .Signature = CSW_SIGNATURE }; +MS_CommandStatusWrapper_t CommandStatus = { .Signature = MS_CSW_SIGNATURE }; /** Flag to asynchronously abort any in-progress data transfers upon the reception of a mass storage reset command. */ -volatile bool IsMassStoreReset = false; +volatile bool IsMassStoreReset = false; /** Main program entry point. This routine configures the hardware required by the application, then @@ -53,7 +53,7 @@ volatile bool IsMassStoreReset = false; int main(void) { SetupHardware(); - + LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); sei(); @@ -76,7 +76,7 @@ void SetupHardware(void) /* Hardware Initialization */ LEDs_Init(); - SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER); + SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER); Dataflash_Init(); USB_Init(); @@ -89,7 +89,7 @@ void EVENT_USB_Device_Connect(void) { /* Indicate USB enumerating */ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); - + /* Reset the MSReset flag upon connection */ IsMassStoreReset = false; } @@ -108,59 +108,50 @@ void EVENT_USB_Device_Disconnect(void) */ void EVENT_USB_Device_ConfigurationChanged(void) { - /* Indicate USB connected and ready */ - LEDs_SetAllLEDs(LEDMASK_USB_READY); + bool ConfigSuccess = true; - /* Setup Mass Storage In and Out Endpoints */ - if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK, - ENDPOINT_DIR_IN, MASS_STORAGE_IO_EPSIZE, - ENDPOINT_BANK_SINGLE))) - { - LEDs_SetAllLEDs(LEDMASK_USB_ERROR); - } - - if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK, - ENDPOINT_DIR_OUT, MASS_STORAGE_IO_EPSIZE, - ENDPOINT_BANK_SINGLE))) - { - LEDs_SetAllLEDs(LEDMASK_USB_ERROR); - } + /* Setup Mass Storage Data Endpoints */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_IN, + MASS_STORAGE_IO_EPSIZE, ENDPOINT_BANK_SINGLE); + ConfigSuccess &= Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_OUT, + MASS_STORAGE_IO_EPSIZE, ENDPOINT_BANK_SINGLE); + + /* Indicate endpoint configuration success or failure */ + LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR); } -/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific - * control requests that are not handled internally by the USB library (including the Mass Storage class-specific - * requests) so that they can be handled appropriately for the application. +/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to + * the device from the USB host before passing along unhandled control requests to the library for processing + * internally. */ -void EVENT_USB_Device_UnhandledControlRequest(void) +void EVENT_USB_Device_ControlRequest(void) { /* Process UFI specific control requests */ switch (USB_ControlRequest.bRequest) { - case REQ_MassStorageReset: + case MS_REQ_MassStorageReset: if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); + Endpoint_ClearStatusStage(); /* Indicate that the current transfer should be aborted */ IsMassStoreReset = true; - - Endpoint_ClearStatusStage(); } break; - case REQ_GetMaxLUN: + case MS_REQ_GetMaxLUN: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); /* Indicate to the host the number of supported LUNs (virtual disks) on the device */ - Endpoint_Write_Byte(TOTAL_LUNS - 1); - + Endpoint_Write_8(TOTAL_LUNS - 1); + Endpoint_ClearIN(); - Endpoint_ClearStatusStage(); } - + break; } } @@ -181,20 +172,20 @@ void MassStorage_Task(void) 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) + if (CommandBlock.Flags & MS_COMMAND_DIR_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; + CommandStatus.Status = SCSI_DecodeSCSICommand() ? MS_SCSI_COMMAND_Pass : MS_SCSI_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)) + if ((CommandStatus.Status == MS_SCSI_COMMAND_Fail) && (CommandStatus.DataTransferResidue)) Endpoint_StallTransaction(); /* Return command status block to the host */ @@ -208,9 +199,9 @@ void MassStorage_Task(void) if (IsMassStoreReset) { /* Reset the data endpoint banks */ - Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM); - Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM); - + Endpoint_ResetEndpoint(MASS_STORAGE_OUT_EPNUM); + Endpoint_ResetEndpoint(MASS_STORAGE_IN_EPNUM); + Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); Endpoint_ClearStall(); Endpoint_ResetDataToggle(); @@ -230,48 +221,53 @@ void MassStorage_Task(void) */ static bool ReadInCommandBlock(void) { + uint16_t BytesTransferred; + /* Select the Data Out endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); - + /* Abort if no command has been sent from the host */ if (!(Endpoint_IsOUTReceived())) return false; /* Read in command block header */ - Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)), - StreamCallback_AbortOnMassStoreReset); - - /* Check if the current command is being aborted by the host */ - if (IsMassStoreReset) - return false; + BytesTransferred = 0; + while (Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)), + &BytesTransferred) == ENDPOINT_RWSTREAM_IncompleteTransfer) + { + /* Check if the current command is being aborted by the host */ + if (IsMassStoreReset) + return false; + } /* Verify the command block - abort if invalid */ - if ((CommandBlock.Signature != CBW_SIGNATURE) || - (CommandBlock.LUN >= TOTAL_LUNS) || - (CommandBlock.Flags & 0x1F) || - (CommandBlock.SCSICommandLength == 0) || - (CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH)) + if ((CommandBlock.Signature != MS_CBW_SIGNATURE) || + (CommandBlock.LUN >= TOTAL_LUNS) || + (CommandBlock.Flags & 0x1F) || + (CommandBlock.SCSICommandLength == 0) || + (CommandBlock.SCSICommandLength > sizeof(CommandBlock.SCSICommandData))) { /* Stall both data pipes until reset by host */ Endpoint_StallTransaction(); Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM); Endpoint_StallTransaction(); - + return false; } /* Read in command block command data */ - Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData, - CommandBlock.SCSICommandLength, - StreamCallback_AbortOnMassStoreReset); - - /* Check if the current command is being aborted by the host */ - if (IsMassStoreReset) - return false; + BytesTransferred = 0; + while (Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData, CommandBlock.SCSICommandLength, + &BytesTransferred) == ENDPOINT_RWSTREAM_IncompleteTransfer) + { + /* Check if the current command is being aborted by the host */ + if (IsMassStoreReset) + return false; + } /* Finalize the stream transfer to send the last packet */ Endpoint_ClearOUT(); - + return true; } @@ -280,6 +276,8 @@ static bool ReadInCommandBlock(void) */ static void ReturnCommandStatus(void) { + uint16_t BytesTransferred; + /* Select the Data Out endpoint */ Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM); @@ -301,28 +299,17 @@ static void ReturnCommandStatus(void) if (IsMassStoreReset) return; } - + /* Write the CSW to the endpoint */ - Endpoint_Write_Stream_LE(&CommandStatus, sizeof(CommandStatus), - StreamCallback_AbortOnMassStoreReset); + 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; + } - /* 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(); } - -/** Stream callback function for the Endpoint stream read and write functions. This callback will abort the current stream transfer - * if a Mass Storage Reset request has been issued to the control endpoint. - */ -uint8_t StreamCallback_AbortOnMassStoreReset(void) -{ - /* Abort if a Mass Storage reset command was received */ - if (IsMassStoreReset) - return STREAMCALLBACK_Abort; - - /* Continue with the current stream operation */ - return STREAMCALLBACK_Continue; -}