Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "SBCMethods.h"
00040 #include "MSDDStateMachine.h"
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 static void MSDDriver_Callback(MSDTransfer *transfer,
00054 uint8_t status,
00055 uint32_t transferred,
00056 uint32_t remaining)
00057 {
00058 TRACE_DEBUG_WP( "Cbk " ) ;
00059 transfer->semaphore++;
00060 transfer->status = status;
00061 transfer->transferred = transferred;
00062 transfer->remaining = remaining;
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 static void MSDD_GetCommandInformation(MSCbw *cbw,
00073 unsigned int *length,
00074 unsigned char *type)
00075 {
00076
00077 (*length) = cbw->dCBWDataTransferLength;
00078
00079 if (*length == 0) {
00080
00081 (*type) = MSDD_NO_TRANSFER;
00082 }
00083 else if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) != 0) {
00084
00085 (*type) = MSDD_DEVICE_TO_HOST;
00086 }
00087 else {
00088
00089 (*type) = MSDD_HOST_TO_DEVICE;
00090 }
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 static unsigned char MSDD_PreProcessCommand(MSDDriver *pMsdDriver)
00103 {
00104 unsigned int hostLength = 0;
00105 unsigned int deviceLength = 0;
00106 unsigned char hostType;
00107 unsigned char deviceType;
00108 unsigned char isCommandSupported;
00109 MSDCommandState *commandState = &(pMsdDriver->commandState);
00110 MSCsw *csw = &(commandState->csw);
00111 MSCbw *cbw = &(commandState->cbw);
00112 MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
00113
00114
00115
00116 MSDD_GetCommandInformation(cbw, &hostLength, &hostType);
00117
00118
00119 isCommandSupported = SBC_GetCommandInformation(cbw->pCommand,
00120 &deviceLength,
00121 &deviceType,
00122 lun);
00123
00124
00125 csw->dCSWDataResidue = 0;
00126 csw->bCSWStatus = MSD_CSW_COMMAND_PASSED;
00127
00128
00129 if (isCommandSupported) {
00130
00131
00132 if(hostType == MSDD_NO_TRANSFER) {
00133
00134
00135 if(deviceType == MSDD_NO_TRANSFER) {
00136
00137
00138 commandState->postprocess = 0;
00139 commandState->length = 0;
00140 }
00141 else if(deviceType == MSDD_DEVICE_TO_HOST) {
00142
00143
00144 TRACE_WARNING(
00145 "MSDD_PreProcessCommand: Case 2\n\r");
00146 commandState->postprocess = MSDD_CASE_PHASE_ERROR;
00147 commandState->length = 0;
00148 }
00149 else {
00150
00151
00152 TRACE_WARNING(
00153 "MSDD_PreProcessCommand: Case 3\n\r");
00154 commandState->postprocess = MSDD_CASE_PHASE_ERROR;
00155 commandState->length = 0;
00156 }
00157 }
00158
00159
00160 else if(hostType == MSDD_DEVICE_TO_HOST) {
00161
00162 if(deviceType == MSDD_NO_TRANSFER) {
00163
00164 TRACE_WARNING(
00165 "MSDD_PreProcessCommand: Case 4\n\r");
00166 commandState->postprocess = MSDD_CASE_STALL_IN;
00167 commandState->length = 0;
00168 csw->dCSWDataResidue = hostLength;
00169 }
00170 else if(deviceType == MSDD_DEVICE_TO_HOST) {
00171
00172 if(hostLength > deviceLength) {
00173
00174
00175 TRACE_WARNING(
00176 "MSDD_PreProcessCommand: Case 5\n\r");
00177 commandState->postprocess = MSDD_CASE_STALL_IN;
00178 commandState->length = deviceLength;
00179 csw->dCSWDataResidue = hostLength - deviceLength;
00180 }
00181 else if(hostLength == deviceLength) {
00182
00183
00184 commandState->postprocess = 0;
00185 commandState->length = deviceLength;
00186 }
00187 else {
00188
00189
00190 TRACE_WARNING(
00191 "MSDD_PreProcessCommand: Case 7\n\r");
00192 commandState->postprocess = MSDD_CASE_PHASE_ERROR;
00193 commandState->length = hostLength;
00194 }
00195 }
00196 else {
00197
00198
00199 TRACE_WARNING(
00200 "MSDD_PreProcessCommand: Case 8\n\r");
00201 commandState->postprocess =
00202 MSDD_CASE_STALL_IN | MSDD_CASE_PHASE_ERROR;
00203 commandState->length = 0;
00204 }
00205 }
00206 else if(hostType == MSDD_HOST_TO_DEVICE) {
00207
00208 if(deviceType == MSDD_NO_TRANSFER) {
00209
00210
00211 TRACE_WARNING(
00212 "MSDD_PreProcessCommand: Case 9\n\r");
00213 commandState->postprocess = MSDD_CASE_STALL_OUT;
00214 commandState->length = 0;
00215 csw->dCSWDataResidue = hostLength;
00216 }
00217 else if(deviceType == MSDD_DEVICE_TO_HOST) {
00218
00219
00220 TRACE_WARNING(
00221 "MSDD_PreProcessCommand: Case 10\n\r");
00222 commandState->postprocess =
00223 MSDD_CASE_STALL_OUT | MSDD_CASE_PHASE_ERROR;
00224 commandState->length = 0;
00225 }
00226 else {
00227
00228 if(hostLength > deviceLength) {
00229
00230
00231 TRACE_WARNING(
00232 "MSDD_PreProcessCommand: Case 11\n\r");
00233 commandState->postprocess = MSDD_CASE_STALL_OUT;
00234
00235
00236 commandState->length = 0;
00237 csw->dCSWDataResidue = deviceLength;
00238 }
00239 else if(hostLength == deviceLength) {
00240
00241
00242
00243
00244 commandState->postprocess = 0;
00245 commandState->length = deviceLength;
00246 }
00247 else {
00248
00249
00250 TRACE_WARNING(
00251 "MSDD_PreProcessCommand: Case 13\n\r");
00252 commandState->postprocess = MSDD_CASE_PHASE_ERROR;
00253 commandState->length = hostLength;
00254 }
00255 }
00256 }
00257 }
00258
00259 return isCommandSupported;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 static unsigned char MSDD_PostProcessCommand(MSDDriver *pMsdDriver)
00273 {
00274 MSDCommandState *commandState = &(pMsdDriver->commandState);
00275 MSCsw *csw = &(commandState->csw);
00276 unsigned char haltStatus = 0;
00277
00278
00279 if ((commandState->postprocess & MSDD_CASE_STALL_IN) != 0) {
00280
00281 TRACE_INFO_WP("StallIn ");
00282
00283 USBD_Halt(commandState->pipeIN);
00284 haltStatus = 1;
00285 }
00286
00287
00288 if ((commandState->postprocess & MSDD_CASE_STALL_OUT) != 0) {
00289
00290 TRACE_INFO_WP("StallOut ");
00291
00292 USBD_Halt(commandState->pipeOUT);
00293 haltStatus = 1;
00294 }
00295
00296
00297 if ((commandState->postprocess & MSDD_CASE_PHASE_ERROR) != 0) {
00298
00299 TRACE_INFO_WP("PhaseErr ");
00300 csw->bCSWStatus = MSD_CSW_PHASE_ERROR;
00301 }
00302
00303 return haltStatus;
00304 }
00305
00306
00307
00308
00309
00310
00311 static unsigned char MSDD_ProcessCommand(MSDDriver * pMsdDriver)
00312 {
00313 unsigned char status;
00314 MSDCommandState *commandState = &(pMsdDriver->commandState);
00315 MSCbw *cbw = &(commandState->cbw);
00316 MSCsw *csw = &(commandState->csw);
00317 MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
00318 unsigned char isCommandComplete = 0;
00319
00320
00321 if (cbw->bCBWLUN > pMsdDriver->maxLun) {
00322
00323 TRACE_WARNING(
00324 "MSDD_ProcessCommand: LUN %d not exist\n\r", cbw->bCBWLUN);
00325 status = MSDD_STATUS_ERROR;
00326 }
00327 else {
00328
00329
00330 if (pMsdDriver->maxLun > 0) {
00331
00332 TRACE_INFO_WP("LUN%d ", cbw->bCBWLUN);
00333 }
00334
00335 status = SBC_ProcessCommand(lun, commandState);
00336 }
00337
00338
00339 if (status == MSDD_STATUS_PARAMETER) {
00340
00341 TRACE_WARNING(
00342 "MSDD_ProcessCommand: Unknown cmd 0x%02X\n\r",
00343 cbw->pCommand[0]);
00344
00345
00346 SBC_UpdateSenseData(&(lun->requestSenseData),
00347 SBC_SENSE_KEY_ILLEGAL_REQUEST,
00348 SBC_ASC_INVALID_FIELD_IN_CDB,
00349 0);
00350
00351
00352 csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
00353 isCommandComplete = 1;
00354
00355
00356 if (((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0)
00357 && (cbw->dCBWDataTransferLength > 0)) {
00358
00359
00360
00361 commandState->postprocess = MSDD_CASE_STALL_OUT;
00362 TRACE_INFO_WP("StaOUT ");
00363 }
00364 else {
00365
00366
00367
00368 commandState->postprocess = MSDD_CASE_STALL_IN;
00369 TRACE_INFO_WP("StaIN ");
00370 }
00371 }
00372 else if (status == MSDD_STATUS_ERROR) {
00373
00374 TRACE_WARNING("MSD_ProcessCommand: Cmd %x fail\n\r",
00375 ((SBCCommand*)commandState->cbw.pCommand)->bOperationCode);
00376
00377
00378 SBC_UpdateSenseData(&(lun->requestSenseData),
00379 SBC_SENSE_KEY_MEDIUM_ERROR,
00380 SBC_ASC_INVALID_FIELD_IN_CDB,
00381 0);
00382
00383
00384 csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
00385 isCommandComplete = 1;
00386 }
00387 else if (status == MSDD_STATUS_RW) {
00388
00389 csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
00390 isCommandComplete = 1;
00391 }
00392 else {
00393
00394
00395 SBC_UpdateSenseData(&(lun->requestSenseData),
00396 SBC_SENSE_KEY_NO_SENSE,
00397 0,
00398 0);
00399
00400
00401 if (status == MSDD_STATUS_SUCCESS) {
00402
00403 isCommandComplete = 1;
00404 }
00405 }
00406
00407
00408 if (isCommandComplete) {
00409
00410 TRACE_INFO_WP("Cplt ");
00411
00412
00413 if (commandState->length != 0) {
00414
00415 csw->dCSWDataResidue += commandState->length;
00416
00417
00418 if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0) {
00419
00420
00421
00422 commandState->postprocess = MSDD_CASE_STALL_OUT;
00423 TRACE_INFO_WP("StaOUT ");
00424 }
00425 else {
00426
00427
00428
00429 commandState->postprocess = MSDD_CASE_STALL_IN;
00430 TRACE_INFO_WP("StaIN ");
00431 }
00432 }
00433
00434
00435 commandState->state = 0;
00436 }
00437
00438 return isCommandComplete;
00439 }
00440
00441
00442
00443
00444
00445 void MSDD_StateMachine(MSDDriver * pMsdDriver)
00446 {
00447 MSDCommandState *commandState = &(pMsdDriver->commandState);
00448 MSCbw *cbw = &(commandState->cbw);
00449 MSCsw *csw = &(commandState->csw);
00450 MSDTransfer *transfer = &(commandState->transfer);
00451 unsigned char status;
00452
00453
00454 switch (pMsdDriver->state) {
00455
00456 case MSDD_STATE_READ_CBW:
00457
00458
00459 transfer->semaphore = 0;
00460 #if 1
00461 status = USBD_Read(commandState->pipeOUT,
00462 cbw,
00463 MSD_CBW_SIZE,
00464 (TransferCallback) MSDDriver_Callback,
00465 (void *) transfer);
00466 #else
00467 status = MSDD_Read(cbw,
00468 MSD_CBW_SIZE,
00469 (TransferCallback) MSDDriver_Callback,
00470 (void *) transfer);
00471 #endif
00472
00473
00474 if (status == USBD_STATUS_SUCCESS) {
00475
00476
00477 pMsdDriver->state = MSDD_STATE_WAIT_CBW;
00478 }
00479 break;
00480
00481
00482 case MSDD_STATE_WAIT_CBW:
00483
00484
00485 if (transfer->semaphore > 0) {
00486
00487
00488 transfer->semaphore--;
00489
00490
00491 if (transfer->status == USBD_STATUS_SUCCESS) {
00492
00493 TRACE_INFO_WP("\n\r------------------------------\n\r");
00494
00495
00496 pMsdDriver->state = MSDD_STATE_PROCESS_CBW;
00497 }
00498 else if (transfer->status == USBD_STATUS_RESET) {
00499
00500 TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
00501 pMsdDriver->state = MSDD_STATE_READ_CBW;
00502 }
00503 else {
00504
00505 TRACE_WARNING(
00506 "MSDD_StateMachine: Failed to read CBW\n\r");
00507 pMsdDriver->state = MSDD_STATE_READ_CBW;
00508 }
00509 }
00510 break;
00511
00512
00513 case MSDD_STATE_PROCESS_CBW:
00514
00515
00516 if (commandState->state == 0) {
00517
00518
00519 csw->dCSWTag = cbw->dCBWTag;
00520
00521
00522 if ((transfer->transferred != MSD_CBW_SIZE) ||
00523 (transfer->remaining != 0)) {
00524
00525 TRACE_WARNING(
00526 "MSDD_StateMachine: Invalid CBW (len %d)\n\r",
00527 (int)transfer->transferred);
00528
00529
00530 pMsdDriver->waitResetRecovery = 1;
00531
00532
00533
00534 USBD_Halt(commandState->pipeIN);
00535 USBD_Halt(commandState->pipeOUT);
00536
00537 csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
00538 pMsdDriver->state = MSDD_STATE_READ_CBW;
00539
00540 }
00541
00542 else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) {
00543
00544 TRACE_WARNING(
00545 "MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r");
00546
00547
00548 pMsdDriver->waitResetRecovery = 1;
00549
00550
00551
00552 USBD_Halt(commandState->pipeIN);
00553 USBD_Halt(commandState->pipeOUT);
00554
00555 csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
00556 pMsdDriver->state = MSDD_STATE_READ_CBW;
00557 }
00558 else {
00559
00560
00561 MSDD_PreProcessCommand(pMsdDriver);
00562 }
00563 }
00564
00565
00566 if (csw->bCSWStatus == MSDD_STATUS_SUCCESS) {
00567
00568 if (MSDD_ProcessCommand(pMsdDriver)) {
00569
00570
00571 if (MSDD_PostProcessCommand(pMsdDriver)) {
00572
00573 TRACE_INFO_WP("WaitHALT ");
00574 pMsdDriver->state = MSDD_STATE_WAIT_HALT;
00575 }
00576 else {
00577
00578 pMsdDriver->state = MSDD_STATE_SEND_CSW;
00579 }
00580 }
00581 TRACE_INFO_WP("\n\r");
00582 }
00583
00584 break;
00585
00586
00587 case MSDD_STATE_SEND_CSW:
00588
00589
00590 csw->dCSWSignature = MSD_CSW_SIGNATURE;
00591
00592
00593 #if 1
00594 status = USBD_Write(commandState->pipeIN,
00595 csw,
00596 MSD_CSW_SIZE,
00597 (TransferCallback) MSDDriver_Callback,
00598 (void *) transfer);
00599 #else
00600 status = MSDD_Write(csw,
00601 MSD_CSW_SIZE,
00602 (TransferCallback) MSDDriver_Callback,
00603 (void *) transfer);
00604 #endif
00605
00606
00607 if (status == USBD_STATUS_SUCCESS) {
00608
00609 TRACE_INFO_WP("SendCSW ");
00610
00611
00612 pMsdDriver->state = MSDD_STATE_WAIT_CSW;
00613 }
00614 break;
00615
00616
00617 case MSDD_STATE_WAIT_CSW:
00618
00619
00620 if (transfer->semaphore > 0) {
00621
00622
00623 transfer->semaphore--;
00624
00625
00626 if (transfer->status == USBD_STATUS_RESET) {
00627
00628 TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
00629 }
00630 else if (transfer->status == USBD_STATUS_ABORTED) {
00631
00632 TRACE_WARNING(
00633 "MSDD_StateMachine: Failed to send CSW\n\r");
00634 }
00635 else {
00636
00637 TRACE_INFO_WP("ok");
00638 }
00639
00640
00641 pMsdDriver->state = MSDD_STATE_READ_CBW;
00642 }
00643 break;
00644
00645
00646 case MSDD_STATE_WAIT_HALT:
00647
00648
00649 if (!USBD_IsHalted(commandState->pipeIN)) {
00650
00651 pMsdDriver->state = MSDD_STATE_SEND_CSW;
00652 }
00653 break;
00654 }
00655 }
00656
00657