01c88ddda7af234994bcb645f71ffe61df40f3b8
[fw/stlink] / example / stm32f4 / STM32_USB_Device_Library / Class / msc / src / usbd_msc_bot.c
1 /**
2   ******************************************************************************
3   * @file    usbd_msc_bot.c
4   * @author  MCD Application Team
5   * @version V1.0.0
6   * @date    22-July-2011
7   * @brief   This file provides all the BOT protocol core functions.
8   ******************************************************************************
9   * @attention
10   *
11   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
12   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
13   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
14   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
15   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
16   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
17   *
18   * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
19   ******************************************************************************
20   */ 
21
22 /* Includes ------------------------------------------------------------------*/
23 #include "usbd_msc_bot.h"
24 #include "usbd_msc_scsi.h"
25 #include "usbd_ioreq.h"
26 #include "usbd_msc_mem.h"
27 /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
28   * @{
29   */
30
31
32 /** @defgroup MSC_BOT 
33   * @brief BOT protocol module
34   * @{
35   */ 
36
37 /** @defgroup MSC_BOT_Private_TypesDefinitions
38   * @{
39   */ 
40 /**
41   * @}
42   */ 
43
44
45 /** @defgroup MSC_BOT_Private_Defines
46   * @{
47   */ 
48
49 /**
50   * @}
51   */ 
52
53
54 /** @defgroup MSC_BOT_Private_Macros
55   * @{
56   */ 
57 /**
58   * @}
59   */ 
60
61
62 /** @defgroup MSC_BOT_Private_Variables
63   * @{
64   */ 
65 uint16_t             MSC_BOT_DataLen;
66 uint8_t              MSC_BOT_State;
67 uint8_t              MSC_BOT_Status;
68
69 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
70   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
71     #pragma data_alignment=4   
72   #endif
73 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
74 __ALIGN_BEGIN uint8_t              MSC_BOT_Data[MSC_MEDIA_PACKET] __ALIGN_END ;
75
76 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
77   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
78     #pragma data_alignment=4   
79   #endif
80 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
81 __ALIGN_BEGIN MSC_BOT_CBW_TypeDef  MSC_BOT_cbw __ALIGN_END ;
82
83 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
84   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
85     #pragma data_alignment=4   
86   #endif
87 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
88 __ALIGN_BEGIN MSC_BOT_CSW_TypeDef  MSC_BOT_csw __ALIGN_END ;
89 /**
90   * @}
91   */ 
92
93
94 /** @defgroup MSC_BOT_Private_FunctionPrototypes
95   * @{
96   */ 
97 static void MSC_BOT_CBW_Decode (USB_OTG_CORE_HANDLE  *pdev);
98
99 static void MSC_BOT_SendData (USB_OTG_CORE_HANDLE  *pdev, 
100                               uint8_t* pbuf, 
101                               uint16_t len);
102
103 static void MSC_BOT_Abort(USB_OTG_CORE_HANDLE  *pdev);
104 /**
105   * @}
106   */ 
107
108
109 /** @defgroup MSC_BOT_Private_Functions
110   * @{
111   */ 
112
113
114
115 /**
116 * @brief  MSC_BOT_Init
117 *         Initialize the BOT Process
118 * @param  pdev: device instance
119 * @retval None
120 */
121 void MSC_BOT_Init (USB_OTG_CORE_HANDLE  *pdev)
122 {
123   MSC_BOT_State = BOT_IDLE;
124   MSC_BOT_Status = BOT_STATE_NORMAL;
125   USBD_STORAGE_fops->Init(0);
126   
127   DCD_EP_Flush(pdev, MSC_OUT_EP);
128   DCD_EP_Flush(pdev, MSC_IN_EP);
129   /* Prapare EP to Receive First BOT Cmd */
130   DCD_EP_PrepareRx (pdev,
131                     MSC_OUT_EP,
132                     (uint8_t *)&MSC_BOT_cbw,
133                     BOT_CBW_LENGTH);    
134 }
135
136 /**
137 * @brief  MSC_BOT_Reset
138 *         Reset the BOT Machine
139 * @param  pdev: device instance
140 * @retval  None
141 */
142 void MSC_BOT_Reset (USB_OTG_CORE_HANDLE  *pdev)
143 {
144   MSC_BOT_State = BOT_IDLE;
145   MSC_BOT_Status = BOT_STATE_RECOVERY;
146   /* Prapare EP to Receive First BOT Cmd */
147   DCD_EP_PrepareRx (pdev,
148                     MSC_OUT_EP,
149                     (uint8_t *)&MSC_BOT_cbw,
150                     BOT_CBW_LENGTH);    
151 }
152
153 /**
154 * @brief  MSC_BOT_DeInit
155 *         Uninitialize the BOT Machine
156 * @param  pdev: device instance
157 * @retval None
158 */
159 void MSC_BOT_DeInit (USB_OTG_CORE_HANDLE  *pdev)
160 {
161   MSC_BOT_State = BOT_IDLE;
162 }
163
164 /**
165 * @brief  MSC_BOT_DataIn
166 *         Handle BOT IN data stage
167 * @param  pdev: device instance
168 * @param  epnum: endpoint index
169 * @retval None
170 */
171 void MSC_BOT_DataIn (USB_OTG_CORE_HANDLE  *pdev, 
172                      uint8_t epnum)
173 {
174   
175   switch (MSC_BOT_State)
176   {
177   case BOT_DATA_IN:
178     if(SCSI_ProcessCmd(pdev,
179                         MSC_BOT_cbw.bLUN,
180                         &MSC_BOT_cbw.CB[0]) < 0)
181     {
182       MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED);
183     }
184     break;
185     
186   case BOT_SEND_DATA:
187   case BOT_LAST_DATA_IN:
188     MSC_BOT_SendCSW (pdev, CSW_CMD_PASSED);
189     
190     break;
191     
192   default:
193     break;
194   }
195 }
196 /**
197 * @brief  MSC_BOT_DataOut
198 *         Proccess MSC OUT data
199 * @param  pdev: device instance
200 * @param  epnum: endpoint index
201 * @retval None
202 */
203 void MSC_BOT_DataOut (USB_OTG_CORE_HANDLE  *pdev, 
204                       uint8_t epnum)
205 {
206   switch (MSC_BOT_State)
207   {
208   case BOT_IDLE:
209     MSC_BOT_CBW_Decode(pdev);
210     break;
211     
212   case BOT_DATA_OUT:
213     
214     if(SCSI_ProcessCmd(pdev,
215                         MSC_BOT_cbw.bLUN,
216                         &MSC_BOT_cbw.CB[0]) < 0)
217     {
218       MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED);
219     }
220
221     break;
222     
223   default:
224     break;
225   }
226   
227 }
228
229 /**
230 * @brief  MSC_BOT_CBW_Decode
231 *         Decode the CBW command and set the BOT state machine accordingtly  
232 * @param  pdev: device instance
233 * @retval None
234 */
235 static void  MSC_BOT_CBW_Decode (USB_OTG_CORE_HANDLE  *pdev)
236 {
237
238   MSC_BOT_csw.dTag = MSC_BOT_cbw.dTag;
239   MSC_BOT_csw.dDataResidue = MSC_BOT_cbw.dDataLength;
240   
241   if ((USBD_GetRxCount (pdev ,MSC_OUT_EP) != BOT_CBW_LENGTH) ||
242       (MSC_BOT_cbw.dSignature != BOT_CBW_SIGNATURE)||
243         (MSC_BOT_cbw.bLUN > 1) || 
244           (MSC_BOT_cbw.bCBLength < 1) || 
245             (MSC_BOT_cbw.bCBLength > 16))
246   {
247     
248     SCSI_SenseCode(MSC_BOT_cbw.bLUN, 
249                    ILLEGAL_REQUEST, 
250                    INVALID_CDB);
251      MSC_BOT_Status = BOT_STATE_ERROR;   
252     MSC_BOT_Abort(pdev);
253  
254   }
255   else
256   {
257     if(SCSI_ProcessCmd(pdev,
258                               MSC_BOT_cbw.bLUN,
259                               &MSC_BOT_cbw.CB[0]) < 0)
260     {
261       MSC_BOT_Abort(pdev);
262     }
263     /*Burst xfer handled internally*/
264     else if ((MSC_BOT_State != BOT_DATA_IN) && 
265              (MSC_BOT_State != BOT_DATA_OUT) &&
266              (MSC_BOT_State != BOT_LAST_DATA_IN)) 
267     {
268       if (MSC_BOT_DataLen > 0)
269       {
270         MSC_BOT_SendData(pdev,
271                          MSC_BOT_Data, 
272                          MSC_BOT_DataLen);
273       }
274       else if (MSC_BOT_DataLen == 0) 
275       {
276         MSC_BOT_SendCSW (pdev,
277                          CSW_CMD_PASSED);
278       }
279     }
280   }
281 }
282
283 /**
284 * @brief  MSC_BOT_SendData
285 *         Send the requested data
286 * @param  pdev: device instance
287 * @param  buf: pointer to data buffer
288 * @param  len: Data Length
289 * @retval None
290 */
291 static void  MSC_BOT_SendData(USB_OTG_CORE_HANDLE  *pdev,
292                               uint8_t* buf, 
293                               uint16_t len)
294 {
295   
296   len = MIN (MSC_BOT_cbw.dDataLength, len);
297   MSC_BOT_csw.dDataResidue -= len;
298   MSC_BOT_csw.bStatus = CSW_CMD_PASSED;
299   MSC_BOT_State = BOT_SEND_DATA;
300   
301   DCD_EP_Tx (pdev, MSC_IN_EP, buf, len);  
302 }
303
304 /**
305 * @brief  MSC_BOT_SendCSW
306 *         Send the Command Status Wrapper
307 * @param  pdev: device instance
308 * @param  status : CSW status
309 * @retval None
310 */
311 void  MSC_BOT_SendCSW (USB_OTG_CORE_HANDLE  *pdev,
312                               uint8_t CSW_Status)
313 {
314   MSC_BOT_csw.dSignature = BOT_CSW_SIGNATURE;
315   MSC_BOT_csw.bStatus = CSW_Status;
316   MSC_BOT_State = BOT_IDLE;
317   
318   DCD_EP_Tx (pdev, 
319              MSC_IN_EP, 
320              (uint8_t *)&MSC_BOT_csw, 
321              BOT_CSW_LENGTH);
322   
323   /* Prapare EP to Receive next Cmd */
324   DCD_EP_PrepareRx (pdev,
325                     MSC_OUT_EP,
326                     (uint8_t *)&MSC_BOT_cbw, 
327                     BOT_CBW_LENGTH);  
328   
329 }
330
331 /**
332 * @brief  MSC_BOT_Abort
333 *         Abort the current transfer
334 * @param  pdev: device instance
335 * @retval status
336 */
337
338 static void  MSC_BOT_Abort (USB_OTG_CORE_HANDLE  *pdev)
339 {
340
341   if ((MSC_BOT_cbw.bmFlags == 0) && 
342       (MSC_BOT_cbw.dDataLength != 0) &&
343       (MSC_BOT_Status == BOT_STATE_NORMAL) )
344   {
345     DCD_EP_Stall(pdev, MSC_OUT_EP );
346   }
347   DCD_EP_Stall(pdev, MSC_IN_EP);
348   
349   if(MSC_BOT_Status == BOT_STATE_ERROR)
350   {
351     DCD_EP_PrepareRx (pdev,
352                       MSC_OUT_EP,
353                       (uint8_t *)&MSC_BOT_cbw, 
354                       BOT_CBW_LENGTH);    
355   }
356 }
357
358 /**
359 * @brief  MSC_BOT_CplClrFeature
360 *         Complete the clear feature request
361 * @param  pdev: device instance
362 * @param  epnum: endpoint index
363 * @retval None
364 */
365
366 void  MSC_BOT_CplClrFeature (USB_OTG_CORE_HANDLE  *pdev, uint8_t epnum)
367 {
368   if(MSC_BOT_Status == BOT_STATE_ERROR )/* Bad CBW Signature */
369   {
370     DCD_EP_Stall(pdev, MSC_IN_EP);
371     MSC_BOT_Status = BOT_STATE_NORMAL;    
372   }
373   else if(((epnum & 0x80) == 0x80) && ( MSC_BOT_Status != BOT_STATE_RECOVERY))
374   {
375     MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED);
376   }
377   
378 }
379 /**
380   * @}
381   */ 
382
383
384 /**
385   * @}
386   */ 
387
388
389 /**
390   * @}
391   */ 
392
393 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/