msdbot.c
Go to the documentation of this file.00001
00036 #include "em_usb.h"
00037 #include "msdbot.h"
00038
00041 #define TIMEOUT_1SEC 1000
00042 #define TIMEOUT_2SEC 2000
00043 #define DEFAULT_TIMEOUT TIMEOUT_2SEC
00044
00045
00046 static USBH_Ep_TypeDef *epOut = NULL;
00047 static USBH_Ep_TypeDef *epIn = NULL;
00048
00049
00050 static int timeoutFactor;
00051
00052
00053 STATIC_UBUF(csw, CSW_LEN);
00054 static MSDBOT_CSW_TypeDef *pCsw = (MSDBOT_CSW_TypeDef*) csw;
00055
00056
00057 static bool CswMeaningful(MSDBOT_CBW_TypeDef *pCbw);
00058 static bool CswValid(MSDBOT_CBW_TypeDef *pCbw);
00059 static void ResetRecovery(void);
00060
00063
00076 int MSDBOT_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
00077 {
00078
00079
00080 if ((sizeof(MSDBOT_CBW_TypeDef) != CBW_LEN) ||
00081 (sizeof(MSDBOT_CSW_TypeDef) != CSW_LEN))
00082 {
00083 DEBUG_USB_API_PUTS("\nMSDBOT_Init(), typedef size error");
00084 EFM_ASSERT(false);
00085 return MSDBOT_INIT_ERROR;
00086 }
00087
00088
00089 epOut = out;
00090 epIn = in;
00091
00092
00093 if (epIn->parentDevice->speed == PORT_FULL_SPEED)
00094 timeoutFactor = 512;
00095 else
00096 timeoutFactor = 64;
00097
00098 return MSDBOT_STATUS_OK;
00099 }
00100
00101
00116 int MSDBOT_Xfer(void* cbw, void* data)
00117 {
00118 uint32_t len;
00119 int timeout, result, direction, retVal;
00120 MSDBOT_CBW_TypeDef *pCbw = (MSDBOT_CBW_TypeDef*) cbw;
00121
00122
00123 result = USBH_WriteB(epOut, cbw, CBW_LEN, DEFAULT_TIMEOUT);
00124
00125 if (result != CBW_LEN)
00126 {
00127 ResetRecovery();
00128 return MSDBOT_XFER_ERROR;
00129 }
00130
00131 retVal = 0;
00132 direction = pCbw->Direction;
00133 len = pCbw->dCBWDataTransferLength;
00134
00135
00136 if (len)
00137 {
00138 timeout = DEFAULT_TIMEOUT + (len / timeoutFactor);
00139
00140 if (direction)
00141 result = USBH_ReadB(epIn, data, len, timeout);
00142 else
00143 result = USBH_WriteB(epOut, data, len, timeout);
00144
00145 retVal = result;
00146
00147 if (result == USB_STATUS_EP_STALLED)
00148 {
00149 if (direction)
00150 USBH_UnStallEpB(epIn);
00151 else
00152 USBH_UnStallEpB(epOut);
00153 }
00154
00155 else if (result <= 0)
00156 {
00157 ResetRecovery();
00158 return MSDBOT_XFER_ERROR;
00159 }
00160 }
00161
00162
00163 result = USBH_ReadB(epIn, csw, CSW_LEN, DEFAULT_TIMEOUT);
00164
00165 if (result != CSW_LEN)
00166 {
00167 if (result == USB_STATUS_EP_STALLED)
00168 {
00169 if (direction)
00170 USBH_UnStallEpB(epIn);
00171 else
00172 USBH_UnStallEpB(epOut);
00173
00174 result = USBH_ReadB(epIn, csw, CSW_LEN, DEFAULT_TIMEOUT);
00175
00176 if (result != CSW_LEN)
00177 {
00178 ResetRecovery();
00179 return MSDBOT_XFER_ERROR;
00180 }
00181 }
00182 else
00183 {
00184 ResetRecovery();
00185 return MSDBOT_XFER_ERROR;
00186 }
00187 }
00188
00189 if (CswValid(pCbw) && CswMeaningful(pCbw))
00190 {
00191 if (pCsw->bCSWStatus == USB_CLASS_MSD_CSW_CMDPASSED)
00192 {
00193 return retVal;
00194 }
00195 return MSDBOT_CMD_FAILED;
00196 }
00197
00198 ResetRecovery();
00199 return MSDBOT_XFER_ERROR;
00200 }
00201
00204
00215 static bool CswMeaningful(MSDBOT_CBW_TypeDef *cbw)
00216 {
00217 if (((pCsw->bCSWStatus == USB_CLASS_MSD_CSW_CMDPASSED) ||
00218 (pCsw->bCSWStatus == USB_CLASS_MSD_CSW_CMDFAILED)) &&
00219 (pCsw->dCSWDataResidue <= cbw->dCBWDataTransferLength))
00220 return true;
00221
00222 return false;
00223 }
00224
00225
00236 static bool CswValid(MSDBOT_CBW_TypeDef *cbw)
00237 {
00238 if ((pCsw->dCSWSignature == CSW_SIGNATURE) &&
00239 (pCsw->dCSWTag == cbw->dCBWTag))
00240 return true;
00241
00242 return false;
00243 }
00244
00245
00249 static void ResetRecovery(void)
00250 {
00251 USBH_ControlMsgB(&epIn->parentDevice->ep0,
00252 USB_SETUP_DIR_H2D | USB_SETUP_RECIPIENT_INTERFACE |
00253 USB_SETUP_TYPE_CLASS_MASK,
00254 USB_MSD_BOTRESET,
00255 0,
00256 0,
00257 0,
00258 NULL,
00259 TIMEOUT_1SEC);
00260
00261 USBH_UnStallEpB(epIn);
00262 USBH_UnStallEpB(epOut);
00263 }
00264