Browse code

Add source code of the firmware for the IO Board

Pawel Jablonski authored on 05/06/2023 17:01:27
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1203 @@
1
+/**
2
+  ******************************************************************************
3
+  * @file    usbd_msc_scsi.c
4
+  * @author  MCD Application Team
5
+  * @brief   This file provides all the USBD SCSI layer functions.
6
+  ******************************************************************************
7
+  * @attention
8
+  *
9
+  * Copyright (c) 2015 STMicroelectronics.
10
+  * All rights reserved.
11
+  *
12
+  * This software is licensed under terms that can be found in the LICENSE file
13
+  * in the root directory of this software component.
14
+  * If no LICENSE file comes with this software, it is provided AS-IS.
15
+  *
16
+  ******************************************************************************
17
+  */
18
+
19
+/* BSPDependencies
20
+- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
21
+- "stm32xxxxx_{eval}{discovery}_io.c"
22
+- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c"
23
+EndBSPDependencies */
24
+
25
+/* Includes ------------------------------------------------------------------*/
26
+#include "usbd_msc_bot.h"
27
+#include "usbd_msc_scsi.h"
28
+#include "usbd_msc.h"
29
+#include "usbd_msc_data.h"
30
+
31
+
32
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
33
+  * @{
34
+  */
35
+
36
+
37
+/** @defgroup MSC_SCSI
38
+  * @brief Mass storage SCSI layer module
39
+  * @{
40
+  */
41
+
42
+/** @defgroup MSC_SCSI_Private_TypesDefinitions
43
+  * @{
44
+  */
45
+/**
46
+  * @}
47
+  */
48
+
49
+
50
+/** @defgroup MSC_SCSI_Private_Defines
51
+  * @{
52
+  */
53
+
54
+/**
55
+  * @}
56
+  */
57
+
58
+
59
+/** @defgroup MSC_SCSI_Private_Macros
60
+  * @{
61
+  */
62
+/**
63
+  * @}
64
+  */
65
+
66
+
67
+/** @defgroup MSC_SCSI_Private_Variables
68
+  * @{
69
+  */
70
+extern uint8_t MSCInEpAdd;
71
+extern uint8_t MSCOutEpAdd;
72
+/**
73
+  * @}
74
+  */
75
+
76
+
77
+/** @defgroup MSC_SCSI_Private_FunctionPrototypes
78
+  * @{
79
+  */
80
+static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
81
+static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
82
+static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
83
+static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
84
+static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
85
+static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
86
+static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
87
+static int8_t SCSI_AllowPreventRemovable(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
88
+static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
89
+static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
90
+static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
91
+static int8_t SCSI_Write12(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_Read12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
94
+static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
95
+static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun,
96
+                                     uint32_t blk_offset, uint32_t blk_nbr);
97
+
98
+static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun);
99
+static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun);
100
+
101
+static int8_t SCSI_UpdateBotData(USBD_MSC_BOT_HandleTypeDef *hmsc,
102
+                                 uint8_t *pBuff, uint16_t length);
103
+/**
104
+  * @}
105
+  */
106
+
107
+
108
+/** @defgroup MSC_SCSI_Private_Functions
109
+  * @{
110
+  */
111
+
112
+
113
+/**
114
+  * @brief  SCSI_ProcessCmd
115
+  *         Process SCSI commands
116
+  * @param  pdev: device instance
117
+  * @param  lun: Logical unit number
118
+  * @param  params: Command parameters
119
+  * @retval status
120
+  */
121
+int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd)
122
+{
123
+  int8_t ret;
124
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
125
+
126
+  if (hmsc == NULL)
127
+  {
128
+    return -1;
129
+  }
130
+
131
+  switch (cmd[0])
132
+  {
133
+    case SCSI_TEST_UNIT_READY:
134
+      ret = SCSI_TestUnitReady(pdev, lun, cmd);
135
+      break;
136
+
137
+    case SCSI_REQUEST_SENSE:
138
+      ret = SCSI_RequestSense(pdev, lun, cmd);
139
+      break;
140
+
141
+    case SCSI_INQUIRY:
142
+      ret = SCSI_Inquiry(pdev, lun, cmd);
143
+      break;
144
+
145
+    case SCSI_START_STOP_UNIT:
146
+      ret = SCSI_StartStopUnit(pdev, lun, cmd);
147
+      break;
148
+
149
+    case SCSI_ALLOW_MEDIUM_REMOVAL:
150
+      ret = SCSI_AllowPreventRemovable(pdev, lun, cmd);
151
+      break;
152
+
153
+    case SCSI_MODE_SENSE6:
154
+      ret = SCSI_ModeSense6(pdev, lun, cmd);
155
+      break;
156
+
157
+    case SCSI_MODE_SENSE10:
158
+      ret = SCSI_ModeSense10(pdev, lun, cmd);
159
+      break;
160
+
161
+    case SCSI_READ_FORMAT_CAPACITIES:
162
+      ret = SCSI_ReadFormatCapacity(pdev, lun, cmd);
163
+      break;
164
+
165
+    case SCSI_READ_CAPACITY10:
166
+      ret = SCSI_ReadCapacity10(pdev, lun, cmd);
167
+      break;
168
+
169
+    case SCSI_READ_CAPACITY16:
170
+      ret = SCSI_ReadCapacity16(pdev, lun, cmd);
171
+      break;
172
+
173
+    case SCSI_READ10:
174
+      ret = SCSI_Read10(pdev, lun, cmd);
175
+      break;
176
+
177
+    case SCSI_READ12:
178
+      ret = SCSI_Read12(pdev, lun, cmd);
179
+      break;
180
+
181
+    case SCSI_WRITE10:
182
+      ret = SCSI_Write10(pdev, lun, cmd);
183
+      break;
184
+
185
+    case SCSI_WRITE12:
186
+      ret = SCSI_Write12(pdev, lun, cmd);
187
+      break;
188
+
189
+    case SCSI_VERIFY10:
190
+      ret = SCSI_Verify10(pdev, lun, cmd);
191
+      break;
192
+
193
+    default:
194
+      SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB);
195
+      hmsc->bot_status = USBD_BOT_STATUS_ERROR;
196
+      ret = -1;
197
+      break;
198
+  }
199
+
200
+  return ret;
201
+}
202
+
203
+
204
+/**
205
+  * @brief  SCSI_TestUnitReady
206
+  *         Process SCSI Test Unit Ready Command
207
+  * @param  lun: Logical unit number
208
+  * @param  params: Command parameters
209
+  * @retval status
210
+  */
211
+static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
212
+{
213
+  UNUSED(params);
214
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
215
+
216
+  if (hmsc == NULL)
217
+  {
218
+    return -1;
219
+  }
220
+
221
+  /* case 9 : Hi > D0 */
222
+  if (hmsc->cbw.dDataLength != 0U)
223
+  {
224
+    SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
225
+
226
+    return -1;
227
+  }
228
+
229
+  if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)
230
+  {
231
+    SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
232
+    hmsc->bot_state = USBD_BOT_NO_DATA;
233
+    return -1;
234
+  }
235
+
236
+  if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0)
237
+  {
238
+    SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
239
+    hmsc->bot_state = USBD_BOT_NO_DATA;
240
+
241
+    return -1;
242
+  }
243
+  hmsc->bot_data_length = 0U;
244
+
245
+  return 0;
246
+}
247
+
248
+
249
+/**
250
+  * @brief  SCSI_Inquiry
251
+  *         Process Inquiry command
252
+  * @param  lun: Logical unit number
253
+  * @param  params: Command parameters
254
+  * @retval status
255
+  */
256
+static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
257
+{
258
+  uint8_t *pPage;
259
+  uint16_t len;
260
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
261
+
262
+  if (hmsc == NULL)
263
+  {
264
+    return -1;
265
+  }
266
+
267
+  if (hmsc->cbw.dDataLength == 0U)
268
+  {
269
+    SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
270
+    return -1;
271
+  }
272
+
273
+  if ((params[1] & 0x01U) != 0U) /* Evpd is set */
274
+  {
275
+    if (params[2] == 0U) /* Request for Supported Vital Product Data Pages*/
276
+    {
277
+      (void)SCSI_UpdateBotData(hmsc, MSC_Page00_Inquiry_Data, LENGTH_INQUIRY_PAGE00);
278
+    }
279
+    else if (params[2] == 0x80U) /* Request for VPD page 0x80 Unit Serial Number */
280
+    {
281
+      (void)SCSI_UpdateBotData(hmsc, MSC_Page80_Inquiry_Data, LENGTH_INQUIRY_PAGE80);
282
+    }
283
+    else /* Request Not supported */
284
+    {
285
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST,
286
+                     INVALID_FIELED_IN_COMMAND);
287
+
288
+      return -1;
289
+    }
290
+  }
291
+  else
292
+  {
293
+
294
+    pPage = (uint8_t *) & ((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN];
295
+    len = (uint16_t)pPage[4] + 5U;
296
+
297
+    if (params[4] <= len)
298
+    {
299
+      len = params[4];
300
+    }
301
+
302
+    (void)SCSI_UpdateBotData(hmsc, pPage, len);
303
+  }
304
+
305
+  return 0;
306
+}
307
+
308
+
309
+/**
310
+  * @brief  SCSI_ReadCapacity10
311
+  *         Process Read Capacity 10 command
312
+  * @param  lun: Logical unit number
313
+  * @param  params: Command parameters
314
+  * @retval status
315
+  */
316
+static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
317
+{
318
+  UNUSED(params);
319
+  int8_t ret;
320
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
321
+
322
+  if (hmsc == NULL)
323
+  {
324
+    return -1;
325
+  }
326
+
327
+  ret = ((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size);
328
+
329
+  if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED))
330
+  {
331
+    SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
332
+    return -1;
333
+  }
334
+
335
+  hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 24);
336
+  hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 16);
337
+  hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >>  8);
338
+  hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1U);
339
+
340
+  hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >>  24);
341
+  hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >>  16);
342
+  hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >>  8);
343
+  hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size);
344
+
345
+  hmsc->bot_data_length = 8U;
346
+
347
+  return 0;
348
+
349
+}
350
+
351
+
352
+/**
353
+  * @brief  SCSI_ReadCapacity16
354
+  *         Process Read Capacity 16 command
355
+  * @param  lun: Logical unit number
356
+  * @param  params: Command parameters
357
+  * @retval status
358
+  */
359
+static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
360
+{
361
+  UNUSED(params);
362
+  uint8_t idx;
363
+  int8_t ret;
364
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
365
+
366
+  if (hmsc == NULL)
367
+  {
368
+    return -1;
369
+  }
370
+
371
+  ret = ((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size);
372
+
373
+  if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED))
374
+  {
375
+    SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
376
+    return -1;
377
+  }
378
+
379
+  hmsc->bot_data_length = ((uint32_t)params[10] << 24) |
380
+                          ((uint32_t)params[11] << 16) |
381
+                          ((uint32_t)params[12] <<  8) |
382
+                          (uint32_t)params[13];
383
+
384
+  for (idx = 0U; idx < hmsc->bot_data_length; idx++)
385
+  {
386
+    hmsc->bot_data[idx] = 0U;
387
+  }
388
+
389
+  hmsc->bot_data[4] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 24);
390
+  hmsc->bot_data[5] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 16);
391
+  hmsc->bot_data[6] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >>  8);
392
+  hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_nbr - 1U);
393
+
394
+  hmsc->bot_data[8] = (uint8_t)(hmsc->scsi_blk_size >>  24);
395
+  hmsc->bot_data[9] = (uint8_t)(hmsc->scsi_blk_size >>  16);
396
+  hmsc->bot_data[10] = (uint8_t)(hmsc->scsi_blk_size >>  8);
397
+  hmsc->bot_data[11] = (uint8_t)(hmsc->scsi_blk_size);
398
+
399
+  hmsc->bot_data_length = ((uint32_t)params[10] << 24) |
400
+                          ((uint32_t)params[11] << 16) |
401
+                          ((uint32_t)params[12] <<  8) |
402
+                          (uint32_t)params[13];
403
+
404
+  return 0;
405
+}
406
+
407
+
408
+/**
409
+  * @brief  SCSI_ReadFormatCapacity
410
+  *         Process Read Format Capacity command
411
+  * @param  lun: Logical unit number
412
+  * @param  params: Command parameters
413
+  * @retval status
414
+  */
415
+static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
416
+{
417
+  UNUSED(params);
418
+  uint16_t blk_size;
419
+  uint32_t blk_nbr;
420
+  uint16_t i;
421
+  int8_t ret;
422
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
423
+
424
+  if (hmsc == NULL)
425
+  {
426
+    return -1;
427
+  }
428
+
429
+  ret = ((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetCapacity(lun, &blk_nbr, &blk_size);
430
+
431
+  if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED))
432
+  {
433
+    SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
434
+    return -1;
435
+  }
436
+
437
+  for (i = 0U; i < 12U ; i++)
438
+  {
439
+    hmsc->bot_data[i] = 0U;
440
+  }
441
+
442
+  hmsc->bot_data[3] = 0x08U;
443
+  hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1U) >> 24);
444
+  hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1U) >> 16);
445
+  hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1U) >>  8);
446
+  hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1U);
447
+
448
+  hmsc->bot_data[8] = 0x02U;
449
+  hmsc->bot_data[9] = (uint8_t)(blk_size >>  16);
450
+  hmsc->bot_data[10] = (uint8_t)(blk_size >>  8);
451
+  hmsc->bot_data[11] = (uint8_t)(blk_size);
452
+
453
+  hmsc->bot_data_length = 12U;
454
+
455
+  return 0;
456
+}
457
+
458
+
459
+/**
460
+  * @brief  SCSI_ModeSense6
461
+  *         Process Mode Sense6 command
462
+  * @param  lun: Logical unit number
463
+  * @param  params: Command parameters
464
+  * @retval status
465
+  */
466
+static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
467
+{
468
+  UNUSED(lun);
469
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
470
+  uint16_t len = MODE_SENSE6_LEN;
471
+
472
+  if (hmsc == NULL)
473
+  {
474
+    return -1;
475
+  }
476
+
477
+  if (params[4] <= len)
478
+  {
479
+    len = params[4];
480
+  }
481
+
482
+  (void)SCSI_UpdateBotData(hmsc, MSC_Mode_Sense6_data, len);
483
+
484
+  return 0;
485
+}
486
+
487
+
488
+/**
489
+  * @brief  SCSI_ModeSense10
490
+  *         Process Mode Sense10 command
491
+  * @param  lun: Logical unit number
492
+  * @param  params: Command parameters
493
+  * @retval status
494
+  */
495
+static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
496
+{
497
+  UNUSED(lun);
498
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
499
+  uint16_t len = MODE_SENSE10_LEN;
500
+
501
+  if (hmsc == NULL)
502
+  {
503
+    return -1;
504
+  }
505
+
506
+  if (params[8] <= len)
507
+  {
508
+    len = params[8];
509
+  }
510
+
511
+  (void)SCSI_UpdateBotData(hmsc, MSC_Mode_Sense10_data, len);
512
+
513
+  return 0;
514
+}
515
+
516
+
517
+/**
518
+  * @brief  SCSI_RequestSense
519
+  *         Process Request Sense command
520
+  * @param  lun: Logical unit number
521
+  * @param  params: Command parameters
522
+  * @retval status
523
+  */
524
+static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
525
+{
526
+  UNUSED(lun);
527
+  uint8_t i;
528
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
529
+
530
+  if (hmsc == NULL)
531
+  {
532
+    return -1;
533
+  }
534
+
535
+  if (hmsc->cbw.dDataLength == 0U)
536
+  {
537
+    SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
538
+    return -1;
539
+  }
540
+
541
+  for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++)
542
+  {
543
+    hmsc->bot_data[i] = 0U;
544
+  }
545
+
546
+  hmsc->bot_data[0] = 0x70U;
547
+  hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6U;
548
+
549
+  if ((hmsc->scsi_sense_head != hmsc->scsi_sense_tail))
550
+  {
551
+    hmsc->bot_data[2] = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;
552
+    hmsc->bot_data[12] = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;
553
+    hmsc->bot_data[13] = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;
554
+    hmsc->scsi_sense_head++;
555
+
556
+    if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
557
+    {
558
+      hmsc->scsi_sense_head = 0U;
559
+    }
560
+  }
561
+
562
+  hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;
563
+
564
+  if (params[4] <= REQUEST_SENSE_DATA_LEN)
565
+  {
566
+    hmsc->bot_data_length = params[4];
567
+  }
568
+
569
+  return 0;
570
+}
571
+
572
+
573
+/**
574
+  * @brief  SCSI_SenseCode
575
+  *         Load the last error code in the error list
576
+  * @param  lun: Logical unit number
577
+  * @param  sKey: Sense Key
578
+  * @param  ASC: Additional Sense Code
579
+  * @retval none
580
+
581
+  */
582
+void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
583
+{
584
+  UNUSED(lun);
585
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
586
+
587
+  if (hmsc == NULL)
588
+  {
589
+    return;
590
+  }
591
+
592
+  hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;
593
+  hmsc->scsi_sense[hmsc->scsi_sense_tail].w.b.ASC = ASC;
594
+  hmsc->scsi_sense[hmsc->scsi_sense_tail].w.b.ASCQ = 0U;
595
+  hmsc->scsi_sense_tail++;
596
+
597
+  if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH)
598
+  {
599
+    hmsc->scsi_sense_tail = 0U;
600
+  }
601
+}
602
+
603
+
604
+/**
605
+  * @brief  SCSI_StartStopUnit
606
+  *         Process Start Stop Unit command
607
+  * @param  lun: Logical unit number
608
+  * @param  params: Command parameters
609
+  * @retval status
610
+  */
611
+static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
612
+{
613
+  UNUSED(lun);
614
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
615
+
616
+  if (hmsc == NULL)
617
+  {
618
+    return -1;
619
+  }
620
+
621
+  if ((hmsc->scsi_medium_state == SCSI_MEDIUM_LOCKED) && ((params[4] & 0x3U) == 2U))
622
+  {
623
+    SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
624
+
625
+    return -1;
626
+  }
627
+
628
+  if ((params[4] & 0x3U) == 0x1U) /* START=1 */
629
+  {
630
+    hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;
631
+  }
632
+  else if ((params[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
633
+  {
634
+    hmsc->scsi_medium_state = SCSI_MEDIUM_EJECTED;
635
+  }
636
+  else if ((params[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
637
+  {
638
+    hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;
639
+  }
640
+  else
641
+  {
642
+    /* .. */
643
+  }
644
+  hmsc->bot_data_length = 0U;
645
+
646
+  return 0;
647
+}
648
+
649
+
650
+/**
651
+  * @brief  SCSI_AllowPreventRemovable
652
+  *         Process Allow Prevent Removable medium command
653
+  * @param  lun: Logical unit number
654
+  * @param  params: Command parameters
655
+  * @retval status
656
+  */
657
+static int8_t SCSI_AllowPreventRemovable(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
658
+{
659
+  UNUSED(lun);
660
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
661
+
662
+  if (hmsc == NULL)
663
+  {
664
+    return -1;
665
+  }
666
+
667
+  if (params[4] == 0U)
668
+  {
669
+    hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;
670
+  }
671
+  else
672
+  {
673
+    hmsc->scsi_medium_state = SCSI_MEDIUM_LOCKED;
674
+  }
675
+
676
+  hmsc->bot_data_length = 0U;
677
+
678
+  return 0;
679
+}
680
+
681
+
682
+/**
683
+  * @brief  SCSI_Read10
684
+  *         Process Read10 command
685
+  * @param  lun: Logical unit number
686
+  * @param  params: Command parameters
687
+  * @retval status
688
+  */
689
+static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
690
+{
691
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
692
+
693
+  if (hmsc == NULL)
694
+  {
695
+    return -1;
696
+  }
697
+
698
+  if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
699
+  {
700
+    /* case 10 : Ho <> Di */
701
+    if ((hmsc->cbw.bmFlags & 0x80U) != 0x80U)
702
+    {
703
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
704
+      return -1;
705
+    }
706
+
707
+    if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)
708
+    {
709
+      SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
710
+
711
+      return -1;
712
+    }
713
+
714
+    if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0)
715
+    {
716
+      SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
717
+      return -1;
718
+    }
719
+
720
+    hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) |
721
+                          ((uint32_t)params[3] << 16) |
722
+                          ((uint32_t)params[4] <<  8) |
723
+                          (uint32_t)params[5];
724
+
725
+    hmsc->scsi_blk_len = ((uint32_t)params[7] <<  8) | (uint32_t)params[8];
726
+
727
+    if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,
728
+                               hmsc->scsi_blk_len) < 0)
729
+    {
730
+      return -1; /* error */
731
+    }
732
+
733
+    /* cases 4,5 : Hi <> Dn */
734
+    if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size))
735
+    {
736
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
737
+      return -1;
738
+    }
739
+
740
+    hmsc->bot_state = USBD_BOT_DATA_IN;
741
+  }
742
+  hmsc->bot_data_length = MSC_MEDIA_PACKET;
743
+
744
+  return SCSI_ProcessRead(pdev, lun);
745
+}
746
+
747
+
748
+/**
749
+  * @brief  SCSI_Read12
750
+  *         Process Read12 command
751
+  * @param  lun: Logical unit number
752
+  * @param  params: Command parameters
753
+  * @retval status
754
+  */
755
+static int8_t SCSI_Read12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
756
+{
757
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
758
+
759
+  if (hmsc == NULL)
760
+  {
761
+    return -1;
762
+  }
763
+
764
+  if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
765
+  {
766
+    /* case 10 : Ho <> Di */
767
+    if ((hmsc->cbw.bmFlags & 0x80U) != 0x80U)
768
+    {
769
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
770
+      return -1;
771
+    }
772
+
773
+    if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)
774
+    {
775
+      SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
776
+      return -1;
777
+    }
778
+
779
+    if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0)
780
+    {
781
+      SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
782
+      return -1;
783
+    }
784
+
785
+    hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) |
786
+                          ((uint32_t)params[3] << 16) |
787
+                          ((uint32_t)params[4] <<  8) |
788
+                          (uint32_t)params[5];
789
+
790
+    hmsc->scsi_blk_len = ((uint32_t)params[6] << 24) |
791
+                         ((uint32_t)params[7] << 16) |
792
+                         ((uint32_t)params[8] << 8) |
793
+                         (uint32_t)params[9];
794
+
795
+    if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,
796
+                               hmsc->scsi_blk_len) < 0)
797
+    {
798
+      return -1; /* error */
799
+    }
800
+
801
+    /* cases 4,5 : Hi <> Dn */
802
+    if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size))
803
+    {
804
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
805
+      return -1;
806
+    }
807
+
808
+    hmsc->bot_state = USBD_BOT_DATA_IN;
809
+  }
810
+  hmsc->bot_data_length = MSC_MEDIA_PACKET;
811
+
812
+  return SCSI_ProcessRead(pdev, lun);
813
+}
814
+
815
+
816
+/**
817
+  * @brief  SCSI_Write10
818
+  *         Process Write10 command
819
+  * @param  lun: Logical unit number
820
+  * @param  params: Command parameters
821
+  * @retval status
822
+  */
823
+static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
824
+{
825
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
826
+  uint32_t len;
827
+
828
+  if (hmsc == NULL)
829
+  {
830
+    return -1;
831
+  }
832
+
833
+#ifdef USE_USBD_COMPOSITE
834
+  /* Get the Endpoints addresses allocated for this class instance */
835
+  MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
836
+#endif /* USE_USBD_COMPOSITE */
837
+
838
+  if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
839
+  {
840
+    if (hmsc->cbw.dDataLength == 0U)
841
+    {
842
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
843
+      return -1;
844
+    }
845
+
846
+    /* case 8 : Hi <> Do */
847
+    if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U)
848
+    {
849
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
850
+      return -1;
851
+    }
852
+
853
+    /* Check whether Media is ready */
854
+    if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0)
855
+    {
856
+      SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
857
+      return -1;
858
+    }
859
+
860
+    /* Check If media is write-protected */
861
+    if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsWriteProtected(lun) != 0)
862
+    {
863
+      SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED);
864
+      return -1;
865
+    }
866
+
867
+    hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) |
868
+                          ((uint32_t)params[3] << 16) |
869
+                          ((uint32_t)params[4] << 8) |
870
+                          (uint32_t)params[5];
871
+
872
+    hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) |
873
+                         (uint32_t)params[8];
874
+
875
+    /* check if LBA address is in the right range */
876
+    if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,
877
+                               hmsc->scsi_blk_len) < 0)
878
+    {
879
+      return -1; /* error */
880
+    }
881
+
882
+    len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
883
+
884
+    /* cases 3,11,13 : Hn,Ho <> D0 */
885
+    if (hmsc->cbw.dDataLength != len)
886
+    {
887
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
888
+      return -1;
889
+    }
890
+
891
+    len = MIN(len, MSC_MEDIA_PACKET);
892
+
893
+    /* Prepare EP to receive first data packet */
894
+    hmsc->bot_state = USBD_BOT_DATA_OUT;
895
+    (void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, hmsc->bot_data, len);
896
+  }
897
+  else /* Write Process ongoing */
898
+  {
899
+    return SCSI_ProcessWrite(pdev, lun);
900
+  }
901
+
902
+  return 0;
903
+}
904
+
905
+
906
+/**
907
+  * @brief  SCSI_Write12
908
+  *         Process Write12 command
909
+  * @param  lun: Logical unit number
910
+  * @param  params: Command parameters
911
+  * @retval status
912
+  */
913
+static int8_t SCSI_Write12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
914
+{
915
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
916
+  uint32_t len;
917
+
918
+  if (hmsc == NULL)
919
+  {
920
+    return -1;
921
+  }
922
+#ifdef USE_USBD_COMPOSITE
923
+  /* Get the Endpoints addresses allocated for this class instance */
924
+  MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
925
+#endif /* USE_USBD_COMPOSITE */
926
+
927
+  if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
928
+  {
929
+    if (hmsc->cbw.dDataLength == 0U)
930
+    {
931
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
932
+      return -1;
933
+    }
934
+
935
+    /* case 8 : Hi <> Do */
936
+    if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U)
937
+    {
938
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
939
+      return -1;
940
+    }
941
+
942
+    /* Check whether Media is ready */
943
+    if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0)
944
+    {
945
+      SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
946
+      hmsc->bot_state = USBD_BOT_NO_DATA;
947
+      return -1;
948
+    }
949
+
950
+    /* Check If media is write-protected */
951
+    if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsWriteProtected(lun) != 0)
952
+    {
953
+      SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED);
954
+      hmsc->bot_state = USBD_BOT_NO_DATA;
955
+      return -1;
956
+    }
957
+
958
+    hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) |
959
+                          ((uint32_t)params[3] << 16) |
960
+                          ((uint32_t)params[4] << 8) |
961
+                          (uint32_t)params[5];
962
+
963
+    hmsc->scsi_blk_len = ((uint32_t)params[6] << 24) |
964
+                         ((uint32_t)params[7] << 16) |
965
+                         ((uint32_t)params[8] << 8) |
966
+                         (uint32_t)params[9];
967
+
968
+    /* check if LBA address is in the right range */
969
+    if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,
970
+                               hmsc->scsi_blk_len) < 0)
971
+    {
972
+      return -1; /* error */
973
+    }
974
+
975
+    len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
976
+
977
+    /* cases 3,11,13 : Hn,Ho <> D0 */
978
+    if (hmsc->cbw.dDataLength != len)
979
+    {
980
+      SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);
981
+      return -1;
982
+    }
983
+
984
+    len = MIN(len, MSC_MEDIA_PACKET);
985
+
986
+    /* Prepare EP to receive first data packet */
987
+    hmsc->bot_state = USBD_BOT_DATA_OUT;
988
+    (void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, hmsc->bot_data, len);
989
+  }
990
+  else /* Write Process ongoing */
991
+  {
992
+    return SCSI_ProcessWrite(pdev, lun);
993
+  }
994
+
995
+  return 0;
996
+}
997
+
998
+
999
+/**
1000
+  * @brief  SCSI_Verify10
1001
+  *         Process Verify10 command
1002
+  * @param  lun: Logical unit number
1003
+  * @param  params: Command parameters
1004
+  * @retval status
1005
+  */
1006
+static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
1007
+{
1008
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
1009
+
1010
+  if (hmsc == NULL)
1011
+  {
1012
+    return -1;
1013
+  }
1014
+
1015
+  if ((params[1] & 0x02U) == 0x02U)
1016
+  {
1017
+    SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
1018
+    return -1; /* Error, Verify Mode Not supported*/
1019
+  }
1020
+
1021
+  if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
1022
+  {
1023
+    return -1; /* error */
1024
+  }
1025
+
1026
+  hmsc->bot_data_length = 0U;
1027
+
1028
+  return 0;
1029
+}
1030
+
1031
+/**
1032
+  * @brief  SCSI_CheckAddressRange
1033
+  *         Check address range
1034
+  * @param  lun: Logical unit number
1035
+  * @param  blk_offset: first block address
1036
+  * @param  blk_nbr: number of block to be processed
1037
+  * @retval status
1038
+  */
1039
+static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun,
1040
+                                     uint32_t blk_offset, uint32_t blk_nbr)
1041
+{
1042
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
1043
+
1044
+  if (hmsc == NULL)
1045
+  {
1046
+    return -1;
1047
+  }
1048
+
1049
+  if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr)
1050
+  {
1051
+    SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE);
1052
+    return -1;
1053
+  }
1054
+
1055
+  return 0;
1056
+}
1057
+
1058
+/**
1059
+  * @brief  SCSI_ProcessRead
1060
+  *         Handle Read Process
1061
+  * @param  lun: Logical unit number
1062
+  * @retval status
1063
+  */
1064
+static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun)
1065
+{
1066
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
1067
+  uint32_t len;
1068
+
1069
+  if (hmsc == NULL)
1070
+  {
1071
+    return -1;
1072
+  }
1073
+
1074
+  len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
1075
+
1076
+#ifdef USE_USBD_COMPOSITE
1077
+  /* Get the Endpoints addresses allocated for this class instance */
1078
+  MSCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
1079
+#endif /* USE_USBD_COMPOSITE */
1080
+
1081
+  len = MIN(len, MSC_MEDIA_PACKET);
1082
+
1083
+  if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->Read(lun, hmsc->bot_data,
1084
+                                                                    hmsc->scsi_blk_addr,
1085
+                                                                    (len / hmsc->scsi_blk_size)) < 0)
1086
+  {
1087
+    SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR);
1088
+    return -1;
1089
+  }
1090
+
1091
+  (void)USBD_LL_Transmit(pdev, MSCInEpAdd, hmsc->bot_data, len);
1092
+
1093
+  hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);
1094
+  hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);
1095
+
1096
+  /* case 6 : Hi = Di */
1097
+  hmsc->csw.dDataResidue -= len;
1098
+
1099
+  if (hmsc->scsi_blk_len == 0U)
1100
+  {
1101
+    hmsc->bot_state = USBD_BOT_LAST_DATA_IN;
1102
+  }
1103
+
1104
+  return 0;
1105
+}
1106
+
1107
+/**
1108
+  * @brief  SCSI_ProcessWrite
1109
+  *         Handle Write Process
1110
+  * @param  lun: Logical unit number
1111
+  * @retval status
1112
+  */
1113
+static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun)
1114
+{
1115
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
1116
+  uint32_t len;
1117
+
1118
+  if (hmsc == NULL)
1119
+  {
1120
+    return -1;
1121
+  }
1122
+
1123
+  len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
1124
+
1125
+#ifdef USE_USBD_COMPOSITE
1126
+  /* Get the Endpoints addresses allocated for this class instance */
1127
+  MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
1128
+#endif /* USE_USBD_COMPOSITE */
1129
+
1130
+  len = MIN(len, MSC_MEDIA_PACKET);
1131
+
1132
+  if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->Write(lun, hmsc->bot_data,
1133
+                                                                     hmsc->scsi_blk_addr,
1134
+                                                                     (len / hmsc->scsi_blk_size)) < 0)
1135
+  {
1136
+    SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, WRITE_FAULT);
1137
+    return -1;
1138
+  }
1139
+
1140
+  hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);
1141
+  hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);
1142
+
1143
+  /* case 12 : Ho = Do */
1144
+  hmsc->csw.dDataResidue -= len;
1145
+
1146
+  if (hmsc->scsi_blk_len == 0U)
1147
+  {
1148
+    MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED);
1149
+  }
1150
+  else
1151
+  {
1152
+    len = MIN((hmsc->scsi_blk_len * hmsc->scsi_blk_size), MSC_MEDIA_PACKET);
1153
+
1154
+    /* Prepare EP to Receive next packet */
1155
+    (void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, hmsc->bot_data, len);
1156
+  }
1157
+
1158
+  return 0;
1159
+}
1160
+
1161
+
1162
+/**
1163
+  * @brief  SCSI_UpdateBotData
1164
+  *         fill the requested Data to transmit buffer
1165
+  * @param  hmsc handler
1166
+  * @param  pBuff: Data buffer
1167
+  * @param  length: Data length
1168
+  * @retval status
1169
+  */
1170
+static int8_t SCSI_UpdateBotData(USBD_MSC_BOT_HandleTypeDef *hmsc,
1171
+                                 uint8_t *pBuff, uint16_t length)
1172
+{
1173
+  uint16_t len = length;
1174
+
1175
+  if (hmsc == NULL)
1176
+  {
1177
+    return -1;
1178
+  }
1179
+
1180
+  hmsc->bot_data_length = len;
1181
+
1182
+  while (len != 0U)
1183
+  {
1184
+    len--;
1185
+    hmsc->bot_data[len] = pBuff[len];
1186
+  }
1187
+
1188
+  return 0;
1189
+}
1190
+/**
1191
+  * @}
1192
+  */
1193
+
1194
+
1195
+/**
1196
+  * @}
1197
+  */
1198
+
1199
+
1200
+/**
1201
+  * @}
1202
+  */
1203
+