STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
usbh_msc_bot.c
Go to the documentation of this file.
1 
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbh_msc_bot.h"
30 #include "usbh_msc.h"
31 
84 static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir);
85 static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost);
110 {
111 
113  USB_REQ_RECIPIENT_INTERFACE;
114 
116  phost->Control.setup.b.wValue.w = 0;
117  phost->Control.setup.b.wIndex.w = 0;
118  phost->Control.setup.b.wLength.w = 0;
119 
120  return USBH_CtlReq(phost, 0 , 0 );
121 }
122 
131 {
133  USB_REQ_RECIPIENT_INTERFACE;
134 
136  phost->Control.setup.b.wValue.w = 0;
137  phost->Control.setup.b.wIndex.w = 0;
138  phost->Control.setup.b.wLength.w = 1;
139 
140  return USBH_CtlReq(phost, Maxlun , 1 );
141 }
142 
143 
144 
152 {
153 
154  MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
155 
156  MSC_Handle->hbot.cbw.field.Signature = BOT_CBW_SIGNATURE;
157  MSC_Handle->hbot.cbw.field.Tag = BOT_CBW_TAG;
158  MSC_Handle->hbot.state = BOT_SEND_CBW;
159  MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;
160 
161  return USBH_OK;
162 }
163 
164 
165 
174 {
175  USBH_StatusTypeDef status = USBH_BUSY;
176  USBH_StatusTypeDef error = USBH_BUSY;
178  USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
179  MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
180  uint8_t toggle = 0;
181 
182  switch (MSC_Handle->hbot.state)
183  {
184  case BOT_SEND_CBW:
185  MSC_Handle->hbot.cbw.field.LUN = lun;
186  MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT;
187  USBH_BulkSendData (phost,
188  MSC_Handle->hbot.cbw.data,
190  MSC_Handle->OutPipe,
191  1);
192 
193  break;
194 
195  case BOT_SEND_CBW_WAIT:
196 
197  URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);
198 
199  if(URB_Status == USBH_URB_DONE)
200  {
201  if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 )
202  {
203  /* If there is Data Transfer Stage */
204  if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H)
205  {
206  /* Data Direction is IN */
207  MSC_Handle->hbot.state = BOT_DATA_IN;
208  }
209  else
210  {
211  /* Data Direction is OUT */
212  MSC_Handle->hbot.state = BOT_DATA_OUT;
213  }
214  }
215 
216  else
217  {/* If there is NO Data Transfer Stage */
218  MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
219  }
220 #if (USBH_USE_OS == 1)
221  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
222 #endif
223 
224  }
225  else if(URB_Status == USBH_URB_NOTREADY)
226  {
227  /* Re-send CBW */
228  MSC_Handle->hbot.state = BOT_SEND_CBW;
229 #if (USBH_USE_OS == 1)
230  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
231 #endif
232  }
233  else if(URB_Status == USBH_URB_STALL)
234  {
235  MSC_Handle->hbot.state = BOT_ERROR_OUT;
236 #if (USBH_USE_OS == 1)
237  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
238 #endif
239  }
240  break;
241 
242  case BOT_DATA_IN:
243  /* Send first packet */
244  USBH_BulkReceiveData (phost,
245  MSC_Handle->hbot.pbuf,
246  MSC_Handle->InEpSize ,
247  MSC_Handle->InPipe);
248 
249  MSC_Handle->hbot.state = BOT_DATA_IN_WAIT;
250 
251  break;
252 
253  case BOT_DATA_IN_WAIT:
254 
255  URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);
256 
257  if(URB_Status == USBH_URB_DONE)
258  {
259  /* Adjust Data pointer and data length */
260  if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize)
261  {
262  MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize;
263  MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize;
264  }
265  else
266  {
267  MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
268  }
269 
270  /* More Data To be Received */
271  if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
272  {
273  /* Send next packet */
274  USBH_BulkReceiveData (phost,
275  MSC_Handle->hbot.pbuf,
276  MSC_Handle->InEpSize ,
277  MSC_Handle->InPipe);
278 
279  }
280  else
281  {
282  /* If value was 0, and successful transfer, then change the state */
283  MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
284 #if (USBH_USE_OS == 1)
285  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
286 #endif
287  }
288  }
289  else if(URB_Status == USBH_URB_STALL)
290  {
291  /* This is Data IN Stage STALL Condition */
292  MSC_Handle->hbot.state = BOT_ERROR_IN;
293 
294  /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
295  6.7.2 Host expects to receive data from the device
296  3. On a STALL condition receiving data, then:
297  The host shall accept the data received.
298  The host shall clear the Bulk-In pipe.
299  4. The host shall attempt to receive a CSW.*/
300 
301 #if (USBH_USE_OS == 1)
302  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
303 #endif
304  }
305  break;
306 
307  case BOT_DATA_OUT:
308 
309  USBH_BulkSendData (phost,
310  MSC_Handle->hbot.pbuf,
311  MSC_Handle->OutEpSize ,
312  MSC_Handle->OutPipe,
313  1);
314 
315 
316  MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT;
317  break;
318 
319  case BOT_DATA_OUT_WAIT:
320  URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);
321 
322  if(URB_Status == USBH_URB_DONE)
323  {
324  /* Adjust Data pointer and data length */
325  if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize)
326  {
327  MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize;
328  MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize;
329  }
330  else
331  {
332  MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
333  }
334 
335  /* More Data To be Sent */
336  if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
337  {
338  USBH_BulkSendData (phost,
339  MSC_Handle->hbot.pbuf,
340  MSC_Handle->OutEpSize ,
341  MSC_Handle->OutPipe,
342  1);
343  }
344  else
345  {
346  /* If value was 0, and successful transfer, then change the state */
347  MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
348  }
349 #if (USBH_USE_OS == 1)
350  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
351 #endif
352  }
353 
354  else if(URB_Status == USBH_URB_NOTREADY)
355  {
356  /* Resend same data */
357  MSC_Handle->hbot.state = BOT_DATA_OUT;
358 #if (USBH_USE_OS == 1)
359  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
360 #endif
361  }
362 
363  else if(URB_Status == USBH_URB_STALL)
364  {
365  MSC_Handle->hbot.state = BOT_ERROR_OUT;
366 
367  /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
368  6.7.3 Ho - Host expects to send data to the device
369  3. On a STALL condition sending data, then:
370  " The host shall clear the Bulk-Out pipe.
371  4. The host shall attempt to receive a CSW.
372  */
373 #if (USBH_USE_OS == 1)
374  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
375 #endif
376  }
377  break;
378 
379  case BOT_RECEIVE_CSW:
380 
381  USBH_BulkReceiveData (phost,
382  MSC_Handle->hbot.csw.data,
383  BOT_CSW_LENGTH ,
384  MSC_Handle->InPipe);
385 
386  MSC_Handle->hbot.state = BOT_RECEIVE_CSW_WAIT;
387  break;
388 
390 
391  URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);
392 
393  /* Decode CSW */
394  if(URB_Status == USBH_URB_DONE)
395  {
396  MSC_Handle->hbot.state = BOT_SEND_CBW;
397  MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;
398  CSW_Status = USBH_MSC_DecodeCSW(phost);
399 
400  if(CSW_Status == BOT_CSW_CMD_PASSED)
401  {
402  status = USBH_OK;
403  }
404  else
405  {
406  status = USBH_FAIL;
407  }
408 #if (USBH_USE_OS == 1)
409  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
410 #endif
411  }
412  else if(URB_Status == USBH_URB_STALL)
413  {
414  MSC_Handle->hbot.state = BOT_ERROR_IN;
415 #if (USBH_USE_OS == 1)
416  osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
417 #endif
418  }
419  break;
420 
421  case BOT_ERROR_IN:
422  error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN);
423 
424  if (error == USBH_OK)
425  {
426  MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
427  }
428  else if (error == USBH_UNRECOVERED_ERROR)
429  {
430  /* This means that there is a STALL Error limit, Do Reset Recovery */
431  MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
432  }
433  break;
434 
435  case BOT_ERROR_OUT:
436  error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT);
437 
438  if ( error == USBH_OK)
439  {
440 
441  toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe);
442  USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle);
443  USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0);
444  MSC_Handle->hbot.state = BOT_ERROR_IN;
445  }
446  else if (error == USBH_UNRECOVERED_ERROR)
447  {
448  MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
449  }
450  break;
451 
452 
453  case BOT_UNRECOVERED_ERROR:
454  status = USBH_MSC_BOT_REQ_Reset(phost);
455  if ( status == USBH_OK)
456  {
457  MSC_Handle->hbot.state = BOT_SEND_CBW;
458  }
459  break;
460 
461  default:
462  break;
463  }
464  return status;
465 }
466 
475 static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir)
476 {
477  USBH_StatusTypeDef status = USBH_FAIL;
478  MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
479 
480  switch (dir)
481  {
482  case BOT_DIR_IN :
483  /* send ClrFeture on Bulk IN endpoint */
484  status = USBH_ClrFeature(phost, MSC_Handle->InEp);
485 
486  break;
487 
488  case BOT_DIR_OUT :
489  /*send ClrFeature on Bulk OUT endpoint */
490  status = USBH_ClrFeature(phost, MSC_Handle->OutEp);
491  break;
492 
493  default:
494  break;
495  }
496  return status;
497 }
498 
514 static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost)
515 {
516  MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
518 
519  /*Checking if the transfer length is different than 13*/
520  if(USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != BOT_CSW_LENGTH)
521  {
522  /*(4) Hi > Dn (Host expects to receive data from the device,
523  Device intends to transfer no data)
524  (5) Hi > Di (Host expects to receive data from the device,
525  Device intends to send data to the host)
526  (9) Ho > Dn (Host expects to send data to the device,
527  Device intends to transfer no data)
528  (11) Ho > Do (Host expects to send data to the device,
529  Device intends to receive data from the host)*/
530 
531 
532  status = BOT_CSW_PHASE_ERROR;
533  }
534  else
535  { /* CSW length is Correct */
536 
537  /* Check validity of the CSW Signature and CSWStatus */
538  if(MSC_Handle->hbot.csw.field.Signature == BOT_CSW_SIGNATURE)
539  {/* Check Condition 1. dCSWSignature is equal to 53425355h */
540 
541  if(MSC_Handle->hbot.csw.field.Tag == MSC_Handle->hbot.cbw.field.Tag)
542  {
543  /* Check Condition 3. dCSWTag matches the dCBWTag from the
544  corresponding CBW */
545 
546  if(MSC_Handle->hbot.csw.field.Status == 0)
547  {
548  /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
549 
550  Hn Host expects no data transfers
551  Hi Host expects to receive data from the device
552  Ho Host expects to send data to the device
553 
554  Dn Device intends to transfer no data
555  Di Device intends to send data to the host
556  Do Device intends to receive data from the host
557 
558  Section 6.7
559  (1) Hn = Dn (Host expects no data transfers,
560  Device intends to transfer no data)
561  (6) Hi = Di (Host expects to receive data from the device,
562  Device intends to send data to the host)
563  (12) Ho = Do (Host expects to send data to the device,
564  Device intends to receive data from the host)
565 
566  */
567 
568  status = BOT_CSW_CMD_PASSED;
569  }
570  else if(MSC_Handle->hbot.csw.field.Status == 1)
571  {
572  status = BOT_CSW_CMD_FAILED;
573  }
574 
575  else if(MSC_Handle->hbot.csw.field.Status == 2)
576  {
577  /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
578  Section 6.7
579  (2) Hn < Di ( Host expects no data transfers,
580  Device intends to send data to the host)
581  (3) Hn < Do ( Host expects no data transfers,
582  Device intends to receive data from the host)
583  (7) Hi < Di ( Host expects to receive data from the device,
584  Device intends to send data to the host)
585  (8) Hi <> Do ( Host expects to receive data from the device,
586  Device intends to receive data from the host)
587  (10) Ho <> Di (Host expects to send data to the device,
588  Di Device intends to send data to the host)
589  (13) Ho < Do (Host expects to send data to the device,
590  Device intends to receive data from the host)
591  */
592 
593  status = BOT_CSW_PHASE_ERROR;
594  }
595  } /* CSW Tag Matching is Checked */
596  } /* CSW Signature Correct Checking */
597  else
598  {
599  /* If the CSW Signature is not valid, We sall return the Phase Error to
600  Upper Layers for Reset Recovery */
601 
602  status = BOT_CSW_PHASE_ERROR;
603  }
604  } /* CSW Length Check*/
605 
606  return status;
607 }
608 
609 
630 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
631 
632 
633 
#define USB_H2D
Definition: usbh_def.h:108
USB_Setup_TypeDef setup
Definition: usbh_def.h:412
BOT_CBWTypeDef cbw
Definition: usbh_msc_bot.h:137
Header file for usbh_msc_bot.c.
#define USB_D2H
Definition: usbh_def.h:109
uint16_t_uint8_t wValue
Definition: usbh_def.h:223
#define BOT_CBW_TAG
Definition: usbh_msc_bot.h:155
#define BOT_CBW_LENGTH
Definition: usbh_msc_bot.h:157
#define BOT_DIR_IN
Definition: usbh_msc_bot.h:165
USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t hc_num)
USBH_BulkReceiveData Receives IN bulk packet from device.
Definition: usbh_ioreq.c:218
uint8_t OutEp
Definition: usbh_msc.h:121
#define USB_REQ_BOT_RESET
Definition: usbh_msc.h:148
uint8_t InEp
Definition: usbh_msc.h:122
#define USB_REQ_DIR_MASK
Definition: usbh_def.h:107
USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, uint8_t ep_num)
USBH_ClrFeature This request is used to clear or disable a specific feature.
Definition: usbh_ctlreq.c:308
USBH_StatusTypeDef USBH_BulkSendData(USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t hc_num, uint8_t do_ping)
USBH_BulkSendData Sends the Bulk Packet to the device.
Definition: usbh_ioreq.c:186
uint16_t_uint8_t wLength
Definition: usbh_def.h:225
uint32_t USBH_LL_GetLastXferSize(USBH_HandleTypeDef *phost, uint8_t)
USBH_LL_GetLastXferSize Return the last transferred packet size.
#define BOT_DIR_OUT
Definition: usbh_msc_bot.h:166
This file contains all the prototypes for the usbh_msc.c.
uint8_t USBH_LL_GetToggle(USBH_HandleTypeDef *phost, uint8_t)
USBH_LL_GetToggle Return the current toggle of a pipe.
USBH_CtrlTypeDef Control
Definition: usbh_def.h:455
USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost)
USBH_MSC_BOT_Init The function Initializes the BOT protocol.
Definition: usbh_msc_bot.c:151
uint8_t data[13]
Definition: usbh_msc_bot.h:127
USBH_StatusTypeDef USBH_CtlReq(USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length)
USBH_CtlReq USBH_CtlReq sends a control request and provide the status after completion of the reques...
Definition: usbh_ctlreq.c:531
BOT_StateTypeDef state
Definition: usbh_msc_bot.h:134
#define USB_REQ_TYPE_CLASS
Definition: usbd_def.h:74
#define BOT_CBW_SIGNATURE
Definition: usbh_msc_bot.h:154
BOT_CMDStateTypeDef cmd_state
Definition: usbh_msc_bot.h:136
USBH_URBStateTypeDef
Definition: usbh_def.h:384
uint16_t w
Definition: usbh_def.h:204
uint8_t data[31]
Definition: usbh_msc_bot.h:114
USBH_StatusTypeDef USBH_LL_SetToggle(USBH_HandleTypeDef *phost, uint8_t, uint8_t)
USBH_LL_SetToggle Set toggle for a pipe.
USBH_URBStateTypeDef USBH_LL_GetURBState(USBH_HandleTypeDef *phost, uint8_t)
USBH_LL_GetURBState Get a URB state from the low level driver.
#define BOT_CSW_SIGNATURE
Definition: usbh_msc_bot.h:156
BOT_HandleTypeDef hbot
Definition: usbh_msc.h:129
#define USB_REQ_GET_MAX_LUN
Definition: usbh_msc.h:149
#define BOT_CSW_LENGTH
Definition: usbh_msc_bot.h:158
USBH_StatusTypeDef
Definition: usbh_def.h:302
USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun)
USBH_MSC_BOT_REQ_GetMaxLUN The function the MSC BOT GetMaxLUN request.
Definition: usbh_msc_bot.c:130
struct BOT_CSWTypeDef::__CSW field
struct BOT_CBWTypeDef::__CBW field
osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec)
Put a Message to a Queue.
Definition: cmsis_os.c:951
USBH_StatusTypeDef USBH_MSC_BOT_Process(USBH_HandleTypeDef *phost, uint8_t lun)
USBH_MSC_BOT_Process The function handle the BOT protocol.
Definition: usbh_msc_bot.c:173
USBH_ClassTypeDef * pActiveClass
Definition: usbh_def.h:458
uint16_t InEpSize
Definition: usbh_msc.h:124
uint16_t OutEpSize
Definition: usbh_msc.h:123
USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost)
USBH_MSC_BOT_REQ_Reset The function the MSC BOT Reset request.
Definition: usbh_msc_bot.c:109
uint16_t_uint8_t wIndex
Definition: usbh_def.h:224
struct _USB_Setup::_SetupPkt_Struc b
uint8_t InPipe
Definition: usbh_msc.h:119
uint8_t OutPipe
Definition: usbh_msc.h:120
BOT_CSWTypeDef csw
Definition: usbh_msc_bot.h:139
BOT_CSWStatusTypeDef
Definition: usbh_msc_bot.h:78