2 ******************************************************************************
4 * @author MCD Application Team
7 * @brief This file provides all the BOT protocol core functions.
8 ******************************************************************************
11 * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
13 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
14 * You may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at:
17 * http://www.st.com/software_license_agreement_liberty_v2
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
25 ******************************************************************************
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbd_composite.h"
30 #include "usbd_msc_bot.h"
32 #include "usbd_msc_scsi.h"
33 #include "usbd_ioreq.h"
35 /** @addtogroup STM32_USB_DEVICE_LIBRARY
41 * @brief BOT protocol module
45 /** @defgroup MSC_BOT_Private_TypesDefinitions
53 /** @defgroup MSC_BOT_Private_Defines
62 /** @defgroup MSC_BOT_Private_Macros
70 /** @defgroup MSC_BOT_Private_Variables
79 /** @defgroup MSC_BOT_Private_FunctionPrototypes
82 static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev);
84 static void MSC_BOT_SendData (USBD_HandleTypeDef *pdev,
88 static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev);
94 /** @defgroup MSC_BOT_Private_Functions
101 * @brief MSC_BOT_Init
102 * Initialize the BOT Process
103 * @param pdev: device instance
106 void MSC_BOT_Init (USBD_HandleTypeDef *pdev)
108 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
109 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
111 hmsc->bot_state = USBD_BOT_IDLE;
112 hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
114 hmsc->scsi_sense_tail = 0;
115 hmsc->scsi_sense_head = 0;
117 ((USBD_StorageTypeDef *)pdev->pUserData)->Init(0);
119 USBD_LL_FlushEP(pdev, MSC_EPOUT_ADDR);
120 USBD_LL_FlushEP(pdev, MSC_EPIN_ADDR);
122 /* Prapare EP to Receive First BOT Cmd */
123 USBD_LL_PrepareReceive (pdev,
125 (uint8_t *)&hmsc->cbw,
126 USBD_BOT_CBW_LENGTH);
130 * @brief MSC_BOT_Reset
131 * Reset the BOT Machine
132 * @param pdev: device instance
135 void MSC_BOT_Reset (USBD_HandleTypeDef *pdev)
137 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
138 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
140 hmsc->bot_state = USBD_BOT_IDLE;
141 hmsc->bot_status = USBD_BOT_STATUS_RECOVERY;
143 /* Prapare EP to Receive First BOT Cmd */
144 USBD_LL_PrepareReceive (pdev,
146 (uint8_t *)&hmsc->cbw,
147 USBD_BOT_CBW_LENGTH);
151 * @brief MSC_BOT_DeInit
152 * Deinitialize the BOT Machine
153 * @param pdev: device instance
156 void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev)
158 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
159 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
160 hmsc->bot_state = USBD_BOT_IDLE;
164 * @brief MSC_BOT_DataIn
165 * Handle BOT IN data stage
166 * @param pdev: device instance
167 * @param epnum: endpoint index
170 void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum)
172 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
173 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
175 switch (hmsc->bot_state)
177 case USBD_BOT_DATA_IN:
178 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
180 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
184 case USBD_BOT_SEND_DATA:
185 case USBD_BOT_LAST_DATA_IN:
186 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
194 * @brief MSC_BOT_DataOut
195 * Process MSC OUT data
196 * @param pdev: device instance
197 * @param epnum: endpoint index
200 void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
202 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
203 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
205 switch (hmsc->bot_state)
208 MSC_BOT_CBW_Decode(pdev);
211 case USBD_BOT_DATA_OUT:
212 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
214 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
224 * @brief MSC_BOT_CBW_Decode
225 * Decode the CBW command and set the BOT state machine accordingly
226 * @param pdev: device instance
229 static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev)
231 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
232 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
234 hmsc->csw.dTag = hmsc->cbw.dTag;
235 hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
237 if ((USBD_LL_GetRxDataSize (pdev ,MSC_EPOUT_ADDR) != USBD_BOT_CBW_LENGTH) ||
238 (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE)||
239 (hmsc->cbw.bLUN > 1) ||
240 (hmsc->cbw.bCBLength < 1) ||
241 (hmsc->cbw.bCBLength > 16))
248 hmsc->bot_status = USBD_BOT_STATUS_ERROR;
253 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
255 if(hmsc->bot_state == USBD_BOT_NO_DATA)
257 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
264 /*Burst xfer handled internally*/
265 else if ((hmsc->bot_state != USBD_BOT_DATA_IN) &&
266 (hmsc->bot_state != USBD_BOT_DATA_OUT) &&
267 (hmsc->bot_state != USBD_BOT_LAST_DATA_IN))
269 if (hmsc->bot_data_length > 0)
271 MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length);
273 else if (hmsc->bot_data_length == 0)
275 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
282 * @brief MSC_BOT_SendData
283 * Send the requested data
284 * @param pdev: device instance
285 * @param buf: pointer to data buffer
286 * @param len: Data Length
289 static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
293 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
294 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
296 len = MIN (hmsc->cbw.dDataLength, len);
297 hmsc->csw.dDataResidue -= len;
298 hmsc->csw.bStatus = USBD_CSW_CMD_PASSED;
299 hmsc->bot_state = USBD_BOT_SEND_DATA;
301 USBD_LL_Transmit (pdev, MSC_EPIN_ADDR, buf, len);
305 * @brief MSC_BOT_SendCSW
306 * Send the Command Status Wrapper
307 * @param pdev: device instance
308 * @param status : CSW status
311 void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev, uint8_t CSW_Status)
313 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
314 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
316 hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE;
317 hmsc->csw.bStatus = CSW_Status;
318 hmsc->bot_state = USBD_BOT_IDLE;
320 USBD_LL_Transmit (pdev,
322 (uint8_t *)&hmsc->csw,
323 USBD_BOT_CSW_LENGTH);
325 /* Prepare EP to Receive next Cmd */
326 USBD_LL_PrepareReceive (pdev,
328 (uint8_t *)&hmsc->cbw,
329 USBD_BOT_CBW_LENGTH);
334 * @brief MSC_BOT_Abort
335 * Abort the current transfer
336 * @param pdev: device instance
340 static void MSC_BOT_Abort (USBD_HandleTypeDef *pdev)
342 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
343 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
345 if ((hmsc->cbw.bmFlags == 0) &&
346 (hmsc->cbw.dDataLength != 0) &&
347 (hmsc->bot_status == USBD_BOT_STATUS_NORMAL) )
349 USBD_LL_StallEP(pdev, MSC_EPOUT_ADDR );
351 USBD_LL_StallEP(pdev, MSC_EPIN_ADDR);
353 if(hmsc->bot_status == USBD_BOT_STATUS_ERROR)
355 USBD_LL_PrepareReceive (pdev,
357 (uint8_t *)&hmsc->cbw,
358 USBD_BOT_CBW_LENGTH);
363 * @brief MSC_BOT_CplClrFeature
364 * Complete the clear feature request
365 * @param pdev: device instance
366 * @param epnum: endpoint index
370 void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum)
372 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
373 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
375 if(hmsc->bot_status == USBD_BOT_STATUS_ERROR )/* Bad CBW Signature */
377 USBD_LL_StallEP(pdev, MSC_EPIN_ADDR);
378 hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
380 else if((epnum == MSC_EPIN_ADDR) && ( hmsc->bot_status != USBD_BOT_STATUS_RECOVERY))
382 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);