STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
usbd_msc_scsi.c
Go to the documentation of this file.
1 
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbd_msc_bot.h"
30 #include "usbd_msc_scsi.h"
31 #include "usbd_msc.h"
32 #include "usbd_msc_data.h"
33 
34 
35 
83 static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
84 static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
85 static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
86 static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
87 static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
88 static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
89 static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
90 static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
91 static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
92 static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
93 static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
94 static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev,
95  uint8_t lun ,
96  uint32_t blk_offset ,
97  uint16_t blk_nbr);
98 static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev,
99  uint8_t lun);
100 
101 static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev,
102  uint8_t lun);
122  uint8_t lun,
123  uint8_t *params)
124 {
125 
126  switch (params[0])
127  {
129  return SCSI_TestUnitReady(pdev, lun, params);
130 
131  case SCSI_REQUEST_SENSE:
132  return SCSI_RequestSense (pdev, lun, params);
133  case SCSI_INQUIRY:
134  return SCSI_Inquiry(pdev, lun, params);
135 
137  return SCSI_StartStopUnit(pdev, lun, params);
138 
140  return SCSI_StartStopUnit(pdev, lun, params);
141 
142  case SCSI_MODE_SENSE6:
143  return SCSI_ModeSense6 (pdev, lun, params);
144 
145  case SCSI_MODE_SENSE10:
146  return SCSI_ModeSense10 (pdev, lun, params);
147 
149  return SCSI_ReadFormatCapacity(pdev, lun, params);
150 
152  return SCSI_ReadCapacity10(pdev, lun, params);
153 
154  case SCSI_READ10:
155  return SCSI_Read10(pdev, lun, params);
156 
157  case SCSI_WRITE10:
158  return SCSI_Write10(pdev, lun, params);
159 
160  case SCSI_VERIFY10:
161  return SCSI_Verify10(pdev, lun, params);
162 
163  default:
164  SCSI_SenseCode(pdev,
165  lun,
167  INVALID_CDB);
168  return -1;
169  }
170 }
171 
172 
180 static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
181 {
183 
184  /* case 9 : Hi > D0 */
185  if (hmsc->cbw.dDataLength != 0)
186  {
187  SCSI_SenseCode(pdev,
188  hmsc->cbw.bLUN,
190  INVALID_CDB);
191  return -1;
192  }
193 
194  if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
195  {
196  SCSI_SenseCode(pdev,
197  lun,
198  NOT_READY,
200 
201  hmsc->bot_state = USBD_BOT_NO_DATA;
202  return -1;
203  }
204  hmsc->bot_data_length = 0;
205  return 0;
206 }
207 
215 static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
216 {
217  uint8_t* pPage;
218  uint16_t len;
220 
221  if (params[1] & 0x01)/*Evpd is set*/
222  {
223  pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
224  len = LENGTH_INQUIRY_PAGE00;
225  }
226  else
227  {
228 
229  pPage = (uint8_t *)&((USBD_StorageTypeDef *)pdev->pUserData)->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN];
230  len = pPage[4] + 5;
231 
232  if (params[4] <= len)
233  {
234  len = params[4];
235  }
236  }
237  hmsc->bot_data_length = len;
238 
239  while (len)
240  {
241  len--;
242  hmsc->bot_data[len] = pPage[len];
243  }
244  return 0;
245 }
246 
254 static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
255 {
257 
258  if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0)
259  {
260  SCSI_SenseCode(pdev,
261  lun,
262  NOT_READY,
264  return -1;
265  }
266  else
267  {
268 
269  hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24);
270  hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16);
271  hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 8);
272  hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1);
273 
274  hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24);
275  hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16);
276  hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8);
277  hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size);
278 
279  hmsc->bot_data_length = 8;
280  return 0;
281  }
282 }
290 static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
291 {
293 
294  uint16_t blk_size;
295  uint32_t blk_nbr;
296  uint16_t i;
297 
298  for(i=0 ; i < 12 ; i++)
299  {
300  hmsc->bot_data[i] = 0;
301  }
302 
303  if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blk_nbr, &blk_size) != 0)
304  {
305  SCSI_SenseCode(pdev,
306  lun,
307  NOT_READY,
309  return -1;
310  }
311  else
312  {
313  hmsc->bot_data[3] = 0x08;
314  hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24);
315  hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16);
316  hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >> 8);
317  hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1);
318 
319  hmsc->bot_data[8] = 0x02;
320  hmsc->bot_data[9] = (uint8_t)(blk_size >> 16);
321  hmsc->bot_data[10] = (uint8_t)(blk_size >> 8);
322  hmsc->bot_data[11] = (uint8_t)(blk_size);
323 
324  hmsc->bot_data_length = 12;
325  return 0;
326  }
327 }
335 static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
336 {
338  uint16_t len = 8 ;
339  hmsc->bot_data_length = len;
340 
341  while (len)
342  {
343  len--;
344  hmsc->bot_data[len] = MSC_Mode_Sense6_data[len];
345  }
346  return 0;
347 }
348 
356 static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
357 {
358  uint16_t len = 8;
360 
361  hmsc->bot_data_length = len;
362 
363  while (len)
364  {
365  len--;
366  hmsc->bot_data[len] = MSC_Mode_Sense10_data[len];
367  }
368  return 0;
369 }
370 
379 static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
380 {
381  uint8_t i;
383 
384  for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
385  {
386  hmsc->bot_data[i] = 0;
387  }
388 
389  hmsc->bot_data[0] = 0x70;
390  hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6;
391 
392  if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) {
393 
394  hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;
395  hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;
396  hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;
397  hmsc->scsi_sense_head++;
398 
399  if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
400  {
401  hmsc->scsi_sense_head = 0;
402  }
403  }
405 
406  if (params[4] <= REQUEST_SENSE_DATA_LEN)
407  {
408  hmsc->bot_data_length = params[4];
409  }
410  return 0;
411 }
412 
422 void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
423 {
425 
426  hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;
427  hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8;
428  hmsc->scsi_sense_tail++;
430  {
431  hmsc->scsi_sense_tail = 0;
432  }
433 }
441 static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
442 {
444  hmsc->bot_data_length = 0;
445  return 0;
446 }
447 
455 static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
456 {
458 
459  if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
460  {
461 
462  /* case 10 : Ho <> Di */
463 
464  if ((hmsc->cbw.bmFlags & 0x80) != 0x80)
465  {
466  SCSI_SenseCode(pdev,
467  hmsc->cbw.bLUN,
469  INVALID_CDB);
470  return -1;
471  }
472 
473  if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
474  {
475  SCSI_SenseCode(pdev,
476  lun,
477  NOT_READY,
479  return -1;
480  }
481 
482  hmsc->scsi_blk_addr = (params[2] << 24) | \
483  (params[3] << 16) | \
484  (params[4] << 8) | \
485  params[5];
486 
487  hmsc->scsi_blk_len = (params[7] << 8) | \
488  params[8];
489 
490 
491 
492  if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
493  {
494  return -1; /* error */
495  }
496 
497  hmsc->bot_state = USBD_BOT_DATA_IN;
498  hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
499  hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
500 
501  /* cases 4,5 : Hi <> Dn */
502  if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
503  {
504  SCSI_SenseCode(pdev,
505  hmsc->cbw.bLUN,
507  INVALID_CDB);
508  return -1;
509  }
510  }
512 
513  return SCSI_ProcessRead(pdev, lun);
514 }
515 
524 static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
525 {
527 
528  if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
529  {
530 
531  /* case 8 : Hi <> Do */
532 
533  if ((hmsc->cbw.bmFlags & 0x80) == 0x80)
534  {
535  SCSI_SenseCode(pdev,
536  hmsc->cbw.bLUN,
538  INVALID_CDB);
539  return -1;
540  }
541 
542  /* Check whether Media is ready */
543  if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
544  {
545  SCSI_SenseCode(pdev,
546  lun,
547  NOT_READY,
549  return -1;
550  }
551 
552  /* Check If media is write-protected */
553  if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
554  {
555  SCSI_SenseCode(pdev,
556  lun,
557  NOT_READY,
559  return -1;
560  }
561 
562 
563  hmsc->scsi_blk_addr = (params[2] << 24) | \
564  (params[3] << 16) | \
565  (params[4] << 8) | \
566  params[5];
567  hmsc->scsi_blk_len = (params[7] << 8) | \
568  params[8];
569 
570  /* check if LBA address is in the right range */
571  if(SCSI_CheckAddressRange(pdev,
572  lun,
573  hmsc->scsi_blk_addr,
574  hmsc->scsi_blk_len) < 0)
575  {
576  return -1; /* error */
577  }
578 
579  hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
580  hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
581 
582  /* cases 3,11,13 : Hn,Ho <> D0 */
583  if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
584  {
585  SCSI_SenseCode(pdev,
586  hmsc->cbw.bLUN,
588  INVALID_CDB);
589  return -1;
590  }
591 
592  /* Prepare EP to receive first data packet */
593  hmsc->bot_state = USBD_BOT_DATA_OUT;
596  hmsc->bot_data,
597  MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
598  }
599  else /* Write Process ongoing */
600  {
601  return SCSI_ProcessWrite(pdev, lun);
602  }
603  return 0;
604 }
605 
606 
615 static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
616 {
618 
619  if ((params[1]& 0x02) == 0x02)
620  {
621  SCSI_SenseCode (pdev,
622  lun,
625  return -1; /* Error, Verify Mode Not supported*/
626  }
627 
628  if(SCSI_CheckAddressRange(pdev,
629  lun,
630  hmsc->scsi_blk_addr,
631  hmsc->scsi_blk_len) < 0)
632  {
633  return -1; /* error */
634  }
635  hmsc->bot_data_length = 0;
636  return 0;
637 }
638 
647 static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
648 {
650 
651  if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr )
652  {
653  SCSI_SenseCode(pdev,
654  lun,
657  return -1;
658  }
659  return 0;
660 }
661 
668 static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
669 {
671  uint32_t len;
672 
673  len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
674 
675  if( ((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun ,
676  hmsc->bot_data,
677  hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
678  len / hmsc->scsi_blk_size) < 0)
679  {
680 
681  SCSI_SenseCode(pdev,
682  lun,
685  return -1;
686  }
687 
688 
689  USBD_LL_Transmit (pdev,
691  hmsc->bot_data,
692  len);
693 
694 
695  hmsc->scsi_blk_addr += len;
696  hmsc->scsi_blk_len -= len;
697 
698  /* case 6 : Hi = Di */
699  hmsc->csw.dDataResidue -= len;
700 
701  if (hmsc->scsi_blk_len == 0)
702  {
704  }
705  return 0;
706 }
707 
715 static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
716 {
717  uint32_t len;
719 
720  len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
721 
722  if(((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun ,
723  hmsc->bot_data,
724  hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
725  len / hmsc->scsi_blk_size) < 0)
726  {
727  SCSI_SenseCode(pdev,
728  lun,
730  WRITE_FAULT);
731  return -1;
732  }
733 
734 
735  hmsc->scsi_blk_addr += len;
736  hmsc->scsi_blk_len -= len;
737 
738  /* case 12 : Ho = Do */
739  hmsc->csw.dDataResidue -= len;
740 
741  if (hmsc->scsi_blk_len == 0)
742  {
744  }
745  else
746  {
747  /* Prepare EP to Receive next packet */
750  hmsc->bot_data,
751  MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
752  }
753 
754  return 0;
755 }
770 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
uint8_t bot_data[MSC_MEDIA_PACKET]
Definition: usbd_msc.h:93
#define USBD_BOT_NO_DATA
Definition: usbd_msc_bot.h:57
#define HARDWARE_ERROR
Definition: usbd_msc_scsi.h:89
#define SCSI_WRITE10
Definition: usbd_msc_scsi.h:74
#define WRITE_FAULT
const uint8_t MSC_Page00_Inquiry_Data[]
Definition: usbd_msc_data.c:72
#define SCSI_VERIFY10
Definition: usbd_msc_scsi.h:78
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size)
Transmits data over an endpoint.
Definition: usbd_conf.c:574
#define NOT_READY
Definition: usbd_msc_scsi.h:87
#define ILLEGAL_REQUEST
Definition: usbd_msc_scsi.h:90
#define MEDIUM_NOT_PRESENT
#define USBD_BOT_IDLE
Definition: usbd_msc_bot.h:52
#define SCSI_READ_CAPACITY10
Definition: usbd_msc_scsi.h:67
USBD_SCSI_SenseTypeDef scsi_sense[SENSE_LIST_DEEPTH]
Definition: usbd_msc.h:97
if(LCD_Lock==DISABLE)
Definition: lcd_log.c:249
const uint8_t MSC_Mode_Sense10_data[]
Definition: usbd_msc_data.c:93
#define LENGTH_INQUIRY_PAGE00
Definition: usbd_msc_data.h:53
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size)
Prepares an endpoint for reception.
Definition: usbd_conf.c:591
#define USBD_BOT_LAST_DATA_IN
Definition: usbd_msc_bot.h:55
#define UNRECOVERED_READ_ERROR
#define SCSI_INQUIRY
Definition: usbd_msc_scsi.h:56
const uint8_t MSC_Mode_Sense6_data[]
Definition: usbd_msc_data.c:82
Header for the usbd_msc.c file.
#define SCSI_READ10
Definition: usbd_msc_scsi.h:63
#define SCSI_START_STOP_UNIT
Definition: usbd_msc_scsi.h:71
#define SCSI_REQUEST_SENSE
Definition: usbd_msc_scsi.h:70
#define MSC_MEDIA_PACKET
Definition: usbd_conf.h:69
#define INVALID_FIELED_IN_COMMAND
#define STANDARD_INQUIRY_DATA_LEN
Header for the usbd_msc_data.c file.
struct _SENSE_ITEM::@35::_ASCs b
int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
SCSI_ProcessCmd Process SCSI commands.
#define SCSI_READ_FORMAT_CAPACITIES
Definition: usbd_msc_scsi.h:83
union _SENSE_ITEM::@35 w
#define SCSI_MODE_SENSE6
Definition: usbd_msc_scsi.h:59
#define SCSI_ALLOW_MEDIUM_REMOVAL
Definition: usbd_msc_scsi.h:61
Header for the usbd_msc_scsi.c file.
#define SENSE_LIST_DEEPTH
Definition: usbd_msc_scsi.h:52
#define USBD_BOT_DATA_IN
Definition: usbd_msc_bot.h:54
#define USBD_BOT_DATA_OUT
Definition: usbd_msc_bot.h:53
USBD_MSC_BOT_CBWTypeDef cbw
Definition: usbd_msc.h:94
#define REQUEST_SENSE_DATA_LEN
#define SCSI_TEST_UNIT_READY
Definition: usbd_msc_scsi.h:72
void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev, uint8_t CSW_Status)
MSC_BOT_SendCSW Send the Command Status Wrapper.
Definition: usbd_msc_bot.c:320
#define WRITE_PROTECTED
#define USBD_CSW_CMD_PASSED
Definition: usbd_msc_bot.h:66
USBD_MSC_BOT_CSWTypeDef csw
Definition: usbd_msc.h:95
#define ADDRESS_OUT_OF_RANGE
#define SCSI_MODE_SENSE10
Definition: usbd_msc_scsi.h:60
Header for the usbd_msc_bot.c file.
#define MSC_EPIN_ADDR
Definition: usbd_msc.h:62
#define INVALID_CDB
void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
SCSI_SenseCode Load the last error code in the error list.
#define MIN(a, b)
Definition: usbd_def.h:265
#define MSC_EPOUT_ADDR
Definition: usbd_msc.h:63