F1 and F3 HAL / LL libraries
[betaflight.git] / lib / main / STM32F3 / Middlewares / ST / STM32_USB_Device_Library / Class / MSC / Src / usbd_msc_scsi.c
blob5d4d252169389c8965ef97f90798cad771d6fdca
1 /**
2 ******************************************************************************
3 * @file usbd_msc_scsi.c
4 * @author MCD Application Team
5 * @version V2.4.2
6 * @date 11-December-2015
7 * @brief This file provides all the USBD SCSI layer functions.
8 ******************************************************************************
9 * @attention
11 * <h2><center>&copy; 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 ******************************************************************************
26 */
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"
36 /** @addtogroup STM32_USB_DEVICE_LIBRARY
37 * @{
41 /** @defgroup MSC_SCSI
42 * @brief Mass storage SCSI layer module
43 * @{
44 */
46 /** @defgroup MSC_SCSI_Private_TypesDefinitions
47 * @{
48 */
49 /**
50 * @}
51 */
54 /** @defgroup MSC_SCSI_Private_Defines
55 * @{
56 */
58 /**
59 * @}
60 */
63 /** @defgroup MSC_SCSI_Private_Macros
64 * @{
65 */
66 /**
67 * @}
68 */
71 /** @defgroup MSC_SCSI_Private_Variables
72 * @{
73 */
75 /**
76 * @}
77 */
80 /** @defgroup MSC_SCSI_Private_FunctionPrototypes
81 * @{
82 */
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);
101 static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev,
102 uint8_t lun);
104 * @}
108 /** @defgroup MSC_SCSI_Private_Functions
109 * @{
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
121 int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
122 uint8_t lun,
123 uint8_t *params)
126 switch (params[0])
128 case SCSI_TEST_UNIT_READY:
129 return SCSI_TestUnitReady(pdev, lun, params);
131 case SCSI_REQUEST_SENSE:
132 return SCSI_RequestSense (pdev, lun, params);
133 case SCSI_INQUIRY:
134 return SCSI_Inquiry(pdev, lun, params);
136 case SCSI_START_STOP_UNIT:
137 return SCSI_StartStopUnit(pdev, lun, params);
139 case SCSI_ALLOW_MEDIUM_REMOVAL:
140 return SCSI_StartStopUnit(pdev, lun, params);
142 case SCSI_MODE_SENSE6:
143 return SCSI_ModeSense6 (pdev, lun, params);
145 case SCSI_MODE_SENSE10:
146 return SCSI_ModeSense10 (pdev, lun, params);
148 case SCSI_READ_FORMAT_CAPACITIES:
149 return SCSI_ReadFormatCapacity(pdev, lun, params);
151 case SCSI_READ_CAPACITY10:
152 return SCSI_ReadCapacity10(pdev, lun, params);
154 case SCSI_READ10:
155 return SCSI_Read10(pdev, lun, params);
157 case SCSI_WRITE10:
158 return SCSI_Write10(pdev, lun, params);
160 case SCSI_VERIFY10:
161 return SCSI_Verify10(pdev, lun, params);
163 default:
164 SCSI_SenseCode(pdev,
165 lun,
166 ILLEGAL_REQUEST,
167 INVALID_CDB);
168 return -1;
174 * @brief SCSI_TestUnitReady
175 * Process SCSI Test Unit Ready Command
176 * @param lun: Logical unit number
177 * @param params: Command parameters
178 * @retval status
180 static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
182 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
184 /* case 9 : Hi > D0 */
185 if (hmsc->cbw.dDataLength != 0)
187 SCSI_SenseCode(pdev,
188 hmsc->cbw.bLUN,
189 ILLEGAL_REQUEST,
190 INVALID_CDB);
191 return -1;
194 if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
196 SCSI_SenseCode(pdev,
197 lun,
198 NOT_READY,
199 MEDIUM_NOT_PRESENT);
201 hmsc->bot_state = USBD_BOT_NO_DATA;
202 return -1;
204 hmsc->bot_data_length = 0;
205 return 0;
209 * @brief SCSI_Inquiry
210 * Process Inquiry command
211 * @param lun: Logical unit number
212 * @param params: Command parameters
213 * @retval status
215 static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
217 uint8_t* pPage;
218 uint16_t len;
219 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
221 if (params[1] & 0x01)/*Evpd is set*/
223 pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
224 len = LENGTH_INQUIRY_PAGE00;
226 else
229 pPage = (uint8_t *)&((USBD_StorageTypeDef *)pdev->pUserData)->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN];
230 len = pPage[4] + 5;
232 if (params[4] <= len)
234 len = params[4];
237 hmsc->bot_data_length = len;
239 while (len)
241 len--;
242 hmsc->bot_data[len] = pPage[len];
244 return 0;
248 * @brief SCSI_ReadCapacity10
249 * Process Read Capacity 10 command
250 * @param lun: Logical unit number
251 * @param params: Command parameters
252 * @retval status
254 static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
256 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
258 if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0)
260 SCSI_SenseCode(pdev,
261 lun,
262 NOT_READY,
263 MEDIUM_NOT_PRESENT);
264 return -1;
266 else
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);
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);
279 hmsc->bot_data_length = 8;
280 return 0;
284 * @brief SCSI_ReadFormatCapacity
285 * Process Read Format Capacity command
286 * @param lun: Logical unit number
287 * @param params: Command parameters
288 * @retval status
290 static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
292 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
294 uint16_t blk_size;
295 uint32_t blk_nbr;
296 uint16_t i;
298 for(i=0 ; i < 12 ; i++)
300 hmsc->bot_data[i] = 0;
303 if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blk_nbr, &blk_size) != 0)
305 SCSI_SenseCode(pdev,
306 lun,
307 NOT_READY,
308 MEDIUM_NOT_PRESENT);
309 return -1;
311 else
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);
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);
324 hmsc->bot_data_length = 12;
325 return 0;
329 * @brief SCSI_ModeSense6
330 * Process Mode Sense6 command
331 * @param lun: Logical unit number
332 * @param params: Command parameters
333 * @retval status
335 static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
337 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
338 uint16_t len = 8 ;
339 hmsc->bot_data_length = len;
341 while (len)
343 len--;
344 hmsc->bot_data[len] = MSC_Mode_Sense6_data[len];
346 return 0;
350 * @brief SCSI_ModeSense10
351 * Process Mode Sense10 command
352 * @param lun: Logical unit number
353 * @param params: Command parameters
354 * @retval status
356 static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
358 uint16_t len = 8;
359 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
361 hmsc->bot_data_length = len;
363 while (len)
365 len--;
366 hmsc->bot_data[len] = MSC_Mode_Sense10_data[len];
368 return 0;
372 * @brief SCSI_RequestSense
373 * Process Request Sense command
374 * @param lun: Logical unit number
375 * @param params: Command parameters
376 * @retval status
379 static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
381 uint8_t i;
382 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
384 for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
386 hmsc->bot_data[i] = 0;
389 hmsc->bot_data[0] = 0x70;
390 hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6;
392 if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) {
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++;
399 if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
401 hmsc->scsi_sense_head = 0;
404 hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;
406 if (params[4] <= REQUEST_SENSE_DATA_LEN)
408 hmsc->bot_data_length = params[4];
410 return 0;
414 * @brief SCSI_SenseCode
415 * Load the last error code in the error list
416 * @param lun: Logical unit number
417 * @param sKey: Sense Key
418 * @param ASC: Additional Sense Key
419 * @retval none
422 void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
424 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
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++;
429 if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH)
431 hmsc->scsi_sense_tail = 0;
435 * @brief SCSI_StartStopUnit
436 * Process Start Stop Unit command
437 * @param lun: Logical unit number
438 * @param params: Command parameters
439 * @retval status
441 static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
443 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*) pdev->pClassData;
444 hmsc->bot_data_length = 0;
445 return 0;
449 * @brief SCSI_Read10
450 * Process Read10 command
451 * @param lun: Logical unit number
452 * @param params: Command parameters
453 * @retval status
455 static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
457 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*) pdev->pClassData;
459 if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
462 /* case 10 : Ho <> Di */
464 if ((hmsc->cbw.bmFlags & 0x80) != 0x80)
466 SCSI_SenseCode(pdev,
467 hmsc->cbw.bLUN,
468 ILLEGAL_REQUEST,
469 INVALID_CDB);
470 return -1;
473 if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
475 SCSI_SenseCode(pdev,
476 lun,
477 NOT_READY,
478 MEDIUM_NOT_PRESENT);
479 return -1;
482 hmsc->scsi_blk_addr = (params[2] << 24) | \
483 (params[3] << 16) | \
484 (params[4] << 8) | \
485 params[5];
487 hmsc->scsi_blk_len = (params[7] << 8) | \
488 params[8];
492 if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
494 return -1; /* error */
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;
501 /* cases 4,5 : Hi <> Dn */
502 if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
504 SCSI_SenseCode(pdev,
505 hmsc->cbw.bLUN,
506 ILLEGAL_REQUEST,
507 INVALID_CDB);
508 return -1;
511 hmsc->bot_data_length = MSC_MEDIA_PACKET;
513 return SCSI_ProcessRead(pdev, lun);
517 * @brief SCSI_Write10
518 * Process Write10 command
519 * @param lun: Logical unit number
520 * @param params: Command parameters
521 * @retval status
524 static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
526 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*) pdev->pClassData;
528 if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
531 /* case 8 : Hi <> Do */
533 if ((hmsc->cbw.bmFlags & 0x80) == 0x80)
535 SCSI_SenseCode(pdev,
536 hmsc->cbw.bLUN,
537 ILLEGAL_REQUEST,
538 INVALID_CDB);
539 return -1;
542 /* Check whether Media is ready */
543 if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
545 SCSI_SenseCode(pdev,
546 lun,
547 NOT_READY,
548 MEDIUM_NOT_PRESENT);
549 return -1;
552 /* Check If media is write-protected */
553 if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
555 SCSI_SenseCode(pdev,
556 lun,
557 NOT_READY,
558 WRITE_PROTECTED);
559 return -1;
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];
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)
576 return -1; /* error */
579 hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
580 hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
582 /* cases 3,11,13 : Hn,Ho <> D0 */
583 if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
585 SCSI_SenseCode(pdev,
586 hmsc->cbw.bLUN,
587 ILLEGAL_REQUEST,
588 INVALID_CDB);
589 return -1;
592 /* Prepare EP to receive first data packet */
593 hmsc->bot_state = USBD_BOT_DATA_OUT;
594 USBD_LL_PrepareReceive (pdev,
595 MSC_EPOUT_ADDR,
596 hmsc->bot_data,
597 MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
599 else /* Write Process ongoing */
601 return SCSI_ProcessWrite(pdev, lun);
603 return 0;
608 * @brief SCSI_Verify10
609 * Process Verify10 command
610 * @param lun: Logical unit number
611 * @param params: Command parameters
612 * @retval status
615 static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
617 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*) pdev->pClassData;
619 if ((params[1]& 0x02) == 0x02)
621 SCSI_SenseCode (pdev,
622 lun,
623 ILLEGAL_REQUEST,
624 INVALID_FIELED_IN_COMMAND);
625 return -1; /* Error, Verify Mode Not supported*/
628 if(SCSI_CheckAddressRange(pdev,
629 lun,
630 hmsc->scsi_blk_addr,
631 hmsc->scsi_blk_len) < 0)
633 return -1; /* error */
635 hmsc->bot_data_length = 0;
636 return 0;
640 * @brief SCSI_CheckAddressRange
641 * Check address range
642 * @param lun: Logical unit number
643 * @param blk_offset: first block address
644 * @param blk_nbr: number of block to be processed
645 * @retval status
647 static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
649 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*) pdev->pClassData;
651 if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr )
653 SCSI_SenseCode(pdev,
654 lun,
655 ILLEGAL_REQUEST,
656 ADDRESS_OUT_OF_RANGE);
657 return -1;
659 return 0;
663 * @brief SCSI_ProcessRead
664 * Handle Read Process
665 * @param lun: Logical unit number
666 * @retval status
668 static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
670 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*)pdev->pClassData;
671 uint32_t len;
673 len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
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)
681 SCSI_SenseCode(pdev,
682 lun,
683 HARDWARE_ERROR,
684 UNRECOVERED_READ_ERROR);
685 return -1;
689 USBD_LL_Transmit (pdev,
690 MSC_EPIN_ADDR,
691 hmsc->bot_data,
692 len);
695 hmsc->scsi_blk_addr += len;
696 hmsc->scsi_blk_len -= len;
698 /* case 6 : Hi = Di */
699 hmsc->csw.dDataResidue -= len;
701 if (hmsc->scsi_blk_len == 0)
703 hmsc->bot_state = USBD_BOT_LAST_DATA_IN;
705 return 0;
709 * @brief SCSI_ProcessWrite
710 * Handle Write Process
711 * @param lun: Logical unit number
712 * @retval status
715 static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
717 uint32_t len;
718 USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*) pdev->pClassData;
720 len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
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)
727 SCSI_SenseCode(pdev,
728 lun,
729 HARDWARE_ERROR,
730 WRITE_FAULT);
731 return -1;
735 hmsc->scsi_blk_addr += len;
736 hmsc->scsi_blk_len -= len;
738 /* case 12 : Ho = Do */
739 hmsc->csw.dDataResidue -= len;
741 if (hmsc->scsi_blk_len == 0)
743 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
745 else
747 /* Prepare EP to Receive next packet */
748 USBD_LL_PrepareReceive (pdev,
749 MSC_EPOUT_ADDR,
750 hmsc->bot_data,
751 MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
754 return 0;
757 * @}
762 * @}
767 * @}
770 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/