00001
00015 #include "em_usb.h"
00016 #include "em_cmu.h"
00017 #include "em_gpio.h"
00018 #include "msdbot.h"
00019 #include "msdscsi.h"
00020 #include "msdd.h"
00021 #include "msddmedia.h"
00022
00023
00058
00059 #define MSD_DIR_DATA_OUT 0
00060 #define MSD_DIR_DATA_IN 1
00061 #define MSD_MAX_BURST 32768U
00062
00063
00066 typedef enum
00067 {
00068 MSDD_IDLE = 0,
00069 MSDD_WAITFOR_CBW = 1,
00070 MSDD_WAITFOR_RECOVERY = 2,
00071 MSDD_SEND_CSW = 3,
00072 MSDD_WAIT_FOR_INUNSTALLED = 4,
00073 MSDD_STALL_IN = 5,
00074 MSDD_ACCESS_INDIRECT = 6,
00075 MSDD_WRITE_INDIRECT = 7,
00076 MSDD_DO_CMD_TASK = 8,
00077 } msdState_TypeDef;
00078
00079
00080
00081 static int CbwCallback(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining);
00082 __STATIC_INLINE bool CswMeaningful(void);
00083 __STATIC_INLINE bool CswValid(void);
00084 __STATIC_INLINE void EnableNextCbw(void);
00085 static void ProcessScsiCdb(void);
00086 __STATIC_INLINE void SendCsw(void);
00087 static void UsbXferBotData(uint8_t *data, uint32_t len, USB_XferCompleteCb_TypeDef cb);
00088 static void XferBotData(uint32_t length);
00089 static int XferBotDataCallback(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining);
00090 static int XferBotDataIndirectCallback(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining);
00091
00092
00093
00094
00095 STATIC_UBUF(cbw, USB_FS_BULK_EP_MAXSIZE);
00096 static MSDBOT_CBW_TypeDef *pCbw = (MSDBOT_CBW_TypeDef*) &cbw;
00097
00098 EFM32_ALIGN(4)
00099
00100 static MSDBOT_CSW_TypeDef csw __attribute__ ((aligned(4)));
00101 static MSDBOT_CSW_TypeDef *pCsw = &csw;
00102
00103 STATIC_UBUF(mediaBuffer, MEDIA_BUFSIZ);
00104
00105 static MSDD_CmdStatus_TypeDef CmdStatus;
00106 static MSDD_CmdStatus_TypeDef *pCmdStatus = &CmdStatus;
00107 static msdState_TypeDef savedState;
00108 static int ledPort;
00109 static unsigned int ledPin;
00110
00111
00114 EFM32_ALIGN(4)
00115 static const MSDSCSI_InquiryData_TypeDef InquiryData __attribute__ ((aligned(4))) =
00116 {
00117 { .PeripheralDeviceType = 0, .PeripheralQualifier = 0 },
00118 { .Reserved1 = 0, .Removable = 1 },
00119
00120 .Version = 5,
00121
00122 { .ResponseDataFormat = 2,
00123 .HiSup = 0, .NormACA = 0, .Obsolete1 = 0 },
00124
00125 .AdditionalLength = 31,
00126
00127 { .Protect = 0, .Reserved2 = 0, .ThirdPartyCode = 0,
00128 .Tpgs = 0, .Acc = 0, .Sccs = 0 },
00129
00130 { .Addr16 = 0, .Obsolete2 = 0, .MChngr = 0, .MultiP = 0,
00131 .Vs1 = 0, .EncServ = 0, .BQue = 0 },
00132
00133 { .Vs2 = 0, .CmdQue = 0, .Obsolete3 = 0, .Linked = 0,
00134 .Sync = 0, .Wbus16 = 0, .Obsolete4 = 0 },
00135
00136 .T10VendorId = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
00137 .ProductId = { 'E', 'F', 'M', '3', '2', ' ', 'M', 'S', 'D', ' ', 'D', 'e', 'v', 'i', 'c', 'e' },
00138 .ProductRevisionLevel ={ '1', '.', '0', '0' }
00139 };
00140
00141
00146 EFM32_ALIGN(4)
00147 static const MSDSCSI_RequestSenseData_TypeDef NoSenseData __attribute__ ((aligned(4))) =
00148 {
00149 { .ResponseCode = 0x70, .Valid = 0 },
00150 .Obsolete = 0,
00151 { .SenseKey = 0, .Reserved =0, .Ili = 0, .Eom = 0, .FileMark = 0 },
00152 .Information = 0,
00153 .AdditionalLength = 10,
00154 .CmdSpecificInfo = 0,
00155 .Asc = 0,
00156 .Ascq = 0,
00157 .Fruc = 0,
00158 { .SenseKeySpecific1 = 0, .Sksv = 0 },
00159 .SenseKeySpecific2 = 0,
00160 .SenseKeySpecific3 = 0
00161 };
00162
00163
00169 EFM32_ALIGN(4)
00170 static const MSDSCSI_RequestSenseData_TypeDef IllegalSenseData __attribute__ ((aligned(4))) =
00171 {
00172 { .ResponseCode = 0x70, .Valid = 0 },
00173 .Obsolete = 0,
00174 { .SenseKey = 5,
00175 .Reserved = 0, .Ili = 0, .Eom = 0, .FileMark = 0 },
00176 .Information = 0,
00177 .AdditionalLength = 10,
00178 .CmdSpecificInfo = 0,
00179 .Asc = 0x24,
00180 .Ascq = 0,
00181 .Fruc = 0,
00182 { .SenseKeySpecific1 = 0, .Sksv = 0 },
00183 .SenseKeySpecific2 = 0,
00184 .SenseKeySpecific3 = 0
00185 };
00186
00187 static volatile msdState_TypeDef msdState;
00188 static MSDSCSI_RequestSenseData_TypeDef *pSenseData;
00192
00202 void MSDD_Init(int activityLedPort, uint32_t activityLedPin)
00203 {
00204 if ( ( sizeof(MSDSCSI_Read10_TypeDef) != SCSI_READ10_LEN ) ||
00205 ( sizeof(MSDSCSI_Write10_TypeDef) != SCSI_WRITE10_LEN ) ||
00206 ( sizeof(MSDSCSI_Verify10_TypeDef) != SCSI_VERIFY10_LEN ) ||
00207 ( sizeof(MSDSCSI_RequestSense_TypeDef) != SCSI_REQUESTSENSE_LEN ) ||
00208 ( sizeof(InquiryData) != SCSI_INQUIRYDATA_LEN ) ||
00209 ( sizeof(NoSenseData) != SCSI_REQUESTSENSEDATA_LEN ) ||
00210 ( sizeof(IllegalSenseData) != SCSI_REQUESTSENSEDATA_LEN ) ||
00211 ( sizeof(MSDSCSI_ReadCapacity_TypeDef) != SCSI_READCAPACITY_LEN ) ||
00212 ( sizeof(MSDSCSI_ReadCapacityData_TypeDef) != SCSI_READCAPACITYDATA_LEN ) )
00213 {
00214 DEBUG_USB_API_PUTS("\nMSDD_Init(), typedef size error");
00215 EFM_ASSERT(false);
00216 return;
00217 }
00218
00219 if ( ( activityLedPort >= gpioPortA ) && ( activityLedPort <= gpioPortF ) )
00220 ledPort = activityLedPort;
00221 else
00222 ledPort = -1;
00223
00224 ledPin = activityLedPin;
00225 msdState = MSDD_IDLE;
00226 pSenseData = (MSDSCSI_RequestSenseData_TypeDef*) &NoSenseData;
00227
00228 if ( ledPort != -1 )
00229 {
00230 CMU_ClockEnable(cmuClock_GPIO, true);
00231 GPIO_PinModeSet((GPIO_Port_TypeDef)ledPort, ledPin, gpioModePushPull, 0);
00232 }
00233 }
00234
00235
00244 bool MSDD_Handler(void)
00245 {
00246 static uint32_t len;
00247
00248 switch (msdState)
00249 {
00250 case MSDD_ACCESS_INDIRECT:
00251 if (pCmdStatus->xferLen)
00252 {
00253 len = EFM32_MIN(pCmdStatus->xferLen, pCmdStatus->maxBurst);
00254
00255 msdState = MSDD_IDLE;
00256 if (pCmdStatus->direction)
00257 {
00258 MSDDMEDIA_Read(pCmdStatus, mediaBuffer, len / 512);
00259 }
00260 UsbXferBotData(mediaBuffer, len, XferBotDataIndirectCallback);
00261 }
00262 else
00263 {
00264
00265 msdState = savedState;
00266
00267 if (msdState == MSDD_SEND_CSW)
00268 {
00269 SendCsw();
00270 EnableNextCbw();
00271 msdState = MSDD_WAITFOR_CBW;
00272 }
00273
00274 else if (msdState == MSDD_STALL_IN)
00275 {
00276 USBD_StallEp(MSD_BULK_IN);
00277 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00278 }
00279 }
00280 break;
00281
00282 case MSDD_WRITE_INDIRECT:
00283 MSDDMEDIA_Write(pCmdStatus, mediaBuffer, len / 512);
00284 pCmdStatus->lba += len / 512;
00285 msdState = MSDD_ACCESS_INDIRECT;
00286 break;
00287
00288 case MSDD_DO_CMD_TASK:
00289 if (pCbw->CBWCB[ 0 ] == SCSI_STARTSTOP_UNIT)
00290 {
00291 MSDDMEDIA_Flush();
00292 }
00293
00294 SendCsw();
00295 EnableNextCbw();
00296 msdState = MSDD_WAITFOR_CBW;
00297 break;
00298
00299 default:
00300 break;
00301 }
00302 return (msdState == MSDD_WAITFOR_CBW) || (msdState == MSDD_IDLE);
00303 }
00304
00305
00317 int MSDD_SetupCmd(const USB_Setup_TypeDef *setup)
00318 {
00319 int retVal;
00320 static uint32_t tmp;
00321
00322 retVal = USB_STATUS_REQ_UNHANDLED;
00323
00324
00325
00326 if ( ( setup->Type == USB_SETUP_TYPE_CLASS ) &&
00327 ( setup->Direction == USB_SETUP_DIR_OUT ) &&
00328 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) &&
00329 ( setup->bRequest == USB_MSD_BOTRESET ) &&
00330 ( setup->wValue == 0 ) &&
00331 ( setup->wIndex == MSD_INTERFACE_NO ) &&
00332 ( setup->wLength == 0 ) )
00333 {
00334 if (msdState == MSDD_WAITFOR_RECOVERY)
00335 {
00336 msdState = MSDD_IDLE;
00337 }
00338 retVal = USB_STATUS_OK;
00339 }
00340
00341
00342
00343
00344 else if ( ( setup->Type == USB_SETUP_TYPE_CLASS ) &&
00345 ( setup->Direction == USB_SETUP_DIR_IN ) &&
00346 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) &&
00347 ( setup->bRequest == USB_MSD_GETMAXLUN ) &&
00348 ( setup->wValue == 0 ) &&
00349 ( setup->wIndex == MSD_INTERFACE_NO ) &&
00350 ( setup->wLength == 1 ) )
00351 {
00352
00353 tmp = 0;
00354 retVal = USBD_Write(0, (void*) &tmp, 1, NULL);
00355 }
00356
00357
00358
00359
00360 else if ( ( setup->Type == USB_SETUP_TYPE_STANDARD ) &&
00361 ( setup->Direction == USB_SETUP_DIR_OUT ) &&
00362 ( setup->Recipient == USB_SETUP_RECIPIENT_ENDPOINT ) &&
00363 ( setup->bRequest == CLEAR_FEATURE ) &&
00364 ( setup->wValue == USB_FEATURE_ENDPOINT_HALT ) &&
00365 ( setup->wLength == 0 ) )
00366 {
00367 if ( ( ( setup->wIndex & 0xFF) == MSD_BULK_OUT ) ||
00368 ( ( setup->wIndex & 0xFF) == MSD_BULK_IN ) )
00369 {
00370 retVal = USB_STATUS_OK;
00371
00372
00373 if (msdState != MSDD_WAITFOR_RECOVERY)
00374 {
00375 retVal = USBD_UnStallEp(setup->wIndex & 0xFF);
00376
00377 if ((setup->wIndex & 0xFF) == MSD_BULK_IN)
00378 {
00379 if (msdState == MSDD_WAIT_FOR_INUNSTALLED)
00380 {
00381 SendCsw();
00382 EnableNextCbw();
00383 msdState = MSDD_WAITFOR_CBW;
00384 }
00385 }
00386 else
00387 {
00388 EnableNextCbw();
00389 msdState = MSDD_WAITFOR_CBW;
00390 }
00391 }
00392 }
00393 }
00394
00395 return retVal;
00396 }
00397
00398
00408 void MSDD_StateChangeEvent( USBD_State_TypeDef oldState,
00409 USBD_State_TypeDef newState )
00410 {
00411 if (newState == USBD_STATE_CONFIGURED)
00412 {
00413
00414 EnableNextCbw();
00415 msdState = MSDD_WAITFOR_CBW;
00416 }
00417
00418 else if ((oldState == USBD_STATE_CONFIGURED) &&
00419 (newState != USBD_STATE_SUSPENDED))
00420 {
00421
00422 msdState = MSDD_IDLE;
00423 }
00424
00425 else if (newState == USBD_STATE_SUSPENDED)
00426 {
00427
00428 msdState = MSDD_IDLE;
00429
00430
00431 }
00432 }
00433
00436
00453 static int CbwCallback(USB_Status_TypeDef status,
00454 uint32_t xferred, uint32_t remaining)
00455 {
00456 (void) remaining;
00457
00458 if ( ( msdState == MSDD_WAITFOR_CBW ) &&
00459 ( status == USB_STATUS_OK ) &&
00460 ( xferred == CBW_LEN ) &&
00461 ( CswValid() ) &&
00462 ( CswMeaningful() ) )
00463 {
00464 if ( ledPort != -1 )
00465 GPIO_PinOutToggle((GPIO_Port_TypeDef)ledPort, ledPin);
00466
00467
00468 ProcessScsiCdb();
00469
00470 if (pCmdStatus->valid)
00471 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_CMDPASSED;
00472 else
00473 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_CMDFAILED;
00474
00475 pCsw->dCSWSignature = CSW_SIGNATURE;
00476 pCsw->dCSWTag = pCbw->dCBWTag;
00477 pCsw->dCSWDataResidue = pCbw->dCBWDataTransferLength;
00478
00479
00480
00481 if ((pCbw->dCBWDataTransferLength != 0) &&
00482 (pCbw->Direction != pCmdStatus->direction))
00483 {
00484
00485 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00486
00487 if (pCbw->Direction)
00488 {
00489
00490 USBD_StallEp(MSD_BULK_IN);
00491 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00492 }
00493 else
00494 {
00495
00496 USBD_StallEp(MSD_BULK_OUT);
00497 SendCsw();
00498 msdState = MSDD_IDLE;
00499 }
00500 }
00501
00502 else if (pCbw->Direction || (pCbw->dCBWDataTransferLength == 0))
00503 {
00504
00505
00506
00507 if (pCbw->dCBWDataTransferLength == 0)
00508 {
00509
00510 if (pCmdStatus->xferLen)
00511 {
00512
00513 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00514 }
00515
00516 if ((pCmdStatus->xferLen == 0) &&
00517 (pCmdStatus->xferType == XFER_INDIRECT))
00518 {
00519
00520
00521 msdState = MSDD_DO_CMD_TASK;
00522 }
00523 else
00524 {
00525 SendCsw();
00526 EnableNextCbw();
00527 msdState = MSDD_WAITFOR_CBW;
00528 }
00529 }
00530 else if (pCbw->dCBWDataTransferLength == pCmdStatus->xferLen)
00531 {
00532
00533
00534 msdState = MSDD_SEND_CSW;
00535 XferBotData(pCmdStatus->xferLen);
00536 }
00537 else if (pCbw->dCBWDataTransferLength > pCmdStatus->xferLen)
00538 {
00539
00540
00541 if (pCmdStatus->xferLen > 0)
00542 {
00543
00544
00545 msdState = MSDD_STALL_IN;
00546 XferBotData(pCmdStatus->xferLen);
00547 }
00548 else
00549 {
00550
00551 USBD_StallEp(MSD_BULK_IN);
00552 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00553 }
00554 }
00555 else
00556 {
00557
00558 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00559
00560 msdState = MSDD_SEND_CSW;
00561 XferBotData(pCbw->dCBWDataTransferLength);
00562 }
00563 }
00564
00565 else
00566 {
00567
00568
00569
00570 if (pCbw->dCBWDataTransferLength == pCmdStatus->xferLen)
00571 {
00572
00573
00574
00575 msdState = MSDD_SEND_CSW;
00576 XferBotData(pCmdStatus->xferLen);
00577 }
00578 else if (pCbw->dCBWDataTransferLength > pCmdStatus->xferLen)
00579 {
00580
00581 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_CMDFAILED;
00582 USBD_StallEp(MSD_BULK_OUT);
00583 SendCsw();
00584 msdState = MSDD_IDLE;
00585 }
00586 else
00587 {
00588
00589 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00590 USBD_StallEp(MSD_BULK_OUT);
00591 SendCsw();
00592 msdState = MSDD_IDLE;
00593 }
00594 }
00595 return USB_STATUS_OK;
00596 }
00597
00598 if ((status == USB_STATUS_OK) &&
00599 (USBD_GetUsbState() == USBD_STATE_CONFIGURED))
00600 {
00601
00602 USBD_StallEp(MSD_BULK_OUT);
00603 USBD_StallEp(MSD_BULK_IN);
00604 msdState = MSDD_WAITFOR_RECOVERY;
00605 }
00606
00607 return USB_STATUS_OK;
00608 }
00609
00610
00615 __STATIC_INLINE bool CswMeaningful(void)
00616 {
00617 if ( ( pCbw->Reserved1 == 0 ) &&
00618 ( pCbw->Obsolete == 0 ) &&
00619 ( pCbw->Reserved2 == 0 ) &&
00620 ( pCbw->Lun == 0 ) &&
00621 ( pCbw->Reserved3 == 0 ) )
00622 {
00623 return true;
00624 }
00625
00626 return false;
00627 }
00628
00629
00634 __STATIC_INLINE bool CswValid(void)
00635 {
00636 return pCbw->dCBWSignature == CBW_SIGNATURE ? true : false;
00637 }
00638
00639
00643 __STATIC_INLINE void EnableNextCbw(void)
00644 {
00645 USBD_Read(MSD_BULK_OUT, (void*) &cbw, USB_FS_BULK_EP_MAXSIZE, CbwCallback);
00646 }
00647
00648
00653 static void ProcessScsiCdb(void)
00654 {
00655 MSDSCSI_Inquiry_TypeDef *cbI;
00656 MSDSCSI_RequestSense_TypeDef *cbRS;
00657 MSDSCSI_ReadCapacity_TypeDef *cbRC;
00658 MSDSCSI_Read10_TypeDef *cbR10;
00659 MSDSCSI_Write10_TypeDef *cbW10;
00660 MSDSCSI_Verify10_TypeDef *cbV10;
00661
00662 EFM32_ALIGN(4)
00663 static MSDSCSI_ReadCapacityData_TypeDef ReadCapData __attribute__ ((aligned(4)));
00664
00665 pCmdStatus->valid = false;
00666 pCmdStatus->xferType = XFER_MEMORYMAPPED;
00667 pCmdStatus->maxBurst = MSD_MAX_BURST;
00668
00669 switch (pCbw->CBWCB[ 0 ])
00670 {
00671 case SCSI_INQUIRY:
00672 cbI = (MSDSCSI_Inquiry_TypeDef*) &pCbw->CBWCB;
00673
00674 if ((cbI->Evpd == 0) && (cbI->PageCode == 0))
00675 {
00676
00677 pCmdStatus->valid = true;
00678 pCmdStatus->direction = MSD_DIR_DATA_IN;
00679 pCmdStatus->pData = (uint8_t*) &InquiryData;
00680 pCmdStatus->xferLen = EFM32_MIN(SCSI_INQUIRYDATA_LEN,
00681 __REV16(cbI->AllocationLength));
00682 }
00683 break;
00684
00685 case SCSI_REQUESTSENSE:
00686 cbRS = (MSDSCSI_RequestSense_TypeDef*) &pCbw->CBWCB;
00687
00688 if ((cbRS->Desc == 0) && (cbRS->Reserved1 == 0) &&
00689 (cbRS->Reserved2 == 0) && (cbRS->Reserved3 == 0))
00690 {
00691 pCmdStatus->valid = true;
00692 pCmdStatus->direction = MSD_DIR_DATA_IN;
00693 pCmdStatus->pData = (uint8_t*) pSenseData;
00694 pCmdStatus->xferLen = EFM32_MIN(SCSI_REQUESTSENSEDATA_LEN,
00695 cbRS->AllocationLength);
00696 pSenseData = (MSDSCSI_RequestSenseData_TypeDef*) &NoSenseData;
00697 }
00698 break;
00699
00700 case SCSI_READCAPACITY:
00701 cbRC = (MSDSCSI_ReadCapacity_TypeDef*) &pCbw->CBWCB;
00702
00703 if ((cbRC->Pmi == 0) && (cbRC->Lba == 0))
00704 {
00705 ReadCapData.LogicalBlockAddress = __REV(MSDDMEDIA_GetSectorCount() - 1);
00706 ReadCapData.LogicalBlockLength = __REV(512);
00707
00708 pCmdStatus->valid = true;
00709 pCmdStatus->direction = MSD_DIR_DATA_IN;
00710 pCmdStatus->pData = (uint8_t*) &ReadCapData;
00711 pCmdStatus->xferLen = SCSI_READCAPACITYDATA_LEN;
00712 }
00713 break;
00714
00715 case SCSI_READ10:
00716 cbR10 = (MSDSCSI_Read10_TypeDef*) &pCbw->CBWCB;
00717
00718 pCmdStatus->direction = MSD_DIR_DATA_IN;
00719 pCmdStatus->valid = MSDDMEDIA_CheckAccess(pCmdStatus,
00720 __REV(cbR10->Lba),
00721 __REV16(cbR10->TransferLength));
00722 break;
00723
00724 case SCSI_WRITE10:
00725 cbW10 = (MSDSCSI_Write10_TypeDef*) &pCbw->CBWCB;
00726
00727 pCmdStatus->direction = MSD_DIR_DATA_OUT;
00728 pCmdStatus->valid = MSDDMEDIA_CheckAccess(pCmdStatus,
00729 __REV(cbW10->Lba),
00730 __REV16(cbW10->TransferLength));
00731 break;
00732
00733 case SCSI_VERIFY10:
00734 cbV10 = (MSDSCSI_Verify10_TypeDef*) &pCbw->CBWCB;
00735
00736 if ((cbV10->BytChk == 0) && (cbV10->Reserved1 == 0) &&
00737 (cbV10->Dpo == 0) && (cbV10->VrProtect == 0) &&
00738 (cbV10->GroupNumber == 0) && (cbV10->Reserved2 == 0) &&
00739 (cbV10->Restricted == 0))
00740 {
00741 pCmdStatus->valid = true;
00742 pCmdStatus->direction = pCbw->Direction;
00743 pCmdStatus->xferLen = 0;
00744 }
00745 break;
00746
00747 case SCSI_TESTUNIT_READY:
00748 pCmdStatus->valid = true;
00749 pCmdStatus->direction = pCbw->Direction;
00750 pCmdStatus->xferLen = 0;
00751 break;
00752
00753 case SCSI_STARTSTOP_UNIT:
00754 pCmdStatus->valid = true;
00755 pCmdStatus->direction = pCbw->Direction;
00756 pCmdStatus->xferLen = 0;
00757 pCmdStatus->xferType = XFER_INDIRECT;
00758 break;
00759 }
00760
00761 if (!pCmdStatus->valid)
00762 {
00763 pCmdStatus->xferLen = 0;
00764 pCmdStatus->direction = pCbw->Direction;
00765 pSenseData = (MSDSCSI_RequestSenseData_TypeDef*) &IllegalSenseData;
00766 }
00767 }
00768
00769
00773 __STATIC_INLINE void SendCsw(void)
00774 {
00775 if ( ledPort != -1 )
00776 GPIO_PinOutToggle((GPIO_Port_TypeDef)ledPort, ledPin);
00777
00778 USBD_Write(MSD_BULK_IN, (void*) &csw, CSW_LEN, NULL);
00779 }
00780
00781
00795 static void UsbXferBotData(uint8_t *data, uint32_t len,
00796 USB_XferCompleteCb_TypeDef cb)
00797 {
00798 if (pCmdStatus->direction)
00799 {
00800 USBD_Write(MSD_BULK_IN, data, len, cb);
00801 }
00802 else
00803 {
00804 USBD_Read(MSD_BULK_OUT, data, len, cb);
00805 }
00806 }
00807
00808
00816 static void XferBotData(uint32_t length)
00817 {
00818 pCmdStatus->xferLen = length;
00819 pCsw->dCSWDataResidue = pCbw->dCBWDataTransferLength;
00820
00821 if (pCmdStatus->xferType == XFER_INDIRECT)
00822 {
00823
00824 savedState = msdState;
00825 msdState = MSDD_ACCESS_INDIRECT;
00826 }
00827 else
00828 {
00829 UsbXferBotData(pCmdStatus->pData,
00830 EFM32_MIN(length, pCmdStatus->maxBurst),
00831 XferBotDataCallback);
00832 }
00833 }
00834
00835
00854 static int XferBotDataCallback(USB_Status_TypeDef status,
00855 uint32_t xferred, uint32_t remaining)
00856 {
00857 (void) status;
00858 (void) remaining;
00859
00860 pCmdStatus->xferLen -= xferred;
00861 pCsw->dCSWDataResidue -= xferred;
00862
00863 if (pCmdStatus->xferLen)
00864 {
00865 pCmdStatus->pData += xferred;
00866 UsbXferBotData(pCmdStatus->pData,
00867 EFM32_MIN(pCmdStatus->xferLen, pCmdStatus->maxBurst),
00868 XferBotDataCallback);
00869 }
00870 else
00871 {
00872 if (msdState == MSDD_SEND_CSW)
00873 {
00874 SendCsw();
00875 EnableNextCbw();
00876 msdState = MSDD_WAITFOR_CBW;
00877 }
00878
00879 else if (msdState == MSDD_STALL_IN)
00880 {
00881 USBD_StallEp(MSD_BULK_IN);
00882 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00883 }
00884 }
00885
00886 return USB_STATUS_OK;
00887 }
00888
00889
00906 static int XferBotDataIndirectCallback(USB_Status_TypeDef status,
00907 uint32_t xferred, uint32_t remaining)
00908 {
00909 (void) status;
00910 (void) remaining;
00911
00912 pCmdStatus->xferLen -= xferred;
00913 pCsw->dCSWDataResidue -= xferred;
00914
00915 if (pCmdStatus->direction)
00916 {
00917 pCmdStatus->lba += xferred / 512;
00918 msdState = MSDD_ACCESS_INDIRECT;
00919 }
00920 else
00921 {
00922 msdState = MSDD_WRITE_INDIRECT;
00923 }
00924
00925 return USB_STATUS_OK;
00926 }
00927