00001
00035 #include "em_usb.h"
00036 #include "em_cmu.h"
00037 #include "em_gpio.h"
00038 #include "msdbot.h"
00039 #include "msdscsi.h"
00040 #include "msdd.h"
00041 #include "msddmedia.h"
00042
00045
00046
00047 #define BULK_OUT 0x01
00048 #define BULK_IN 0x81
00049 #define DIR_DATA_OUT 0
00050 #define DIR_DATA_IN 1
00051 #define MAX_BURST 32768U
00052
00053
00056 typedef enum
00057 {
00058 MSDD_IDLE = 0,
00059 MSDD_WAITFOR_CBW = 1,
00060 MSDD_WAITFOR_RECOVERY = 2,
00061 MSDD_SEND_CSW = 3,
00062 MSDD_WAIT_FOR_INUNSTALLED = 4,
00063 MSDD_STALL_IN = 5,
00064 MSDD_ACCESS_INDIRECT = 6,
00065 MSDD_WRITE_INDIRECT = 7,
00066 MSDD_DO_CMD_TASK = 8,
00067 } msdState_TypeDef;
00068
00069
00070
00071 static int CbwCallback(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining);
00072 __STATIC_INLINE bool CswMeaningful(void);
00073 __STATIC_INLINE bool CswValid(void);
00074 __STATIC_INLINE void EnableNextCbw(void);
00075 static void ProcessScsiCdb(void);
00076 __STATIC_INLINE void SendCsw(void);
00077 static int UsbSetupCmd(const USB_Setup_TypeDef *setup);
00078 static void UsbStateChangeEvent(USBD_State_TypeDef oldState, USBD_State_TypeDef newState);
00079 static void UsbXferBotData(uint8_t *data, uint32_t len, USB_XferCompleteCb_TypeDef cb);
00080 static void XferBotData(uint32_t length);
00081 static int XferBotDataCallback(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining);
00082 static int XferBotDataIndirectCallback(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining);
00083
00084
00085
00086 #include "descriptors.h"
00087
00088
00089
00090
00091 STATIC_UBUF(cbw, USB_MAX_EP_SIZE);
00092 static MSDBOT_CBW_TypeDef *pCbw = (MSDBOT_CBW_TypeDef*) &cbw;
00093
00094 EFM32_ALIGN(4)
00095
00096 static MSDBOT_CSW_TypeDef csw __attribute__ ((aligned(4)));
00097 static MSDBOT_CSW_TypeDef *pCsw = &csw;
00098
00099 STATIC_UBUF(mediaBuffer, MEDIA_BUFSIZ);
00100
00101 static MSDD_CmdStatus_TypeDef CmdStatus;
00102 static MSDD_CmdStatus_TypeDef *pCmdStatus = &CmdStatus;
00103 static msdState_TypeDef savedState;
00104 static int ledPort;
00105 static unsigned int ledPin;
00106
00107
00110 EFM32_ALIGN(4)
00111 static const MSDSCSI_InquiryData_TypeDef InquiryData __attribute__ ((aligned(4))) =
00112 {
00113 { .PeripheralDeviceType = 0, .PeripheralQualifier = 0 },
00114 { .Reserved1 = 0, .Removable = 1 },
00115
00116 .Version = 5,
00117
00118 { .ResponseDataFormat = 2,
00119 .HiSup = 0, .NormACA = 0, .Obsolete1 = 0 },
00120
00121 .AdditionalLength = 31,
00122
00123 { .Protect = 0, .Reserved2 = 0, .ThirdPartyCode = 0,
00124 .Tpgs = 0, .Acc = 0, .Sccs = 0 },
00125
00126 { .Addr16 = 0, .Obsolete2 = 0, .MChngr = 0, .MultiP = 0,
00127 .Vs1 = 0, .EncServ = 0, .BQue = 0 },
00128
00129 { .Vs2 = 0, .CmdQue =0, .Obsolete3 = 0, .Linked = 0,
00130 .Sync = 0, .Wbus16 = 0, .Obsolete4 = 0 },
00131
00132 .T10VendorId = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
00133 .ProductId = { 'E', 'F', 'M', '3', '2', ' ', 'M', 'S', 'D', ' ', 'D', 'e', 'v', 'i', 'c', 'e' },
00134 .ProductRevisionLevel ={ '1', '.', '0', '0' }
00135 };
00136
00137
00142 EFM32_ALIGN(4)
00143 static const MSDSCSI_RequestSenseData_TypeDef NoSenseData __attribute__ ((aligned(4))) =
00144 {
00145 { .ResponseCode = 0x70, .Valid = 0 },
00146 .Obsolete = 0,
00147 { .SenseKey = 0, .Reserved =0, .Ili = 0, .Eom = 0, .FileMark = 0 },
00148 .Information = 0,
00149 .AdditionalLength = 10,
00150 .CmdSpecificInfo = 0,
00151 .Asc = 0,
00152 .Ascq = 0,
00153 .Fruc = 0,
00154 { .SenseKeySpecific1 = 0, .Sksv = 0 },
00155 .SenseKeySpecific2 = 0,
00156 .SenseKeySpecific3 = 0
00157 };
00158
00159
00165 EFM32_ALIGN(4)
00166 static const MSDSCSI_RequestSenseData_TypeDef IllegalSenseData __attribute__ ((aligned(4))) =
00167 {
00168 { .ResponseCode = 0x70, .Valid = 0 },
00169 .Obsolete = 0,
00170 { .SenseKey = 5,
00171 .Reserved = 0, .Ili = 0, .Eom = 0, .FileMark = 0 },
00172 .Information = 0,
00173 .AdditionalLength = 10,
00174 .CmdSpecificInfo = 0,
00175 .Asc = 0x24,
00176 .Ascq = 0,
00177 .Fruc = 0,
00178 { .SenseKeySpecific1 = 0, .Sksv = 0 },
00179 .SenseKeySpecific2 = 0,
00180 .SenseKeySpecific3 = 0
00181 };
00182
00183 static volatile msdState_TypeDef msdState;
00184 static MSDSCSI_RequestSenseData_TypeDef *pSenseData;
00188
00198 void MSDD_Init(int activityLedPort, uint32_t activityLedPin)
00199 {
00200 if ((sizeof(MSDSCSI_Read10_TypeDef) != SCSI_READ10_LEN) ||
00201 (sizeof(MSDSCSI_Write10_TypeDef) != SCSI_WRITE10_LEN) ||
00202 (sizeof(MSDSCSI_RequestSense_TypeDef) != SCSI_REQUESTSENSE_LEN) ||
00203 (sizeof(InquiryData) != SCSI_INQUIRYDATA_LEN) ||
00204 (sizeof(NoSenseData) != SCSI_REQUESTSENSEDATA_LEN) ||
00205 (sizeof(IllegalSenseData) != SCSI_REQUESTSENSEDATA_LEN) ||
00206 (sizeof(MSDSCSI_ReadCapacity_TypeDef) != SCSI_READCAPACITY_LEN) ||
00207 (sizeof(MSDSCSI_ReadCapacityData_TypeDef) != SCSI_READCAPACITYDATA_LEN))
00208 {
00209 DEBUG_USB_API_PUTS("\nMSDD_Init(), typedef size error");
00210 EFM_ASSERT(false);
00211 return;
00212 }
00213
00214 if ( ( activityLedPort >= gpioPortA ) && ( activityLedPort <= gpioPortF ) )
00215 ledPort = activityLedPort;
00216 else
00217 ledPort = -1;
00218
00219 ledPin = activityLedPin;
00220 msdState = MSDD_IDLE;
00221 pSenseData = (MSDSCSI_RequestSenseData_TypeDef*) &NoSenseData;
00222 USBD_Init(&initstruct);
00223
00224 if ( ledPort != -1 )
00225 {
00226 CMU_ClockEnable(cmuClock_GPIO, true);
00227 GPIO_PinModeSet((GPIO_Port_TypeDef)ledPort, ledPin, gpioModePushPull, 0);
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237 }
00238
00239
00248 bool MSDD_Handler(void)
00249 {
00250 static uint32_t len;
00251
00252 switch (msdState)
00253 {
00254 case MSDD_ACCESS_INDIRECT:
00255 if (pCmdStatus->xferLen)
00256 {
00257 len = EFM32_MIN(pCmdStatus->xferLen, pCmdStatus->maxBurst);
00258
00259 msdState = MSDD_IDLE;
00260 if (pCmdStatus->direction)
00261 {
00262 MSDDMEDIA_Read(pCmdStatus, mediaBuffer, len / 512);
00263 }
00264 UsbXferBotData(mediaBuffer, len, XferBotDataIndirectCallback);
00265 }
00266 else
00267 {
00268
00269 msdState = savedState;
00270
00271 if (msdState == MSDD_SEND_CSW)
00272 {
00273 SendCsw();
00274 EnableNextCbw();
00275 msdState = MSDD_WAITFOR_CBW;
00276 }
00277
00278 else if (msdState == MSDD_STALL_IN)
00279 {
00280 USBD_StallEp(BULK_IN);
00281 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00282 }
00283 }
00284 break;
00285
00286 case MSDD_WRITE_INDIRECT:
00287 MSDDMEDIA_Write(pCmdStatus, mediaBuffer, len / 512);
00288 pCmdStatus->lba += len / 512;
00289 msdState = MSDD_ACCESS_INDIRECT;
00290 break;
00291
00292 case MSDD_DO_CMD_TASK:
00293 if (pCbw->CBWCB[ 0 ] == SCSI_STARTSTOP_UNIT)
00294 {
00295 MSDDMEDIA_Flush();
00296 }
00297
00298 SendCsw();
00299 EnableNextCbw();
00300 msdState = MSDD_WAITFOR_CBW;
00301 break;
00302
00303 default:
00304 break;
00305 }
00306 return (msdState == MSDD_WAITFOR_CBW) || (msdState == MSDD_IDLE);
00307 }
00308
00311
00328 static int CbwCallback(USB_Status_TypeDef status,
00329 uint32_t xferred, uint32_t remaining)
00330 {
00331 (void) remaining;
00332
00333 if ((msdState == MSDD_WAITFOR_CBW) &&
00334 (status == USB_STATUS_OK) &&
00335 (xferred == CBW_LEN) &&
00336 (CswValid()) &&
00337 (CswMeaningful()))
00338 {
00339 if ( ledPort != -1 )
00340 GPIO_PinOutToggle((GPIO_Port_TypeDef)ledPort, ledPin);
00341
00342
00343 ProcessScsiCdb();
00344
00345 if (pCmdStatus->valid)
00346 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_CMDPASSED;
00347 else
00348 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_CMDFAILED;
00349
00350 pCsw->dCSWSignature = CSW_SIGNATURE;
00351 pCsw->dCSWTag = pCbw->dCBWTag;
00352 pCsw->dCSWDataResidue = pCbw->dCBWDataTransferLength;
00353
00354
00355
00356 if ((pCbw->dCBWDataTransferLength != 0) &&
00357 (pCbw->Direction != pCmdStatus->direction))
00358 {
00359
00360 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00361
00362 if (pCbw->Direction)
00363 {
00364
00365 USBD_StallEp(BULK_IN);
00366 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00367 }
00368 else
00369 {
00370
00371 USBD_StallEp(BULK_OUT);
00372 SendCsw();
00373 msdState = MSDD_IDLE;
00374 }
00375 }
00376
00377 else if (pCbw->Direction || (pCbw->dCBWDataTransferLength == 0))
00378 {
00379
00380
00381
00382 if (pCbw->dCBWDataTransferLength == 0)
00383 {
00384
00385 if (pCmdStatus->xferLen)
00386 {
00387
00388 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00389 }
00390
00391 if ((pCmdStatus->xferLen == 0) &&
00392 (pCmdStatus->xferType == XFER_INDIRECT))
00393 {
00394
00395
00396 msdState = MSDD_DO_CMD_TASK;
00397 }
00398 else
00399 {
00400 SendCsw();
00401 EnableNextCbw();
00402 msdState = MSDD_WAITFOR_CBW;
00403 }
00404 }
00405 else if (pCbw->dCBWDataTransferLength == pCmdStatus->xferLen)
00406 {
00407
00408
00409 msdState = MSDD_SEND_CSW;
00410 XferBotData(pCmdStatus->xferLen);
00411 }
00412 else if (pCbw->dCBWDataTransferLength > pCmdStatus->xferLen)
00413 {
00414
00415
00416 if (pCmdStatus->xferLen > 0)
00417 {
00418
00419
00420 msdState = MSDD_STALL_IN;
00421 XferBotData(pCmdStatus->xferLen);
00422 }
00423 else
00424 {
00425
00426 USBD_StallEp(BULK_IN);
00427 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00428 }
00429 }
00430 else
00431 {
00432
00433 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00434
00435 msdState = MSDD_SEND_CSW;
00436 XferBotData(pCbw->dCBWDataTransferLength);
00437 }
00438 }
00439
00440 else
00441 {
00442
00443
00444
00445 if (pCbw->dCBWDataTransferLength == pCmdStatus->xferLen)
00446 {
00447
00448
00449
00450 msdState = MSDD_SEND_CSW;
00451 XferBotData(pCmdStatus->xferLen);
00452 }
00453 else if (pCbw->dCBWDataTransferLength > pCmdStatus->xferLen)
00454 {
00455
00456 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_CMDFAILED;
00457 USBD_StallEp(BULK_OUT);
00458 SendCsw();
00459 msdState = MSDD_IDLE;
00460 }
00461 else
00462 {
00463
00464 pCsw->bCSWStatus = USB_CLASS_MSD_CSW_PHASEERROR;
00465 USBD_StallEp(BULK_OUT);
00466 SendCsw();
00467 msdState = MSDD_IDLE;
00468 }
00469 }
00470 return USB_STATUS_OK;
00471 }
00472
00473 if ((status == USB_STATUS_OK) &&
00474 (USBD_GetUsbState() == USBD_STATE_CONFIGURED))
00475 {
00476
00477 USBD_StallEp(BULK_OUT);
00478 USBD_StallEp(BULK_IN);
00479 msdState = MSDD_WAITFOR_RECOVERY;
00480 }
00481
00482 return USB_STATUS_OK;
00483 }
00484
00485
00490 __STATIC_INLINE bool CswMeaningful(void)
00491 {
00492 if ((pCbw->Reserved1 == 0) &&
00493 (pCbw->Obsolete == 0) &&
00494 (pCbw->Reserved2 == 0) &&
00495 (pCbw->Lun == 0) &&
00496 (pCbw->Reserved3 == 0))
00497 {
00498 return true;
00499 }
00500
00501 return false;
00502 }
00503
00504
00509 __STATIC_INLINE bool CswValid(void)
00510 {
00511 return pCbw->dCBWSignature == CBW_SIGNATURE ? true : false;
00512 }
00513
00514
00518 __STATIC_INLINE void EnableNextCbw(void)
00519 {
00520 USBD_Read(BULK_OUT, (void*) &cbw, USB_MAX_EP_SIZE, CbwCallback);
00521 }
00522
00523
00528 static void ProcessScsiCdb(void)
00529 {
00530 MSDSCSI_Inquiry_TypeDef *cbI;
00531 MSDSCSI_RequestSense_TypeDef *cbRS;
00532 MSDSCSI_ReadCapacity_TypeDef *cbRC;
00533 MSDSCSI_Read10_TypeDef *cbR10;
00534 MSDSCSI_Write10_TypeDef *cbW10;
00535
00536 EFM32_ALIGN(4)
00537 static MSDSCSI_ReadCapacityData_TypeDef ReadCapData __attribute__ ((aligned(4)));
00538
00539 pCmdStatus->valid = false;
00540 pCmdStatus->xferType = XFER_MEMORYMAPPED;
00541 pCmdStatus->maxBurst = MAX_BURST;
00542
00543 switch (pCbw->CBWCB[ 0 ])
00544 {
00545 case SCSI_INQUIRY:
00546 cbI = (MSDSCSI_Inquiry_TypeDef*) &pCbw->CBWCB;
00547
00548 if ((cbI->Evpd == 0) && (cbI->PageCode == 0))
00549 {
00550
00551 pCmdStatus->valid = true;
00552 pCmdStatus->direction = DIR_DATA_IN;
00553 pCmdStatus->pData = (uint8_t*) &InquiryData;
00554 pCmdStatus->xferLen = EFM32_MIN(SCSI_INQUIRYDATA_LEN,
00555 __REV16(cbI->AllocationLength));
00556 }
00557 break;
00558
00559 case SCSI_REQUESTSENSE:
00560 cbRS = (MSDSCSI_RequestSense_TypeDef*) &pCbw->CBWCB;
00561
00562 if ((cbRS->Desc == 0) && (cbRS->Reserved1 == 0) &&
00563 (cbRS->Reserved2 == 0) && (cbRS->Reserved3 == 0))
00564 {
00565 pCmdStatus->valid = true;
00566 pCmdStatus->direction = DIR_DATA_IN;
00567 pCmdStatus->pData = (uint8_t*) pSenseData;
00568 pCmdStatus->xferLen = EFM32_MIN(SCSI_REQUESTSENSEDATA_LEN,
00569 cbRS->AllocationLength);
00570 pSenseData = (MSDSCSI_RequestSenseData_TypeDef*) &NoSenseData;
00571 }
00572 break;
00573
00574 case SCSI_READCAPACITY:
00575 cbRC = (MSDSCSI_ReadCapacity_TypeDef*) &pCbw->CBWCB;
00576
00577 if ((cbRC->Pmi == 0) && (cbRC->Lba == 0))
00578 {
00579 ReadCapData.LogicalBlockAddress = __REV(MSDDMEDIA_GetSectorCount() - 1);
00580 ReadCapData.LogicalBlockLength = __REV(512);
00581
00582 pCmdStatus->valid = true;
00583 pCmdStatus->direction = DIR_DATA_IN;
00584 pCmdStatus->pData = (uint8_t*) &ReadCapData;
00585 pCmdStatus->xferLen = SCSI_READCAPACITYDATA_LEN;
00586 }
00587 break;
00588
00589 case SCSI_READ10:
00590 cbR10 = (MSDSCSI_Read10_TypeDef*) &pCbw->CBWCB;
00591
00592 pCmdStatus->direction = DIR_DATA_IN;
00593 pCmdStatus->valid = MSDDMEDIA_CheckAccess(pCmdStatus,
00594 __REV(cbR10->Lba),
00595 __REV16(cbR10->TransferLength));
00596 break;
00597
00598 case SCSI_WRITE10:
00599 cbW10 = (MSDSCSI_Write10_TypeDef*) &pCbw->CBWCB;
00600
00601 pCmdStatus->direction = DIR_DATA_OUT;
00602 pCmdStatus->valid = MSDDMEDIA_CheckAccess(pCmdStatus,
00603 __REV(cbW10->Lba),
00604 __REV16(cbW10->TransferLength));
00605 break;
00606
00607 case SCSI_TESTUNIT_READY:
00608 pCmdStatus->valid = true;
00609 pCmdStatus->direction = pCbw->Direction;
00610 pCmdStatus->xferLen = 0;
00611 break;
00612
00613 case SCSI_STARTSTOP_UNIT:
00614 pCmdStatus->valid = true;
00615 pCmdStatus->direction = pCbw->Direction;
00616 pCmdStatus->xferLen = 0;
00617 pCmdStatus->xferType = XFER_INDIRECT;
00618 break;
00619 }
00620
00621 if (!pCmdStatus->valid)
00622 {
00623 pCmdStatus->xferLen = 0;
00624 pCmdStatus->direction = pCbw->Direction;
00625 pSenseData = (MSDSCSI_RequestSenseData_TypeDef*) &IllegalSenseData;
00626 }
00627 }
00628
00629
00633 __STATIC_INLINE void SendCsw(void)
00634 {
00635 if ( ledPort != -1 )
00636 GPIO_PinOutToggle((GPIO_Port_TypeDef)ledPort, ledPin);
00637
00638 USBD_Write(BULK_IN, (void*) &csw, CSW_LEN, NULL);
00639 }
00640
00641
00653 static int UsbSetupCmd(const USB_Setup_TypeDef *setup)
00654 {
00655 int retVal;
00656 static uint32_t tmp;
00657
00658 retVal = USB_STATUS_REQ_UNHANDLED;
00659
00660
00661
00662 if ((setup->Type == USB_SETUP_TYPE_CLASS) &&
00663 (setup->Direction == USB_SETUP_DIR_OUT) &&
00664 (setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE) &&
00665 (setup->bRequest == USB_MSD_BOTRESET) &&
00666 (setup->wValue == 0) &&
00667 (setup->wIndex == 0) &&
00668 (setup->wLength == 0))
00669 {
00670 if (msdState == MSDD_WAITFOR_RECOVERY)
00671 {
00672 msdState = MSDD_IDLE;
00673 }
00674 retVal = USB_STATUS_OK;
00675 }
00676
00677
00678
00679
00680 else if ((setup->Type == USB_SETUP_TYPE_CLASS) &&
00681 (setup->Direction == USB_SETUP_DIR_IN) &&
00682 (setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE) &&
00683 (setup->bRequest == USB_MSD_GETMAXLUN) &&
00684 (setup->wValue == 0) &&
00685 (setup->wIndex == 0) &&
00686 (setup->wLength == 1))
00687 {
00688
00689 tmp = 0;
00690 retVal = USBD_Write(0, (void*) &tmp, 1, NULL);
00691 }
00692
00693
00694
00695
00696 else if ((setup->Type == USB_SETUP_TYPE_STANDARD) &&
00697 (setup->Direction == USB_SETUP_DIR_OUT) &&
00698 (setup->Recipient == USB_SETUP_RECIPIENT_ENDPOINT) &&
00699 (setup->bRequest == CLEAR_FEATURE) &&
00700 (setup->wValue == USB_FEATURE_ENDPOINT_HALT) &&
00701 (setup->wLength == 0))
00702 {
00703 if (((setup->wIndex & 0xFF) == BULK_OUT) ||
00704 ((setup->wIndex & 0xFF) == BULK_IN))
00705 {
00706 retVal = USB_STATUS_OK;
00707
00708
00709 if (msdState != MSDD_WAITFOR_RECOVERY)
00710 {
00711 retVal = USBD_UnStallEp(setup->wIndex & 0xFF);
00712
00713 if ((setup->wIndex & 0xFF) == BULK_IN)
00714 {
00715 if (msdState == MSDD_WAIT_FOR_INUNSTALLED)
00716 {
00717 SendCsw();
00718 EnableNextCbw();
00719 msdState = MSDD_WAITFOR_CBW;
00720 }
00721 }
00722 else
00723 {
00724 EnableNextCbw();
00725 msdState = MSDD_WAITFOR_CBW;
00726 }
00727 }
00728 }
00729 }
00730
00731 return retVal;
00732 }
00733
00734
00744 static void UsbStateChangeEvent(USBD_State_TypeDef oldState,
00745 USBD_State_TypeDef newState)
00746 {
00747 if (newState == USBD_STATE_CONFIGURED)
00748 {
00749
00750 EnableNextCbw();
00751 msdState = MSDD_WAITFOR_CBW;
00752 }
00753
00754 else if ((oldState == USBD_STATE_CONFIGURED) &&
00755 (newState != USBD_STATE_SUSPENDED))
00756 {
00757
00758 msdState = MSDD_IDLE;
00759 }
00760
00761 else if (newState == USBD_STATE_SUSPENDED)
00762 {
00763
00764 msdState = MSDD_IDLE;
00765
00766
00767 }
00768 }
00769
00770
00784 static void UsbXferBotData(uint8_t *data, uint32_t len,
00785 USB_XferCompleteCb_TypeDef cb)
00786 {
00787 if (pCmdStatus->direction)
00788 {
00789 USBD_Write(BULK_IN, data, len, cb);
00790 }
00791 else
00792 {
00793 USBD_Read(BULK_OUT, data, len, cb);
00794 }
00795 }
00796
00797
00805 static void XferBotData(uint32_t length)
00806 {
00807 pCmdStatus->xferLen = length;
00808 pCsw->dCSWDataResidue = pCbw->dCBWDataTransferLength;
00809
00810 if (pCmdStatus->xferType == XFER_INDIRECT)
00811 {
00812
00813 savedState = msdState;
00814 msdState = MSDD_ACCESS_INDIRECT;
00815 }
00816 else
00817 {
00818 UsbXferBotData(pCmdStatus->pData,
00819 EFM32_MIN(length, pCmdStatus->maxBurst),
00820 XferBotDataCallback);
00821 }
00822 }
00823
00824
00843 static int XferBotDataCallback(USB_Status_TypeDef status,
00844 uint32_t xferred, uint32_t remaining)
00845 {
00846 (void) status;
00847 (void) remaining;
00848
00849 pCmdStatus->xferLen -= xferred;
00850 pCsw->dCSWDataResidue -= xferred;
00851
00852 if (pCmdStatus->xferLen)
00853 {
00854 pCmdStatus->pData += xferred;
00855 UsbXferBotData(pCmdStatus->pData,
00856 EFM32_MIN(pCmdStatus->xferLen, pCmdStatus->maxBurst),
00857 XferBotDataCallback);
00858 }
00859 else
00860 {
00861 if (msdState == MSDD_SEND_CSW)
00862 {
00863 SendCsw();
00864 EnableNextCbw();
00865 msdState = MSDD_WAITFOR_CBW;
00866 }
00867
00868 else if (msdState == MSDD_STALL_IN)
00869 {
00870 USBD_StallEp(BULK_IN);
00871 msdState = MSDD_WAIT_FOR_INUNSTALLED;
00872 }
00873 }
00874
00875 return USB_STATUS_OK;
00876 }
00877
00878
00895 static int XferBotDataIndirectCallback(USB_Status_TypeDef status,
00896 uint32_t xferred, uint32_t remaining)
00897 {
00898 (void) status;
00899 (void) remaining;
00900
00901 pCmdStatus->xferLen -= xferred;
00902 pCsw->dCSWDataResidue -= xferred;
00903
00904 if (pCmdStatus->direction)
00905 {
00906 pCmdStatus->lba += xferred / 512;
00907 msdState = MSDD_ACCESS_INDIRECT;
00908 }
00909 else
00910 {
00911 msdState = MSDD_WRITE_INDIRECT;
00912 }
00913
00914 return USB_STATUS_OK;
00915 }
00916