msdbot.c
Go to the documentation of this file.00001
00018 #include "em_usb.h"
00019 #include "msdbot.h"
00020
00023 #define TIMEOUT_1SEC 1000
00024 #define TIMEOUT_2SEC 2000
00025 #define DEFAULT_TIMEOUT TIMEOUT_2SEC
00026
00027
00028 static USBH_Ep_TypeDef *epOut = NULL;
00029 static USBH_Ep_TypeDef *epIn = NULL;
00030
00031
00032 static int timeoutFactor;
00033
00034
00035 STATIC_UBUF(csw, CSW_LEN);
00036 static MSDBOT_CSW_TypeDef *pCsw = (MSDBOT_CSW_TypeDef*) csw;
00037
00038
00039 static bool CswMeaningful(MSDBOT_CBW_TypeDef *pCbw);
00040 static bool CswValid(MSDBOT_CBW_TypeDef *pCbw);
00041 static void ResetRecovery(void);
00042
00045
00058 int MSDBOT_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
00059 {
00060
00061
00062 if ((sizeof(MSDBOT_CBW_TypeDef) != CBW_LEN) ||
00063 (sizeof(MSDBOT_CSW_TypeDef) != CSW_LEN))
00064 {
00065 DEBUG_USB_API_PUTS("\nMSDBOT_Init(), typedef size error");
00066 EFM_ASSERT(false);
00067 return MSDBOT_INIT_ERROR;
00068 }
00069
00070
00071 epOut = out;
00072 epIn = in;
00073
00074
00075 if (epIn->parentDevice->speed == PORT_FULL_SPEED)
00076 timeoutFactor = 512;
00077 else
00078 timeoutFactor = 64;
00079
00080 return MSDBOT_STATUS_OK;
00081 }
00082
00083
00098 int MSDBOT_Xfer(void* cbw, void* data)
00099 {
00100 uint32_t len;
00101 int timeout, result, direction, retVal;
00102 MSDBOT_CBW_TypeDef *pCbw = (MSDBOT_CBW_TypeDef*) cbw;
00103
00104
00105 result = USBH_WriteB(epOut, cbw, CBW_LEN, DEFAULT_TIMEOUT);
00106
00107 if (result != CBW_LEN)
00108 {
00109 ResetRecovery();
00110 return MSDBOT_XFER_ERROR;
00111 }
00112
00113 retVal = 0;
00114 direction = pCbw->Direction;
00115 len = pCbw->dCBWDataTransferLength;
00116
00117
00118 if (len)
00119 {
00120 timeout = DEFAULT_TIMEOUT + (len / timeoutFactor);
00121
00122 if (direction)
00123 result = USBH_ReadB(epIn, data, len, timeout);
00124 else
00125 result = USBH_WriteB(epOut, data, len, timeout);
00126
00127 retVal = result;
00128
00129 if (result == USB_STATUS_EP_STALLED)
00130 {
00131 if (direction)
00132 USBH_UnStallEpB(epIn);
00133 else
00134 USBH_UnStallEpB(epOut);
00135 }
00136
00137 else if (result <= 0)
00138 {
00139 ResetRecovery();
00140 return MSDBOT_XFER_ERROR;
00141 }
00142 }
00143
00144
00145 result = USBH_ReadB(epIn, csw, CSW_LEN, DEFAULT_TIMEOUT);
00146
00147 if (result != CSW_LEN)
00148 {
00149 if (result == USB_STATUS_EP_STALLED)
00150 {
00151 if (direction)
00152 USBH_UnStallEpB(epIn);
00153 else
00154 USBH_UnStallEpB(epOut);
00155
00156 result = USBH_ReadB(epIn, csw, CSW_LEN, DEFAULT_TIMEOUT);
00157
00158 if (result != CSW_LEN)
00159 {
00160 ResetRecovery();
00161 return MSDBOT_XFER_ERROR;
00162 }
00163 }
00164 else
00165 {
00166 ResetRecovery();
00167 return MSDBOT_XFER_ERROR;
00168 }
00169 }
00170
00171 if (CswValid(pCbw) && CswMeaningful(pCbw))
00172 {
00173 if (pCsw->bCSWStatus == USB_CLASS_MSD_CSW_CMDPASSED)
00174 {
00175 return retVal;
00176 }
00177 return MSDBOT_CMD_FAILED;
00178 }
00179
00180 ResetRecovery();
00181 return MSDBOT_XFER_ERROR;
00182 }
00183
00186
00197 static bool CswMeaningful(MSDBOT_CBW_TypeDef *cbw)
00198 {
00199 if (((pCsw->bCSWStatus == USB_CLASS_MSD_CSW_CMDPASSED) ||
00200 (pCsw->bCSWStatus == USB_CLASS_MSD_CSW_CMDFAILED)) &&
00201 (pCsw->dCSWDataResidue <= cbw->dCBWDataTransferLength))
00202 return true;
00203
00204 return false;
00205 }
00206
00207
00218 static bool CswValid(MSDBOT_CBW_TypeDef *cbw)
00219 {
00220 if ((pCsw->dCSWSignature == CSW_SIGNATURE) &&
00221 (pCsw->dCSWTag == cbw->dCBWTag))
00222 return true;
00223
00224 return false;
00225 }
00226
00227
00231 static void ResetRecovery(void)
00232 {
00233 USBH_ControlMsgB(&epIn->parentDevice->ep0,
00234 USB_SETUP_DIR_H2D | USB_SETUP_RECIPIENT_INTERFACE |
00235 USB_SETUP_TYPE_CLASS_MASK,
00236 USB_MSD_BOTRESET,
00237 0,
00238 0,
00239 0,
00240 NULL,
00241 TIMEOUT_1SEC);
00242
00243 USBH_UnStallEpB(epIn);
00244 USBH_UnStallEpB(epOut);
00245 }
00246