diff options
author | Dean Camera <dean@fourwalledcubicle.com> | 2009-08-26 07:01:32 +0000 |
---|---|---|
committer | Dean Camera <dean@fourwalledcubicle.com> | 2009-08-26 07:01:32 +0000 |
commit | ee744abb7efd5fef49782991d58895e10696809a (patch) | |
tree | 1efb545a069d2e969be60a7e4f827b26024ac13b /LUFA/Drivers/USB/Class/Host | |
parent | f547eb36080dacf275cd94fc3ddfb4c618c587fa (diff) | |
download | lufa-ee744abb7efd5fef49782991d58895e10696809a.tar.gz lufa-ee744abb7efd5fef49782991d58895e10696809a.tar.bz2 lufa-ee744abb7efd5fef49782991d58895e10696809a.zip |
More work on the Mass Storage Host mode Class driver.
Added ATTR_NON_NULL_PTR_ARG() attributes to the class drivers to improve user code reliability by disallowing explicit NULL pointers as pointer parameters in function calls where the parameter must not be NULL.
Disabled building of the Demos/Host/ClassDriver directory until Host Mode Class drivers are complete to prevent build errors in the meantime.
Diffstat (limited to 'LUFA/Drivers/USB/Class/Host')
-rw-r--r-- | LUFA/Drivers/USB/Class/Host/CDC.h | 42 | ||||
-rw-r--r-- | LUFA/Drivers/USB/Class/Host/HID.h | 12 | ||||
-rw-r--r-- | LUFA/Drivers/USB/Class/Host/MassStorage.c | 188 | ||||
-rw-r--r-- | LUFA/Drivers/USB/Class/Host/MassStorage.h | 137 |
4 files changed, 349 insertions, 30 deletions
diff --git a/LUFA/Drivers/USB/Class/Host/CDC.h b/LUFA/Drivers/USB/Class/Host/CDC.h index 5baafafe5..f3abb296e 100644 --- a/LUFA/Drivers/USB/Class/Host/CDC.h +++ b/LUFA/Drivers/USB/Class/Host/CDC.h @@ -122,9 +122,9 @@ /** General management task for a given CDC host class interface, required for the correct operation of the interface. This should
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state
*/
- void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo);
+ void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Host interface configuration routine, to configure a given CDC host interface instance using the Configuration
* Descriptor read from an attached USB device. This function automatically updates the given CDC Host instance's
@@ -132,63 +132,63 @@ * This should be called once after the stack has enumerated the attached device, while the host state machine is in
* the Addressed state.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state
* \param[in] ConfigDescriptorLength Length of the attached device's Configuration Descriptor
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
*/
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, uint16_t ConfigDescriptorLength,
- uint8_t* DeviceConfigDescriptor);
+ uint8_t* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1, 3);
/** Sets the line encoding for the attached device's virtual serial port. This should be called when the LineEncoding
* values of the interface have been changed to push the new settings to the USB device.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
*/
- uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo);
+ uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a Serial Control Line State Change notification to the device. This should be called when the virtual serial
* control lines (DTR, RTS, etc.) have changed states. Line states persist until they are cleared via a second
* notification. This should be called each time the CDC class driver's ControlLineStates.HostToDevice value is updated
* to push the new states to the USB device.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
*/
- uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo);
+ uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a given string to the attached USB device, if connected. If a device is not connected when the function is called, the
* string is discarded.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
* \param[in] Data Pointer to the string to send to the device
* \param[in] Length Size in bytes of the string to send to the device
*/
- void CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, char* Data, uint16_t Length);
+ void CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, char* Data, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1, 2);
/** Sends a given byte to the attached USB device, if connected. If a host is not connected when the function is called, the
* byte is discarded.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
* \param[in] Data Byte of data to send to the device
*/
- void CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, uint8_t Data);
+ void CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
/** Determines the number of bytes received by the CDC interface from the device, waiting to be read.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
*
* \return Total number of buffered bytes received from the device
*/
- uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo);
+ uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
* returns 0. The \ref CDC_Host_BytesReceived() function should be queried before data is recieved to ensure that no data
* underflow occurs.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
*
* \return Next received byte from the device, or 0 if no data received
*/
- uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo);
+ uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** CDC class driver event for a control line state change on a CDC host interface. This event fires each time the device notifies
* the host of a control line state change (containing the virtual serial control line states, such as DCD) and may be hooked in the
@@ -196,9 +196,9 @@ * are available in the ControlLineStates.DeviceToHost value inside the CDC host interface structure passed as a parameter, set as
* a mask of CDC_CONTROL_LINE_IN_* masks.
*
- * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
*/
- void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo);
+ void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
@@ -218,9 +218,9 @@ #if defined(INCLUDE_FROM_CDC_CLASS_HOST_C)
void CDC_Host_Event_Stub(void);
void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo)
- ATTR_WEAK ATTR_ALIAS(CDC_Host_Event_Stub);
- static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* CurrentDescriptor);
- static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* CurrentDescriptor);
+ ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Host_Event_Stub);
+ static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DComp_CDC_Host_NextInterfaceCDCDataEndpoint(void* CurrentDescriptor);
#endif
#endif
diff --git a/LUFA/Drivers/USB/Class/Host/HID.h b/LUFA/Drivers/USB/Class/Host/HID.h index 3d7a5390a..6e1a5222b 100644 --- a/LUFA/Drivers/USB/Class/Host/HID.h +++ b/LUFA/Drivers/USB/Class/Host/HID.h @@ -104,12 +104,12 @@ } HIDHost_EnumerationFailure_ErrorCodes_t;
/* Function Prototypes: */
- void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo);
+ void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo, uint16_t ConfigDescriptorLength,
- uint8_t* DeviceConfigDescriptor);
+ uint8_t* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1, 3);
- bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo);
- uint8_t USB_HID_Host_SetProtocol(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo, bool UseReportProtocol);
+ bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+ uint8_t USB_HID_Host_SetProtocol(USB_ClassInfo_HID_Host_t* HIDInterfaceInfo, bool UseReportProtocol) ATTR_NON_NULL_PTR_ARG(1);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
@@ -121,8 +121,8 @@ /* Function Prototypes: */
#if defined(INCLUDE_FROM_HID_CLASS_HOST_C)
- static uint8_t DComp_HID_Host_NextHIDInterface(void* CurrentDescriptor);
- static uint8_t DComp_HID_Host_NextInterfaceHIDDataEndpoint(void* CurrentDescriptor);
+ static uint8_t DComp_HID_Host_NextHIDInterface(void* CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DComp_HID_Host_NextInterfaceHIDDataEndpoint(void* CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.c b/LUFA/Drivers/USB/Class/Host/MassStorage.c index 6332d3a61..ea7ed3d8a 100644 --- a/LUFA/Drivers/USB/Class/Host/MassStorage.c +++ b/LUFA/Drivers/USB/Class/Host/MassStorage.c @@ -131,4 +131,192 @@ void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* MSInterfaceInfo) }
+static uint8_t MassStore_SendCommand(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, MS_CommandBlockWrapper_t* SCSICommandBlock)
+{
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+
+ if (++MSInterfaceInfo->State.TransactionTag == 0xFFFFFFFF)
+ MSInterfaceInfo->State.TransactionTag = 1;
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+ while(!(Pipe_IsOUTReady()));
+
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+static uint8_t MassStore_WaitForDataReceived(USB_ClassInfo_MS_Host_t* MSInterfaceInfo)
+{
+ uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber);
+ Pipe_Unfreeze();
+
+ while (!(Pipe_IsINReceived()))
+ {
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+ TimeoutMSRem--;
+
+ 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;
+}
+
+static uint8_t MassStore_SendReceiveData(USB_ClassInfo_MS_Host_t* MSInterfaceInfo,
+ MS_CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr)
+{
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+ uint16_t BytesRem = SCSICommandBlock->DataTransferLength;
+
+ if (SCSICommandBlock->Flags & COMMAND_DIRECTION_DATA_IN)
+ {
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearIN();
+ }
+ else
+ {
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+
+ while (!(Pipe_IsOUTReady()))
+ {
+ if (USB_HostState == HOST_STATE_Unattached)
+ return PIPE_RWSTREAM_DeviceDisconnected;
+ }
+ }
+
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+static uint8_t MassStore_GetReturnedStatus(USB_ClassInfo_MS_Host_t* MSInterfaceInfo,
+ MS_CommandStatusWrapper_t* SCSICommandStatus)
+{
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+
+ if ((ErrorCode = MassStore_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Read_Stream_LE(&SCSICommandStatus, sizeof(MS_CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearIN();
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* MSInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.Active))
+ return HOST_SENDCONTROL_DeviceDisconnect;
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = REQ_MassStorageReset,
+ .wValue = 0,
+ .wIndex = MSInterfaceInfo->State.InterfaceNumber,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t* MaxLUNIndex)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.Active))
+ return HOST_SENDCONTROL_DeviceDisconnect;
+
+ uint8_t ErrorCode;
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = REQ_GetMaxLUN,
+ .wValue = 0,
+ .wIndex = MSInterfaceInfo->State.InterfaceNumber,
+ .wLength = 1,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(MaxLUNIndex)) == HOST_SENDCONTROL_SetupStalled)
+ {
+ Pipe_ClearStall();
+
+ *MaxLUNIndex = 0;
+ }
+
+ return ErrorCode;
+}
+
+uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, SCSI_Inquiry_Response_t* InquiryData)
+{
+
+}
+
+uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, bool* DeviceReady);
+uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
+ SCSI_Capacity_t* DeviceCapacity);
+
#endif
diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.h b/LUFA/Drivers/USB/Class/Host/MassStorage.h index 18b2cf4ae..a8a957bab 100644 --- a/LUFA/Drivers/USB/Class/Host/MassStorage.h +++ b/LUFA/Drivers/USB/Class/Host/MassStorage.h @@ -78,25 +78,137 @@ uint16_t DataINPipeSize; /**< Size in bytes of the MS interface's IN data pipe */
uint16_t DataOUTPipeSize; /**< Size in bytes of the MS interface's OUT data pipe */
+
+ uint32_t TransactionTag; /**< Current transaction tag for data synchronising of packets */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_MS_Host_t;
+ /** Type define for a SCSI Sense structure. Structures of this type are filled out by the
+ * device via the MassStore_RequestSense() function, indicating the current sense data of the
+ * device (giving explicit error codes for the last issued command). For details of the
+ * structure contents, refer to the SCSI specifications.
+ */
+ typedef struct
+ {
+ uint8_t ReponseCode;
+
+ uint8_t SegmentNumber;
+
+ unsigned char SenseKey : 4;
+ unsigned char _RESERVED1 : 1;
+ unsigned char ILI : 1;
+ unsigned char EOM : 1;
+ unsigned char FileMark : 1;
+
+ uint8_t Information[4];
+ uint8_t AdditionalLength;
+ uint8_t CmdSpecificInformation[4];
+ uint8_t AdditionalSenseCode;
+ uint8_t AdditionalSenseQualifier;
+ uint8_t FieldReplaceableUnitCode;
+ uint8_t SenseKeySpecific[3];
+ } SCSI_Request_Sense_Response_t;
+
+ /** Type define for a SCSI Inquiry structure. Structures of this type are filled out by the
+ * device via the MassStore_Inquiry() function, retrieving the attached device's information.
+ * For details of the structure contents, refer to the SCSI specifications.
+ */
+ typedef struct
+ {
+ unsigned char DeviceType : 5;
+ unsigned char PeripheralQualifier : 3;
+
+ unsigned char _RESERVED1 : 7;
+ unsigned char Removable : 1;
+
+ uint8_t Version;
+
+ unsigned char ResponseDataFormat : 4;
+ unsigned char _RESERVED2 : 1;
+ unsigned char NormACA : 1;
+ unsigned char TrmTsk : 1;
+ unsigned char AERC : 1;
+
+ uint8_t AdditionalLength;
+ uint8_t _RESERVED3[2];
+
+ unsigned char SoftReset : 1;
+ unsigned char CmdQue : 1;
+ unsigned char _RESERVED4 : 1;
+ unsigned char Linked : 1;
+ unsigned char Sync : 1;
+ unsigned char WideBus16Bit : 1;
+ unsigned char WideBus32Bit : 1;
+ unsigned char RelAddr : 1;
+
+ uint8_t VendorID[8];
+ uint8_t ProductID[16];
+ uint8_t RevisionID[4];
+ } SCSI_Inquiry_Response_t;
+
+ /** SCSI capacity structure, to hold the total capacity of the device in both the number
+ * of blocks in the current LUN, and the size of each block. This structure is filled by
+ * the device when the MassStore_ReadCapacity() function is called.
+ */
+ typedef struct
+ {
+ uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device */
+ uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN */
+ } SCSI_Capacity_t;
+
/* Enums: */
enum
{
MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
- MS_ENUMERROR_NoMSInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor */
+ MS_ENUMERROR_NoMSInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor */
MS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Mass Storage endpoints were not found in the device's interfaces */
} MSHost_EnumerationFailure_ErrorCodes_t;
/* Function Prototypes: */
- void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* MSInterfaceInfo);
+ /** General management task for a given Mass Storage host class interface, required for the correct operation of
+ * the interface. This should be called frequently in the main program loop, before the master USB management task
+ * \ref USB_USBTask().
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state
+ */
+ void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Host interface configuration routine, to configure a given Mass Storage host interface instance using the
+ * Configuration Descriptor read from an attached USB device. This function automatically updates the given Mass
+ * Storage Host instance's state values and configures the pipes required to communicate with the interface if it
+ * is found within the device. This should be called once after the stack has enumerated the attached device, while
+ * the host state machine is in the Addressed state.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state
+ * \param[in] ConfigDescriptorLength Length of the attached device's Configuration Descriptor
+ * \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
+ */
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint16_t ConfigDescriptorLength,
- uint8_t* DeviceConfigDescriptor);
+ uint8_t* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1, 3);
+
+ /** Sends a MASS STORAGE RESET control request to the attached device, resetting the Mass Storage Interface
+ * and readying it for the next Mass Storage command.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
+ */
+ uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t* MaxLUNIndex) ATTR_NON_NULL_PTR_ARG(1, 2);
+
+ uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* MSInterfaceInfo,
+ SCSI_Inquiry_Response_t* InquiryData) ATTR_NON_NULL_PTR_ARG(1, 2);
+
+ uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
+ bool* DeviceReady) ATTR_NON_NULL_PTR_ARG(1, 3);
+
+ uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
+ SCSI_Capacity_t* DeviceCapacity) ATTR_NON_NULL_PTR_ARG(1, 3);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
@@ -105,6 +217,17 @@ #define MASS_STORE_SUBCLASS 0x06
#define MASS_STORE_PROTOCOL 0x50
+ #define REQ_MassStorageReset 0xFF
+ #define REQ_GetMaxLUN 0xFE
+
+ #define CBW_SIGNATURE 0x43425355UL
+ #define CSW_SIGNATURE 0x53425355UL
+
+ #define COMMAND_DIRECTION_DATA_OUT (0 << 7)
+ #define COMMAND_DIRECTION_DATA_IN (1 << 7)
+
+ #define COMMAND_DATA_TIMEOUT_MS 2000
+
#define MS_FOUND_DATAPIPE_IN (1 << 0)
#define MS_FOUND_DATAPIPE_OUT (1 << 1)
@@ -112,6 +235,14 @@ #if defined(INCLUDE_FROM_MS_CLASS_HOST_C)
static uint8_t DComp_NextMassStorageInterface(void* CurrentDescriptor);
static uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor);
+
+ static uint8_t MassStore_SendCommand(USB_ClassInfo_MS_Host_t* MSInterfaceInfo,
+ MS_CommandBlockWrapper_t* SCSICommandBlock);
+ static uint8_t MassStore_WaitForDataReceived(USB_ClassInfo_MS_Host_t* MSInterfaceInfo);
+ static uint8_t MassStore_SendReceiveData(USB_ClassInfo_MS_Host_t* MSInterfaceInfo,
+ MS_CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr);
+ static uint8_t MassStore_GetReturnedStatus(USB_ClassInfo_MS_Host_t* MSInterfaceInfo,
+ MS_CommandStatusWrapper_t* SCSICommandStatus);
#endif
#endif
|