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
);