3      Copyright (C) Dean Camera, 2009. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, and distribute this software 
  13   and its documentation for any purpose and without fee is hereby 
  14   granted, provided that the above copyright notice appear in all 
  15   copies and that both that the copyright notice and this 
  16   permission notice and warranty disclaimer appear in supporting 
  17   documentation, and that the name of the author not be used in 
  18   advertising or publicity pertaining to distribution of the 
  19   software without specific, written prior permission. 
  21   The author disclaim all warranties with regard to this 
  22   software, including all implied warranties of merchantability 
  23   and fitness.  In no event shall the author be liable for any 
  24   special, indirect or consequential damages or any damages 
  25   whatsoever resulting from loss of use, data or profits, whether 
  26   in an action of contract, negligence or other tortious action, 
  27   arising out of or in connection with the use or performance of 
  31 #define  INCLUDE_FROM_MS_CLASS_C 
  32 #include "MassStorage.h" 
  34 static USB_ClassInfo_MS_t
* CallbackMSInterfaceInfo
; 
  36 void USB_MS_ProcessControlPacket(USB_ClassInfo_MS_t
* MSInterfaceInfo
) 
  38         if (!(Endpoint_IsSETUPReceived())) 
  41         if (USB_ControlRequest
.wIndex 
!= MSInterfaceInfo
->InterfaceNumber
) 
  44         switch (USB_ControlRequest
.bRequest
) 
  46                 case REQ_MassStorageReset
: 
  47                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  49                                 Endpoint_ClearSETUP(); 
  51                                 MSInterfaceInfo
->IsMassStoreReset 
= true;                        
  53                                 while (!(Endpoint_IsINReady())); 
  59                         if (USB_ControlRequest
.bmRequestType 
== (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
)) 
  61                                 Endpoint_ClearSETUP(); 
  63                                 Endpoint_Write_Byte(MSInterfaceInfo
->TotalLUNs 
- 1); 
  67                                 while (!(Endpoint_IsOUTReceived())); 
  75 bool USB_MS_ConfigureEndpoints(USB_ClassInfo_MS_t
* MSInterfaceInfo
) 
  77         if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo
->DataINEndpointNumber
, EP_TYPE_BULK
, 
  78                                                                  ENDPOINT_DIR_IN
, MSInterfaceInfo
->DataINEndpointSize
, 
  79                                                                  ENDPOINT_BANK_SINGLE
))) 
  84         if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo
->DataOUTEndpointNumber
, EP_TYPE_BULK
, 
  85                                          ENDPOINT_DIR_OUT
, MSInterfaceInfo
->DataOUTEndpointSize
, 
  86                                          ENDPOINT_BANK_SINGLE
))) 
  94 void USB_MS_USBTask(USB_ClassInfo_MS_t
* MSInterfaceInfo
) 
  96         if (!(USB_IsConnected
)) 
  99         Endpoint_SelectEndpoint(MSInterfaceInfo
->DataOUTEndpointNumber
); 
 101         if (Endpoint_IsReadWriteAllowed()) 
 103                 if (USB_MS_ReadInCommandBlock(MSInterfaceInfo
)) 
 105                         if (MSInterfaceInfo
->CommandBlock
.Flags 
& MS_COMMAND_DIR_DATA_IN
) 
 106                           Endpoint_SelectEndpoint(MSInterfaceInfo
->DataINEndpointNumber
); 
 108                         MSInterfaceInfo
->CommandStatus
.Status              
= CALLBACK_USB_MS_SCSICommandReceived(MSInterfaceInfo
) ?
 
 109                                                                               SCSI_Command_Pass 
: SCSI_Command_Fail
; 
 110                         MSInterfaceInfo
->CommandStatus
.Signature           
= MS_CSW_SIGNATURE
; 
 111                         MSInterfaceInfo
->CommandStatus
.Tag                 
= MSInterfaceInfo
->CommandBlock
.Tag
; 
 112                         MSInterfaceInfo
->CommandStatus
.DataTransferResidue 
= MSInterfaceInfo
->CommandBlock
.DataTransferLength
; 
 114                         if ((MSInterfaceInfo
->CommandStatus
.Status 
== SCSI_Command_Fail
) && (MSInterfaceInfo
->CommandStatus
.DataTransferResidue
)) 
 115                           Endpoint_StallTransaction(); 
 117                         USB_MS_ReturnCommandStatus(MSInterfaceInfo
); 
 119                         if (MSInterfaceInfo
->IsMassStoreReset
) 
 121                                 Endpoint_ResetFIFO(MSInterfaceInfo
->DataOUTEndpointNumber
); 
 122                                 Endpoint_ResetFIFO(MSInterfaceInfo
->DataINEndpointNumber
); 
 124                                 Endpoint_SelectEndpoint(MSInterfaceInfo
->DataOUTEndpointNumber
); 
 125                                 Endpoint_ClearStall(); 
 126                                 Endpoint_SelectEndpoint(MSInterfaceInfo
->DataINEndpointNumber
); 
 127                                 Endpoint_ClearStall(); 
 129                                 MSInterfaceInfo
->IsMassStoreReset 
= false; 
 135 static bool USB_MS_ReadInCommandBlock(USB_ClassInfo_MS_t
* MSInterfaceInfo
) 
 137         Endpoint_SelectEndpoint(MSInterfaceInfo
->DataOUTEndpointNumber
); 
 139         CallbackMSInterfaceInfo 
= MSInterfaceInfo
; 
 140         Endpoint_Read_Stream_LE(&MSInterfaceInfo
->CommandBlock
, 
 141                                 (sizeof(CommandBlockWrapper_t
) - 16), 
 142                                 StreamCallback_AbortOnMassStoreReset
); 
 144         if ((MSInterfaceInfo
->CommandBlock
.Signature         
!= MS_CBW_SIGNATURE
)           || 
 145             (MSInterfaceInfo
->CommandBlock
.LUN               
>= MSInterfaceInfo
->TotalLUNs
) || 
 146                 (MSInterfaceInfo
->CommandBlock
.SCSICommandLength 
>  16)) 
 148                 Endpoint_StallTransaction(); 
 149                 Endpoint_SelectEndpoint(MSInterfaceInfo
->DataINEndpointNumber
); 
 150                 Endpoint_StallTransaction(); 
 155         CallbackMSInterfaceInfo 
= MSInterfaceInfo
; 
 156         Endpoint_Read_Stream_LE(&MSInterfaceInfo
->CommandBlock
.SCSICommandData
, 
 157                                 MSInterfaceInfo
->CommandBlock
.SCSICommandLength
, 
 158                                 StreamCallback_AbortOnMassStoreReset
); 
 162         if (MSInterfaceInfo
->IsMassStoreReset
) 
 168 static void USB_MS_ReturnCommandStatus(USB_ClassInfo_MS_t
* MSInterfaceInfo
) 
 170         Endpoint_SelectEndpoint(MSInterfaceInfo
->DataOUTEndpointNumber
); 
 172         while (Endpoint_IsStalled()) 
 176                 if (MSInterfaceInfo
->IsMassStoreReset
) 
 180         Endpoint_SelectEndpoint(MSInterfaceInfo
->DataINEndpointNumber
); 
 182         while (Endpoint_IsStalled()) 
 186                 if (MSInterfaceInfo
->IsMassStoreReset
) 
 190         CallbackMSInterfaceInfo 
= MSInterfaceInfo
; 
 191         Endpoint_Write_Stream_LE(&MSInterfaceInfo
->CommandStatus
, sizeof(CommandStatusWrapper_t
), 
 192                                  StreamCallback_AbortOnMassStoreReset
); 
 196         if (MSInterfaceInfo
->IsMassStoreReset
) 
 200 static uint8_t StreamCallback_AbortOnMassStoreReset(void) 
 202         USB_MS_USBTask(CallbackMSInterfaceInfo
); 
 204         if (CallbackMSInterfaceInfo
->IsMassStoreReset
) 
 205           return STREAMCALLBACK_Abort
; 
 207           return STREAMCALLBACK_Continue
;