summaryrefslogtreecommitdiff
path: root/usb/device/massstorage/MSDDriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'usb/device/massstorage/MSDDriver.c')
-rw-r--r--usb/device/massstorage/MSDDriver.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/usb/device/massstorage/MSDDriver.c b/usb/device/massstorage/MSDDriver.c
new file mode 100644
index 0000000..fbaebb0
--- /dev/null
+++ b/usb/device/massstorage/MSDDriver.c
@@ -0,0 +1,343 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+
+#include <memories/Media.h>
+#include "MSDDriver.h"
+#include "MSDDriverDescriptors.h"
+#include "SBCMethods.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDCallbacks.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/device/core/USBDDriverCallbacks.h>
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// Mass storage device driver instance.
+static MSDDriver msdDriver;
+
+/// Standard device driver instance.
+static USBDDriver usbdDriver;
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Resets the state of the MSD driver
+//-----------------------------------------------------------------------------
+static void MSDDriver_Reset(void)
+{
+ TRACE_INFO_WP("MSDReset ");
+
+ msdDriver.state = MSDD_STATE_READ_CBW;
+ msdDriver.waitResetRecovery = 0;
+ msdDriver.commandState.state = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Callback re-implementation
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Invoked when a new SETUP request is received from the host. Forwards the
+/// request to the Mass Storage device driver handler function.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ MSDDriver_RequestHandler(request);
+}
+
+//-----------------------------------------------------------------------------
+/// Invoked when the configuration of the device changes. Resets the mass
+/// storage driver.
+/// \param cfgnum New configuration number.
+//-----------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ MSDDriver_Reset();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Driver functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Reads from host through MSD defined bulk OUT pipe. Act as USBD_Read but by
+/// a fixed OUT endpoint.
+/// \param data Pointer to the data buffer that contains data read from host.
+/// \param size The number of bytes should be read (buffer size).
+/// \param callback Pointer to the function invoked on end of reading.
+/// \param argument Pointer to additional argument data struct.
+//-----------------------------------------------------------------------------
+char MSDD_Read(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+
+{
+ return USBD_Read(MSDDriverDescriptors_BULKOUT,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// Writes to host through MSD defined bulk IN pipe. Act as USBD_Write but by
+/// a fixed IN endpoint.
+/// \param data Pointer to the data that writes to the host.
+/// \param size The number of bytes should be write.
+/// \param callback Pointer to the function invoked on end of writing.
+/// \param argument Pointer to additional argument data struct.
+//-----------------------------------------------------------------------------
+char MSDD_Write(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Write(MSDDriverDescriptors_BULKIN,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// HALT Specified USB pipe.
+/// \param stallCASE Case of the stall condition (Bulk In/Out/Both).
+//-----------------------------------------------------------------------------
+void MSDD_Halt(unsigned int stallCASE)
+{
+ if (stallCASE & MSDD_CASE_STALL_OUT) {
+
+ USBD_Halt(MSDDriverDescriptors_BULKOUT);
+ }
+
+ if (stallCASE & MSDD_CASE_STALL_IN) {
+
+ USBD_Halt(MSDDriverDescriptors_BULKIN);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Return halted status
+/// \return stallCASE bitmap, case of the stall condition
+/// (bit: MSDD_CASE_STALL_OUT or MSDD_CASE_STALL_IN)
+//-----------------------------------------------------------------------------
+unsigned int MSDD_IsHalted(void)
+{
+ unsigned int stallCASE = 0;
+ if (USBD_IsHalted(MSDDriverDescriptors_BULKOUT)) {
+
+ stallCASE |= MSDD_CASE_STALL_OUT;
+ }
+ if (USBD_IsHalted(MSDDriverDescriptors_BULKIN)) {
+
+ stallCASE |= MSDD_CASE_STALL_IN;
+ }
+ return stallCASE;
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the MSD driver and the associated USB driver.
+/// \param luns Pointer to a list of LUNs
+/// \param numLuns Number of LUN in list
+/// \see MSDLun
+//-----------------------------------------------------------------------------
+void MSDDriver_Initialize(MSDLun *defLuns, unsigned char numLuns)
+{
+
+ TRACE_INFO("MSD init\n\r");
+
+ // Command state initialization
+ msdDriver.commandState.state = 0;
+ msdDriver.commandState.postprocess = 0;
+ msdDriver.commandState.length = 0;
+ msdDriver.commandState.transfer.semaphore = 0;
+
+ // LUNs
+ msdDriver.luns = defLuns;
+ msdDriver.maxLun = (unsigned char) (numLuns - 1);
+
+ // Reset BOT driver
+ MSDDriver_Reset();
+
+ // Init the USB driver
+ USBDDriver_Initialize(&usbdDriver, &msdDriverDescriptors, 0);
+ USBD_Init();
+}
+
+//-----------------------------------------------------------------------------
+/// Handler for incoming SETUP requests on default Control endpoint 0.
+///
+/// Standard requests are forwarded to the USBDDriver_RequestHandler
+/// method.
+/// \param request Pointer to a USBGenericRequest instance
+//-----------------------------------------------------------------------------
+void MSDDriver_RequestHandler(const USBGenericRequest *request)
+{
+ TRACE_INFO_WP("NewReq ");
+
+ // Handle requests
+ switch (USBGenericRequest_GetRequest(request)) {
+ //---------------------
+ case USBGenericRequest_CLEARFEATURE:
+ //---------------------
+ TRACE_INFO_WP("ClrFeat ");
+
+ switch (USBFeatureRequest_GetFeatureSelector(request)) {
+
+ //---------------------
+ case USBFeatureRequest_ENDPOINTHALT:
+ //---------------------
+ TRACE_INFO_WP("Hlt ");
+
+ // Do not clear the endpoint halt status if the device is waiting
+ // for a reset recovery sequence
+ if (!msdDriver.waitResetRecovery) {
+
+ // Forward the request to the standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+ }
+ else {
+
+ TRACE_INFO_WP("No ");
+ }
+
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ //------
+ default:
+ //------
+ // Forward the request to the standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+ }
+ break;
+
+ //-------------------
+ case MSD_GET_MAX_LUN:
+ //-------------------
+ TRACE_INFO_WP("gMaxLun ");
+
+ // Check request parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == 0)
+ && (request->wLength == 1)) {
+
+ USBD_Write(0, &(msdDriver.maxLun), 1, 0, 0);
+
+ }
+ else {
+
+ TRACE_WARNING(
+ "MSDDriver_RequestHandler: GetMaxLUN(%d,%d,%d)\n\r",
+ request->wValue, request->wIndex, request->wLength);
+ USBD_Stall(0);
+ }
+ break;
+
+ //-----------------------
+ case MSD_BULK_ONLY_RESET:
+ //-----------------------
+ TRACE_INFO_WP("Rst ");
+
+ // Check parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == 0)
+ && (request->wLength == 0)) {
+
+ // Reset the MSD driver
+ MSDDriver_Reset();
+ USBD_Write(0, 0, 0, 0, 0);
+ }
+ else {
+
+ TRACE_WARNING(
+ "MSDDriver_RequestHandler: Reset(%d,%d,%d)\n\r",
+ request->wValue, request->wIndex, request->wLength);
+ USBD_Stall(0);
+ }
+ break;
+
+ //------
+ default:
+ //------
+ // Forward request to standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// State machine for the MSD driver
+//-----------------------------------------------------------------------------
+void MSDDriver_StateMachine(void)
+{
+ if (USBD_GetState() < USBD_STATE_CONFIGURED){}
+ else MSDD_StateMachine(&msdDriver);
+
+}
+
+//-----------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//-----------------------------------------------------------------------------
+void MSDDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+ // Remote wake-up NOT enabled
+ else {
+
+ TRACE_WARNING(
+ "MSD..RemoteWakeUp: Host has not enabled remote wake-up\n\r");
+ }
+}
+
personal git repositories of Harald Welte. Your mileage may vary