Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
usbd_msc.c
00001 /** 00002 * @file usbd_msc.c 00003 * @brief Mass Storage Class driver 00004 * 00005 * DAPLink Interface Firmware 00006 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved 00007 * SPDX-License-Identifier: Apache-2.0 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00010 * not use this file except in compliance with the License. 00011 * You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00017 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 */ 00021 00022 #include <string.h> 00023 00024 #include "rl_usb.h" 00025 #include "usb_for_lib.h" 00026 #include "util.h" 00027 00028 BOOL USBD_MSC_MediaReady = __FALSE; 00029 BOOL USBD_MSC_ReadOnly = __FALSE; 00030 U32 USBD_MSC_MemorySize; 00031 U32 USBD_MSC_BlockSize; 00032 U32 USBD_MSC_BlockGroup; 00033 U32 USBD_MSC_BlockCount; 00034 U8 *USBD_MSC_BlockBuf; 00035 00036 MSC_CBW USBD_MSC_CBW; /* Command Block Wrapper */ 00037 MSC_CSW USBD_MSC_CSW; /* Command Status Wrapper */ 00038 00039 BOOL USBD_MSC_MediaReadyEx = __FALSE; /* Previous state of Media ready */ 00040 BOOL MemOK; /* Memory OK */ 00041 00042 U32 Block; /* R/W Block */ 00043 U32 Offset; /* R/W Offset */ 00044 U32 Length; /* R/W Length */ 00045 00046 U8 BulkStage; /* Bulk Stage */ 00047 U32 BulkLen; /* Bulk In/Out Length */ 00048 00049 00050 /* Dummy Weak Functions that need to be provided by user */ 00051 __weak void usbd_msc_init() 00052 { 00053 00054 } 00055 __weak void usbd_msc_read_sect(U32 block, U8 *buf, U32 num_of_blocks) 00056 { 00057 00058 } 00059 __weak void usbd_msc_write_sect(U32 block, U8 *buf, U32 num_of_blocks) 00060 { 00061 00062 } 00063 __weak void usbd_msc_start_stop(BOOL start) 00064 { 00065 00066 } 00067 00068 00069 /* 00070 * Set Stall for USB Device MSC Endpoint 00071 * Parameters: EPNum: USB Device Endpoint Number 00072 * EPNum.0..3: Address 00073 * EPNum.7: Dir 00074 * Return Value: None 00075 */ 00076 00077 void USBD_MSC_SetStallEP(U32 EPNum) /* set EP halt status according stall status */ 00078 { 00079 USBD_SetStallEP(EPNum); 00080 USBD_EndPointHalt |= (EPNum & 0x80) ? ((1 << 16) << (EPNum & 0x0F)) : (1 << EPNum); 00081 } 00082 00083 00084 /* 00085 * Clear Stall for USB Device MSC Endpoint 00086 * Parameters: EPNum: USB Device Endpoint Number 00087 * EPNum.0..3: Address 00088 * EPNum.7: Dir 00089 * Return Value: None 00090 */ 00091 00092 void USBD_MSC_ClrStallEP(U32 EPNum) /* clear EP halt status according stall status */ 00093 { 00094 U32 n, m; 00095 n = USBD_SetupPacket.wIndexL & 0x8F; 00096 m = (n & 0x80) ? ((1 << 16) << (n & 0x0F)) : (1 << n); 00097 00098 if ((n == (usbd_msc_ep_bulkin | 0x80)) && ((USBD_EndPointHalt & m) != 0)) { 00099 /* Compliance Test: rewrite CSW after unstall */ 00100 if (USBD_MSC_CSW.dSignature == MSC_CSW_Signature) { 00101 USBD_WriteEP((usbd_msc_ep_bulkin | 0x80), (U8 *)&USBD_MSC_CSW, sizeof(USBD_MSC_CSW)); 00102 } 00103 } 00104 } 00105 00106 00107 /* 00108 * USB Device MSC Mass Storage Reset Request Callback 00109 * Called automatically on USB Device Mass Storage Reset Request 00110 * Parameters: None 00111 * Return Value: TRUE - Success, FALSE - Error 00112 */ 00113 00114 BOOL USBD_MSC_Reset(void) 00115 { 00116 USBD_EndPointStall = 0x00000000; /* EP must stay stalled */ 00117 USBD_MSC_CSW.dSignature = 0; /* invalid signature */ 00118 BulkStage = MSC_BS_RESET; 00119 return (__TRUE); 00120 } 00121 00122 00123 /* 00124 * USB Device MSC Get Max LUN Request Callback 00125 * Called automatically on USB Device Get Max LUN Request 00126 * Parameters: None 00127 * Return Value: TRUE - Success, FALSE - Error 00128 */ 00129 00130 BOOL USBD_MSC_GetMaxLUN(void) 00131 { 00132 USBD_EP0Buf[0] = 0; /* one LUN associated with this device */ 00133 return (__TRUE); 00134 } 00135 00136 00137 /* 00138 * USB Device Check Media Ready 00139 * Parameters: None 00140 * Return Value: TRUE - Success, FALSE - Error 00141 */ 00142 00143 BOOL USBD_MSC_CheckMedia(void) 00144 { 00145 USBD_MSC_MediaReadyEx = USBD_MSC_MediaReady; 00146 00147 if (!USBD_MSC_MediaReady) { 00148 if (USBD_MSC_CBW.dDataLength) { 00149 if ((USBD_MSC_CBW.bmFlags & 0x80) != 0) { 00150 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00151 } else { 00152 if (USBD_MSC_CSW.dDataResidue != BulkLen) { 00153 // Only stall if this isn't the last transfer 00154 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00155 } 00156 } 00157 } 00158 00159 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; 00160 USBD_MSC_SetCSW(); 00161 return (__FALSE); 00162 } 00163 00164 return (__TRUE); 00165 } 00166 00167 00168 /* 00169 * USB Device MSC Memory Read Callback 00170 * Called automatically on USB Device Memory Read Event 00171 * Parameters: None 00172 * Return Value: None 00173 */ 00174 00175 void USBD_MSC_MemoryRead(void) 00176 { 00177 U32 n, m; 00178 00179 if (Block >= USBD_MSC_BlockCount) { 00180 n = 0; 00181 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00182 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00183 USBD_MSC_SetCSW(); 00184 } else { 00185 if (Length > usbd_msc_maxpacketsize[USBD_HighSpeed]) { 00186 n = usbd_msc_maxpacketsize[USBD_HighSpeed]; 00187 } else { 00188 n = Length; 00189 } 00190 } 00191 00192 if (!USBD_MSC_CheckMedia()) { 00193 n = 0; 00194 } 00195 00196 if ((Offset == 0) && (n != 0)) { 00197 m = (Length + (USBD_MSC_BlockSize - 1)) / USBD_MSC_BlockSize; 00198 00199 if (m > USBD_MSC_BlockGroup) { 00200 m = USBD_MSC_BlockGroup; 00201 } 00202 00203 usbd_msc_read_sect(Block, USBD_MSC_BlockBuf, m); 00204 } 00205 00206 if (n) { 00207 USBD_WriteEP(usbd_msc_ep_bulkin | 0x80, &USBD_MSC_BlockBuf[Offset], n); 00208 Offset += n; 00209 Length -= n; 00210 } 00211 00212 if (Offset == USBD_MSC_BlockGroup * USBD_MSC_BlockSize) { 00213 Offset = 0; 00214 Block += USBD_MSC_BlockGroup; 00215 } 00216 00217 USBD_MSC_CSW.dDataResidue -= n; 00218 00219 if (!n) { 00220 return; 00221 } 00222 00223 if (Length == 0) { 00224 BulkStage = MSC_BS_DATA_IN_LAST; 00225 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00226 } 00227 } 00228 00229 00230 /* 00231 * USB Device MSC Memory Write Callback 00232 * Called automatically on USB Device Memory Write Event 00233 * Parameters: None 00234 * Return Value: None 00235 */ 00236 00237 void USBD_MSC_MemoryWrite(void) 00238 { 00239 U32 n; 00240 00241 if (Block >= USBD_MSC_BlockCount) { 00242 BulkLen = 0; 00243 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00244 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00245 USBD_MSC_SetCSW(); 00246 } 00247 00248 if (!USBD_MSC_CheckMedia()) { 00249 BulkLen = 0; 00250 } 00251 00252 if (Offset + BulkLen > USBD_MSC_BlockSize) { 00253 // This write would have overflowed USBD_MSC_BlockBuf 00254 util_assert(0); 00255 return; 00256 } 00257 00258 for (n = 0; n < BulkLen; n++) { 00259 USBD_MSC_BlockBuf[Offset + n] = USBD_MSC_BulkBuf[n]; 00260 } 00261 00262 Offset += BulkLen; 00263 Length -= BulkLen; 00264 00265 if (BulkLen) { 00266 if ((Length == 0) && (Offset != 0)) { 00267 n = (Offset + (USBD_MSC_BlockSize - 1)) / USBD_MSC_BlockSize; 00268 00269 if (n > USBD_MSC_BlockGroup) { 00270 n = USBD_MSC_BlockGroup; 00271 } 00272 00273 usbd_msc_write_sect(Block, USBD_MSC_BlockBuf, n); 00274 Offset = 0; 00275 Block += n; 00276 } else if (Offset == USBD_MSC_BlockGroup * USBD_MSC_BlockSize) { 00277 usbd_msc_write_sect(Block, USBD_MSC_BlockBuf, USBD_MSC_BlockGroup); 00278 Offset = 0; 00279 Block += USBD_MSC_BlockGroup; 00280 } 00281 } 00282 00283 USBD_MSC_CSW.dDataResidue -= BulkLen; 00284 00285 if (!BulkLen) { 00286 return; 00287 } 00288 00289 if ((Length == 0) || (BulkStage == MSC_BS_CSW)) { 00290 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00291 USBD_MSC_SetCSW(); 00292 } 00293 } 00294 00295 00296 /* 00297 * USB Device MSC Memory Verify Callback 00298 * Called automatically on USB Device Memory Verify Event 00299 * Parameters: None 00300 * Return Value: None 00301 */ 00302 00303 void USBD_MSC_MemoryVerify(void) 00304 { 00305 U32 n; 00306 00307 if (Block >= USBD_MSC_BlockCount) { 00308 BulkLen = 0; 00309 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00310 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00311 USBD_MSC_SetCSW(); 00312 } 00313 00314 if (!USBD_MSC_CheckMedia()) { 00315 BulkLen = 0; 00316 } 00317 00318 if (BulkLen) { 00319 if ((Offset == 0) && (BulkLen != 0)) { 00320 n = (Length + (USBD_MSC_BlockSize - 1)) / USBD_MSC_BlockSize; 00321 00322 if (n > USBD_MSC_BlockGroup) { 00323 n = USBD_MSC_BlockGroup; 00324 } 00325 00326 usbd_msc_read_sect(Block, USBD_MSC_BlockBuf, n); 00327 } 00328 00329 for (n = 0; n < BulkLen; n++) { 00330 if (USBD_MSC_BlockBuf[Offset + n] != USBD_MSC_BulkBuf[n]) { 00331 MemOK = __FALSE; 00332 break; 00333 } 00334 } 00335 } 00336 00337 Offset += BulkLen; 00338 Length -= BulkLen; 00339 00340 if (Offset == USBD_MSC_BlockGroup * USBD_MSC_BlockSize) { 00341 Offset = 0; 00342 Block += USBD_MSC_BlockGroup; 00343 } 00344 00345 USBD_MSC_CSW.dDataResidue -= BulkLen; 00346 00347 if (!BulkLen) { 00348 return; 00349 } 00350 00351 if ((Length == 0) || (BulkStage == MSC_BS_CSW)) { 00352 USBD_MSC_CSW.bStatus = (MemOK) ? CSW_CMD_PASSED : CSW_CMD_FAILED; 00353 USBD_MSC_SetCSW(); 00354 } 00355 } 00356 00357 00358 /* 00359 * USB Device MSC SCSI Read/Write Setup Callback 00360 * Parameters: None 00361 * Return Value: TRUE - Success, FALSE - Error 00362 */ 00363 00364 BOOL USBD_MSC_RWSetup(void) 00365 { 00366 U32 n; 00367 /* Logical Block Address of First Block */ 00368 n = (USBD_MSC_CBW.CB[2] << 24) | 00369 (USBD_MSC_CBW.CB[3] << 16) | 00370 (USBD_MSC_CBW.CB[4] << 8) | 00371 (USBD_MSC_CBW.CB[5] << 0); 00372 Block = n; 00373 Offset = 0; 00374 00375 /* Number of Blocks to transfer */ 00376 switch (USBD_MSC_CBW.CB[0]) { 00377 case SCSI_WRITE10: 00378 case SCSI_VERIFY10: 00379 if (!USBD_MSC_CheckMedia()) { 00380 return (__FALSE); 00381 } 00382 00383 case SCSI_READ10: 00384 n = (USBD_MSC_CBW.CB[7] << 8) | 00385 (USBD_MSC_CBW.CB[8] << 0); 00386 break; 00387 00388 case SCSI_WRITE12: 00389 if (!USBD_MSC_CheckMedia()) { 00390 return (__FALSE); 00391 } 00392 00393 case SCSI_READ12: 00394 n = (USBD_MSC_CBW.CB[6] << 24) | 00395 (USBD_MSC_CBW.CB[7] << 16) | 00396 (USBD_MSC_CBW.CB[8] << 8) | 00397 (USBD_MSC_CBW.CB[9] << 0); 00398 break; 00399 } 00400 00401 Length = n * USBD_MSC_BlockSize; 00402 00403 if (USBD_MSC_CBW.dDataLength == 0) { /* host requests no data */ 00404 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; 00405 USBD_MSC_SetCSW(); 00406 return (__FALSE); 00407 } 00408 00409 if (USBD_MSC_CBW.dDataLength != Length) { 00410 if ((USBD_MSC_CBW.bmFlags & 0x80) != 0) { /* stall appropriate EP */ 00411 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00412 } else { 00413 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00414 } 00415 00416 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; 00417 USBD_MSC_SetCSW(); 00418 return (__FALSE); 00419 } 00420 00421 return (__TRUE); 00422 } 00423 00424 00425 /* 00426 * USB Device Check Data IN Format 00427 * Parameters: None 00428 * Return Value: TRUE - Success, FALSE - Error 00429 */ 00430 00431 BOOL USBD_MSC_DataInFormat(void) 00432 { 00433 if (USBD_MSC_CBW.dDataLength == 0) { 00434 USBD_MSC_CSW.bStatus = CSW_PHASE_ERROR; 00435 USBD_MSC_SetCSW(); 00436 return (__FALSE); 00437 } 00438 00439 if ((USBD_MSC_CBW.bmFlags & 0x80) == 0) { 00440 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00441 USBD_MSC_CSW.bStatus = CSW_PHASE_ERROR; 00442 USBD_MSC_SetCSW(); 00443 return (__FALSE); 00444 } 00445 00446 return (__TRUE); 00447 } 00448 00449 00450 /* 00451 * USB Device Perform Data IN Transfer 00452 * Parameters: None 00453 * Return Value: None 00454 */ 00455 00456 void USBD_MSC_DataInTransfer(void) 00457 { 00458 if (BulkLen >= USBD_MSC_CBW.dDataLength) { 00459 BulkLen = USBD_MSC_CBW.dDataLength; 00460 BulkStage = MSC_BS_DATA_IN_LAST; 00461 } else { 00462 BulkStage = MSC_BS_DATA_IN_LAST_STALL; /* short or zero packet */ 00463 } 00464 00465 USBD_WriteEP(usbd_msc_ep_bulkin | 0x80, USBD_MSC_BulkBuf, BulkLen); 00466 USBD_MSC_CSW.dDataResidue -= BulkLen; 00467 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00468 } 00469 00470 00471 /* 00472 * USB Device MSC SCSI Test Unit Ready Callback 00473 * Parameters: None 00474 * Return Value: None 00475 */ 00476 00477 void USBD_MSC_TestUnitReady(void) 00478 { 00479 if (USBD_MSC_CBW.dDataLength != 0) { 00480 if ((USBD_MSC_CBW.bmFlags & 0x80) != 0) { 00481 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00482 } else { 00483 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00484 } 00485 00486 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; 00487 USBD_MSC_SetCSW(); 00488 return; 00489 } 00490 00491 if (!USBD_MSC_CheckMedia()) { 00492 return; 00493 } 00494 00495 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00496 USBD_MSC_SetCSW(); 00497 } 00498 00499 00500 /* 00501 * USB Device MSC SCSI Request Sense Callback 00502 * Parameters: None 00503 * Return Value: None 00504 */ 00505 00506 void USBD_MSC_RequestSense(void) 00507 { 00508 if (!USBD_MSC_DataInFormat()) { 00509 return; 00510 } 00511 00512 USBD_MSC_BulkBuf[ 0] = 0x70; /* Response Code */ 00513 USBD_MSC_BulkBuf[ 1] = 0x00; 00514 00515 if ((USBD_MSC_MediaReadyEx ^ USBD_MSC_MediaReady) & USBD_MSC_MediaReady) { /* If media state changed to ready */ 00516 USBD_MSC_BulkBuf[ 2] = 0x06; /* UNIT ATTENTION */ 00517 USBD_MSC_BulkBuf[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */ 00518 USBD_MSC_BulkBuf[13] = 0x00; /* Additional Sense Code Qualifier */ 00519 USBD_MSC_MediaReadyEx = USBD_MSC_MediaReady; 00520 } else if (!USBD_MSC_MediaReady) { 00521 USBD_MSC_BulkBuf[ 2] = 0x02; /* NOT READY */ 00522 USBD_MSC_BulkBuf[12] = 0x3A; /* Additional Sense Code: Medium not present */ 00523 USBD_MSC_BulkBuf[13] = 0x00; /* Additional Sense Code Qualifier */ 00524 } else { 00525 if (USBD_MSC_CSW.bStatus == CSW_CMD_PASSED) { 00526 USBD_MSC_BulkBuf[ 2] = 0x00; /* NO SENSE */ 00527 USBD_MSC_BulkBuf[12] = 0x00; /* Additional Sense Code: No additional code */ 00528 USBD_MSC_BulkBuf[13] = 0x00; /* Additional Sense Code Qualifier */ 00529 } else { 00530 USBD_MSC_BulkBuf[ 2] = 0x05; /* ILLEGAL REQUEST */ 00531 USBD_MSC_BulkBuf[12] = 0x20; /* Additional Sense Code: Invalid command */ 00532 USBD_MSC_BulkBuf[13] = 0x00; /* Additional Sense Code Qualifier */ 00533 } 00534 } 00535 00536 USBD_MSC_BulkBuf[ 3] = 0x00; 00537 USBD_MSC_BulkBuf[ 4] = 0x00; 00538 USBD_MSC_BulkBuf[ 5] = 0x00; 00539 USBD_MSC_BulkBuf[ 6] = 0x00; 00540 USBD_MSC_BulkBuf[ 7] = 0x0A; /* Additional Length */ 00541 USBD_MSC_BulkBuf[ 8] = 0x00; 00542 USBD_MSC_BulkBuf[ 9] = 0x00; 00543 USBD_MSC_BulkBuf[10] = 0x00; 00544 USBD_MSC_BulkBuf[11] = 0x00; 00545 USBD_MSC_BulkBuf[14] = 0x00; 00546 USBD_MSC_BulkBuf[15] = 0x00; 00547 USBD_MSC_BulkBuf[16] = 0x00; 00548 USBD_MSC_BulkBuf[17] = 0x00; 00549 BulkLen = 18; 00550 USBD_MSC_DataInTransfer(); 00551 } 00552 00553 00554 /* 00555 * USB Device MSC SCSI Inquiry Callback 00556 * Parameters: None 00557 * Return Value: None 00558 */ 00559 00560 void USBD_MSC_Inquiry(void) 00561 { 00562 U8 i; 00563 U8 *ptr_str; 00564 00565 if (!USBD_MSC_DataInFormat()) { 00566 return; 00567 } 00568 00569 USBD_MSC_BulkBuf[ 0] = 0x00; /* Direct Access Device */ 00570 USBD_MSC_BulkBuf[ 1] = 0x80; /* RMB = 1: Removable Medium */ 00571 USBD_MSC_BulkBuf[ 2] = 0x02; /* Version: ANSI X3.131: 1994 */ 00572 USBD_MSC_BulkBuf[ 3] = 0x02; 00573 USBD_MSC_BulkBuf[ 4] = 36 - 4; /* Additional Length */ 00574 USBD_MSC_BulkBuf[ 5] = 0x00; /* SCCS = 0: No Storage Controller Component */ 00575 USBD_MSC_BulkBuf[ 6] = 0x00; 00576 USBD_MSC_BulkBuf[ 7] = 0x00; 00577 ptr_str = (U8 *)usbd_msc_inquiry_data; 00578 00579 for (i = 8; i < 36; i++) { /* Product Information + */ 00580 if (*ptr_str) { /* Product Revision Level */ 00581 USBD_MSC_BulkBuf[i] = *ptr_str++; 00582 } else { 00583 USBD_MSC_BulkBuf[i] = ' '; 00584 } 00585 } 00586 00587 BulkLen = 36; 00588 USBD_MSC_DataInTransfer(); 00589 } 00590 00591 00592 /* 00593 * USB Device MSC SCSI Start Stop Unit Callback 00594 * Parameters: None 00595 * Return Value: None 00596 */ 00597 00598 void USBD_MSC_StartStopUnit(void) 00599 { 00600 if (!USBD_MSC_CBW.CB[3]) { /* If power condition modifier is 0 */ 00601 USBD_MSC_MediaReady = USBD_MSC_CBW.CB[4] & 0x01; /* Media ready = START bit value */ 00602 usbd_msc_start_stop(USBD_MSC_MediaReady); 00603 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; /* Start Stop Unit -> pass */ 00604 USBD_MSC_SetCSW(); 00605 return; 00606 } 00607 00608 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; /* Start Stop Unit -> fail */ 00609 USBD_MSC_SetCSW(); 00610 } 00611 00612 00613 /* 00614 * USB Device MSC SCSI Media Removal Callback 00615 * Parameters: None 00616 * Return Value: None 00617 */ 00618 00619 void USBD_MSC_MediaRemoval(void) 00620 { 00621 if (USBD_MSC_CBW.CB[4] & 1) { /* If prevent */ 00622 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; /* Prevent media removal -> fail */ 00623 } else { /* If allow */ 00624 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; /* Allow media removal -> pass */ 00625 } 00626 00627 USBD_MSC_SetCSW(); 00628 } 00629 00630 00631 /* 00632 * USB Device MSC SCSI Mode Sense (6-Byte) Callback 00633 * Parameters: None 00634 * Return Value: None 00635 */ 00636 00637 void USBD_MSC_ModeSense6(void) 00638 { 00639 if (!USBD_MSC_DataInFormat()) { 00640 return; 00641 } 00642 00643 if (!USBD_MSC_CheckMedia()) { 00644 return; 00645 } 00646 00647 USBD_MSC_BulkBuf[ 0] = 0x03; 00648 USBD_MSC_BulkBuf[ 1] = 0x00; 00649 USBD_MSC_BulkBuf[ 2] = (USBD_MSC_ReadOnly << 7); 00650 USBD_MSC_BulkBuf[ 3] = 0x00; 00651 BulkLen = 4; 00652 00653 /* Win host requests maximum number of bytes but as all we have is 4 bytes we have 00654 to tell host back that it is all we have, that's why we correct residue */ 00655 if (USBD_MSC_CSW.dDataResidue > BulkLen) { 00656 USBD_MSC_CBW.dDataLength = BulkLen; 00657 USBD_MSC_CSW.dDataResidue = BulkLen; 00658 } 00659 00660 USBD_MSC_DataInTransfer(); 00661 } 00662 00663 00664 /* 00665 * USB Device MSC SCSI Mode Sense (10-Byte) Callback 00666 * Parameters: None 00667 * Return Value: None 00668 */ 00669 00670 void USBD_MSC_ModeSense10(void) 00671 { 00672 if (!USBD_MSC_DataInFormat()) { 00673 return; 00674 } 00675 00676 if (!USBD_MSC_CheckMedia()) { 00677 return; 00678 } 00679 00680 USBD_MSC_BulkBuf[ 0] = 0x00; 00681 USBD_MSC_BulkBuf[ 1] = 0x06; 00682 USBD_MSC_BulkBuf[ 2] = 0x00; 00683 USBD_MSC_BulkBuf[ 3] = (USBD_MSC_ReadOnly << 7); 00684 USBD_MSC_BulkBuf[ 4] = 0x00; 00685 USBD_MSC_BulkBuf[ 5] = 0x00; 00686 USBD_MSC_BulkBuf[ 6] = 0x00; 00687 USBD_MSC_BulkBuf[ 7] = 0x00; 00688 BulkLen = 8; 00689 00690 /* Win host requests maximum number of bytes but as all we have is 8 bytes we have 00691 to tell host back that it is all we have, that's why we correct residue */ 00692 if (USBD_MSC_CSW.dDataResidue > BulkLen) { 00693 USBD_MSC_CBW.dDataLength = BulkLen; 00694 USBD_MSC_CSW.dDataResidue = BulkLen; 00695 } 00696 00697 USBD_MSC_DataInTransfer(); 00698 } 00699 00700 00701 /* 00702 * USB Device MSC SCSI Read Capacity Callback 00703 * Parameters: None 00704 * Return Value: None 00705 */ 00706 00707 void USBD_MSC_ReadCapacity(void) 00708 { 00709 if (!USBD_MSC_DataInFormat()) { 00710 return; 00711 } 00712 00713 if (!USBD_MSC_CheckMedia()) { 00714 return; 00715 } 00716 00717 /* Last Logical Block */ 00718 USBD_MSC_BulkBuf[ 0] = ((USBD_MSC_BlockCount - 1) >> 24) & 0xFF; 00719 USBD_MSC_BulkBuf[ 1] = ((USBD_MSC_BlockCount - 1) >> 16) & 0xFF; 00720 USBD_MSC_BulkBuf[ 2] = ((USBD_MSC_BlockCount - 1) >> 8) & 0xFF; 00721 USBD_MSC_BulkBuf[ 3] = ((USBD_MSC_BlockCount - 1) >> 0) & 0xFF; 00722 /* Block Length */ 00723 USBD_MSC_BulkBuf[ 4] = (USBD_MSC_BlockSize >> 24) & 0xFF; 00724 USBD_MSC_BulkBuf[ 5] = (USBD_MSC_BlockSize >> 16) & 0xFF; 00725 USBD_MSC_BulkBuf[ 6] = (USBD_MSC_BlockSize >> 8) & 0xFF; 00726 USBD_MSC_BulkBuf[ 7] = (USBD_MSC_BlockSize >> 0) & 0xFF; 00727 BulkLen = 8; 00728 USBD_MSC_DataInTransfer(); 00729 } 00730 00731 00732 /* 00733 * USB Device MSC SCSI Read Format Capacity Callback 00734 * Parameters: None 00735 * Return Value: None 00736 */ 00737 00738 void USBD_MSC_ReadFormatCapacity(void) 00739 { 00740 if (!USBD_MSC_DataInFormat()) { 00741 return; 00742 } 00743 00744 if (!USBD_MSC_CheckMedia()) { 00745 return; 00746 } 00747 00748 USBD_MSC_BulkBuf[ 0] = 0x00; 00749 USBD_MSC_BulkBuf[ 1] = 0x00; 00750 USBD_MSC_BulkBuf[ 2] = 0x00; 00751 USBD_MSC_BulkBuf[ 3] = 0x08; /* Capacity List Length */ 00752 /* Block Count */ 00753 USBD_MSC_BulkBuf[ 4] = (USBD_MSC_BlockCount >> 24) & 0xFF; 00754 USBD_MSC_BulkBuf[ 5] = (USBD_MSC_BlockCount >> 16) & 0xFF; 00755 USBD_MSC_BulkBuf[ 6] = (USBD_MSC_BlockCount >> 8) & 0xFF; 00756 USBD_MSC_BulkBuf[ 7] = (USBD_MSC_BlockCount >> 0) & 0xFF; 00757 /* Block Length */ 00758 USBD_MSC_BulkBuf[ 8] = 0x02; /* Descriptor Code: Formatted Media */ 00759 USBD_MSC_BulkBuf[ 9] = (USBD_MSC_BlockSize >> 16) & 0xFF; 00760 USBD_MSC_BulkBuf[10] = (USBD_MSC_BlockSize >> 8) & 0xFF; 00761 USBD_MSC_BulkBuf[11] = (USBD_MSC_BlockSize >> 0) & 0xFF; 00762 BulkLen = 12; 00763 00764 /* Win host requests maximum number of bytes but as all we have is 12 bytes we have 00765 to tell host back that it is all we have, that's why we correct residue */ 00766 if (USBD_MSC_CSW.dDataResidue > BulkLen) { 00767 USBD_MSC_CBW.dDataLength = BulkLen; 00768 USBD_MSC_CSW.dDataResidue = BulkLen; 00769 } 00770 00771 USBD_MSC_DataInTransfer(); 00772 } 00773 00774 00775 /* 00776 * USB Device MSC SCSI Synchronize Cache (10/16-Byte) Callback 00777 * Parameters: None 00778 * Return Value: None 00779 */ 00780 00781 void USBD_MSC_SynchronizeCache(void) 00782 { 00783 /* Synchronize check always passes as we always write data dirrectly 00784 so cache is always synchronized */ 00785 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00786 USBD_MSC_SetCSW(); 00787 } 00788 00789 00790 /* 00791 * USB Device MSC ATA Pass-Through Callback 00792 * Parameters: None 00793 * Return Value: None 00794 */ 00795 00796 void USBD_MSC_ATAPassThrough(void) 00797 { 00798 if (!USBD_MSC_DataInFormat()) { 00799 return; 00800 } 00801 00802 USBD_MSC_BulkBuf[ 0] = 0x02; 00803 USBD_MSC_BulkBuf[ 1] = 0x02; 00804 BulkLen = 2; 00805 BulkStage = MSC_BS_DATA_IN_LAST; 00806 00807 /* Win host requests maximum number of bytes but as all we have is 2 bytes we have 00808 to tell host back that it is all we have, that's why we correct residue */ 00809 if (USBD_MSC_CSW.dDataResidue > BulkLen) { 00810 USBD_MSC_CBW.dDataLength = BulkLen; 00811 USBD_MSC_CSW.dDataResidue = BulkLen; 00812 } 00813 00814 USBD_WriteEP(usbd_msc_ep_bulkin | 0x80, USBD_MSC_BulkBuf, BulkLen); 00815 USBD_MSC_CSW.dDataResidue -= BulkLen; 00816 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; 00817 } 00818 00819 /* 00820 * USB Device MSC Service Action (16-Byte) Callback 00821 * Parameters: None 00822 * Return Value: None 00823 */ 00824 00825 00826 void USBD_MSC_ServiceActionIn16(void) 00827 { 00828 if (!USBD_MSC_DataInFormat()) { 00829 return; 00830 } 00831 00832 USBD_MSC_BulkBuf[ 0] = 0x20; 00833 USBD_MSC_BulkBuf[ 1] = 0x00; 00834 USBD_MSC_BulkBuf[31] = 0x00; 00835 BulkLen = 32; 00836 BulkStage = MSC_BS_DATA_IN_LAST; 00837 USBD_WriteEP(usbd_msc_ep_bulkin | 0x80, USBD_MSC_BulkBuf, BulkLen); 00838 USBD_MSC_CSW.dDataResidue -= BulkLen; 00839 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; 00840 } 00841 00842 00843 /* 00844 * USB Device MSC Get Command Block Wrapper Callback 00845 * Parameters: None 00846 * Return Value: None 00847 */ 00848 00849 void USBD_MSC_GetCBW(void) 00850 { 00851 U32 n; 00852 U32 copy_size; 00853 copy_size = MIN(BulkLen, sizeof(USBD_MSC_CBW)); 00854 00855 for (n = 0; n < copy_size; n++) { 00856 *((U8 *)&USBD_MSC_CBW + n) = USBD_MSC_BulkBuf[n]; 00857 } 00858 00859 if ((BulkLen == sizeof(USBD_MSC_CBW)) && (USBD_MSC_CBW.dSignature == MSC_CBW_Signature)) { 00860 /* Valid USBD_MSC_CBW */ 00861 USBD_MSC_CSW.dTag = USBD_MSC_CBW.dTag; 00862 USBD_MSC_CSW.dDataResidue = USBD_MSC_CBW.dDataLength; 00863 00864 if ((USBD_MSC_CBW.bLUN > 0) || 00865 (USBD_MSC_CBW.bCBLength < 1) || 00866 (USBD_MSC_CBW.bCBLength > 16)) { 00867 fail: 00868 USBD_MSC_CSW.bStatus = CSW_CMD_FAILED; 00869 USBD_MSC_SetCSW(); 00870 } else { 00871 switch (USBD_MSC_CBW.CB[0]) { 00872 case SCSI_TEST_UNIT_READY: 00873 USBD_MSC_TestUnitReady(); 00874 break; 00875 00876 case SCSI_REQUEST_SENSE: 00877 USBD_MSC_RequestSense(); 00878 break; 00879 00880 case SCSI_FORMAT_UNIT: 00881 goto fail; 00882 00883 case SCSI_INQUIRY: 00884 USBD_MSC_Inquiry(); 00885 break; 00886 00887 case SCSI_START_STOP_UNIT: 00888 USBD_MSC_StartStopUnit(); 00889 break; 00890 00891 case SCSI_MEDIA_REMOVAL: 00892 USBD_MSC_MediaRemoval(); 00893 break; 00894 00895 case SCSI_MODE_SELECT6: 00896 goto fail; 00897 00898 case SCSI_MODE_SENSE6: 00899 USBD_MSC_ModeSense6(); 00900 break; 00901 00902 case SCSI_MODE_SELECT10: 00903 goto fail; 00904 00905 case SCSI_MODE_SENSE10: 00906 USBD_MSC_ModeSense10(); 00907 break; 00908 00909 case SCSI_READ_FORMAT_CAPACITIES: 00910 USBD_MSC_ReadFormatCapacity(); 00911 break; 00912 00913 case SCSI_READ_CAPACITY: 00914 USBD_MSC_ReadCapacity(); 00915 break; 00916 00917 case SCSI_ATA_COMMAND_PASS_THROUGH12: 00918 USBD_MSC_ATAPassThrough(); 00919 break; 00920 00921 case SCSI_SERVICE_ACTION_IN16: 00922 USBD_MSC_ServiceActionIn16(); 00923 break; 00924 00925 case SCSI_READ10: 00926 case SCSI_READ12: 00927 if (USBD_MSC_RWSetup()) { 00928 if ((USBD_MSC_CBW.bmFlags & 0x80) != 0) { 00929 BulkStage = MSC_BS_DATA_IN; 00930 USBD_MSC_MemoryRead(); 00931 } else { /* direction mismatch */ 00932 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00933 USBD_MSC_CSW.bStatus = CSW_PHASE_ERROR; 00934 USBD_MSC_SetCSW(); 00935 } 00936 } 00937 00938 break; 00939 00940 case SCSI_WRITE10: 00941 case SCSI_WRITE12: 00942 if (USBD_MSC_RWSetup()) { 00943 if ((USBD_MSC_CBW.bmFlags & 0x80) == 0) { 00944 BulkStage = MSC_BS_DATA_OUT; 00945 } else { /* direction mismatch */ 00946 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00947 USBD_MSC_CSW.bStatus = CSW_PHASE_ERROR; 00948 USBD_MSC_SetCSW(); 00949 } 00950 } 00951 00952 break; 00953 00954 case SCSI_VERIFY10: 00955 if ((USBD_MSC_CBW.CB[1] & 0x02) == 0) { 00956 // BYTCHK = 0 -> CRC Check (not implemented) 00957 USBD_MSC_CSW.bStatus = CSW_CMD_PASSED; 00958 USBD_MSC_SetCSW(); 00959 break; 00960 } 00961 00962 if (USBD_MSC_RWSetup()) { 00963 if ((USBD_MSC_CBW.bmFlags & 0x80) == 0) { 00964 BulkStage = MSC_BS_DATA_OUT; 00965 MemOK = __TRUE; 00966 } else { 00967 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00968 USBD_MSC_CSW.bStatus = CSW_PHASE_ERROR; 00969 USBD_MSC_SetCSW(); 00970 } 00971 } 00972 00973 break; 00974 00975 case SCSI_SYNC_CACHE10: 00976 case SCSI_SYNC_CACHE16: 00977 USBD_MSC_SynchronizeCache(); 00978 break; 00979 00980 case SCSI_REPORT_ID_INFO: 00981 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00982 goto fail; 00983 00984 default: 00985 goto fail; 00986 } 00987 } 00988 } else { 00989 /* Invalid USBD_MSC_CBW */ 00990 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 00991 /* set EP to stay stalled */ 00992 USBD_EndPointStall |= ((1 << 16) << (usbd_msc_ep_bulkin & 0x0F)); 00993 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 00994 /* set EP to stay stalled */ 00995 USBD_EndPointStall |= 1 << usbd_msc_ep_bulkout; 00996 BulkStage = MSC_BS_ERROR; 00997 } 00998 } 00999 01000 01001 /* 01002 * USB Device MSC Set Command Status Wrapper Callback 01003 * Parameters: None 01004 * Return Value: None 01005 */ 01006 01007 void USBD_MSC_SetCSW(void) 01008 { 01009 USBD_MSC_CSW.dSignature = MSC_CSW_Signature; 01010 USBD_WriteEP(usbd_msc_ep_bulkin | 0x80, (U8 *)&USBD_MSC_CSW, sizeof(USBD_MSC_CSW)); 01011 BulkStage = MSC_BS_CSW; 01012 } 01013 01014 01015 /* 01016 * USB Device MSC Bulk In Callback 01017 * Parameters: None 01018 * Return Value: None 01019 */ 01020 01021 void USBD_MSC_BulkIn(void) 01022 { 01023 switch (BulkStage) { 01024 case MSC_BS_DATA_IN: 01025 switch (USBD_MSC_CBW.CB[0]) { 01026 case SCSI_READ10: 01027 case SCSI_READ12: 01028 USBD_MSC_MemoryRead(); 01029 break; 01030 } 01031 01032 break; 01033 01034 case MSC_BS_DATA_IN_LAST: 01035 USBD_MSC_SetCSW(); 01036 break; 01037 01038 case MSC_BS_DATA_IN_LAST_STALL: 01039 USBD_MSC_SetStallEP(usbd_msc_ep_bulkin | 0x80); 01040 USBD_MSC_SetCSW(); 01041 break; 01042 01043 case MSC_BS_CSW: 01044 BulkStage = MSC_BS_CBW; 01045 break; 01046 01047 default: 01048 break; 01049 } 01050 } 01051 01052 01053 /* 01054 * USB Device MSC Bulk Out Callback 01055 * Parameters: None 01056 * Return Value: None 01057 */ 01058 01059 void USBD_MSC_BulkOut(void) 01060 { 01061 switch (BulkStage) { 01062 case MSC_BS_CBW: 01063 USBD_MSC_GetCBW(); 01064 break; 01065 01066 case MSC_BS_DATA_OUT: 01067 switch (USBD_MSC_CBW.CB[0]) { 01068 case SCSI_WRITE10: 01069 case SCSI_WRITE12: 01070 USBD_MSC_MemoryWrite(); 01071 break; 01072 01073 case SCSI_VERIFY10: 01074 USBD_MSC_MemoryVerify(); 01075 break; 01076 } 01077 break; 01078 01079 case MSC_BS_CSW: 01080 // Previous transfer must be complete 01081 // before the next transfer begins. 01082 // 01083 // If bulk out is stalled then just 01084 // drop this packet and don't assert. 01085 // This packet was left over from before 01086 // the transfer aborted with a stall. 01087 util_assert(USBD_EndPointHalt & (1 << usbd_msc_ep_bulkout)); 01088 break; 01089 01090 case MSC_BS_RESET: 01091 // If Bulk-Only Mass Storage Reset command was received on 01092 // Control Endpoint ignore next Bulk OUT transfer if it was not 01093 // a CBW (as it means it was a unprocessed leftover from 01094 // transfer before reset happened) 01095 BulkStage = MSC_BS_CBW; 01096 if (BulkLen == sizeof(USBD_MSC_CBW)) { 01097 // If it is a CBW size packet go process it as CBW 01098 USBD_MSC_GetCBW(); 01099 } 01100 break; 01101 01102 default: 01103 USBD_MSC_SetStallEP(usbd_msc_ep_bulkout); 01104 USBD_MSC_CSW.bStatus = CSW_PHASE_ERROR; 01105 USBD_MSC_SetCSW(); 01106 break; 01107 } 01108 } 01109 01110 /** \brief Handle Reset Events 01111 01112 The function handles Reset events. 01113 */ 01114 01115 void USBD_MSC_Reset_Event(void) 01116 { 01117 USBD_MSC_Reset(); 01118 } 01119 01120 /* 01121 * USB Device MSC Bulk In Endpoint Event Callback 01122 * Parameters: event: not used (just for compatibility) 01123 * Return Value: None 01124 */ 01125 01126 void USBD_MSC_EP_BULKIN_Event(U32 event) 01127 { 01128 USBD_MSC_BulkIn(); 01129 } 01130 01131 01132 /* 01133 * USB Device MSC Bulk Out Endpoint Event Callback 01134 * Parameters: event: not used (just for compatibility) 01135 * Return Value: None 01136 */ 01137 01138 void USBD_MSC_EP_BULKOUT_Event(U32 event) 01139 { 01140 BulkLen = USBD_ReadEP(usbd_msc_ep_bulkout, USBD_MSC_BulkBuf, USBD_MSC_BulkBufSize); 01141 USBD_MSC_BulkOut(); 01142 } 01143 01144 01145 /* 01146 * USB Device MSC Bulk In/Out Endpoint Event Callback 01147 * Parameters: event: USB Device Event 01148 * USBD_EVT_OUT: Output Event 01149 * USBD_EVT_IN: Input Event 01150 * Return Value: None 01151 */ 01152 01153 void USBD_MSC_EP_BULK_Event(U32 event) 01154 { 01155 if (event & USBD_EVT_OUT) { 01156 USBD_MSC_EP_BULKOUT_Event(0); 01157 } 01158 01159 if (event & USBD_EVT_IN) { 01160 USBD_MSC_EP_BULKIN_Event(0); 01161 } 01162 } 01163 01164 01165 #ifdef __RTX /* RTX tasks for handling events */ 01166 01167 /* 01168 * USB Device MSC Bulk In Endpoint Event Handler Task 01169 * Parameters: None 01170 * Return Value: None 01171 */ 01172 01173 __task void USBD_RTX_MSC_EP_BULKIN_Event(void) 01174 { 01175 for (;;) { 01176 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 01177 01178 if (usbd_os_evt_get() & USBD_EVT_IN) { 01179 USBD_MSC_EP_BULKIN_Event(0); 01180 } 01181 } 01182 } 01183 01184 01185 /* 01186 * USB Device MSC Bulk Out Endpoint Event Handler Task 01187 * Parameters: None 01188 * Return Value: None 01189 */ 01190 01191 __task void USBD_RTX_MSC_EP_BULKOUT_Event(void) 01192 { 01193 for (;;) { 01194 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 01195 01196 if (usbd_os_evt_get() & USBD_EVT_OUT) { 01197 USBD_MSC_EP_BULKOUT_Event(0); 01198 } 01199 } 01200 } 01201 01202 01203 /* 01204 * USB Device MSC Bulk In/Out Endpoint Event Handler Task 01205 * Parameters: None 01206 * Return Value: None 01207 */ 01208 01209 __task void USBD_RTX_MSC_EP_BULK_Event(void) 01210 { 01211 for (;;) { 01212 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 01213 USBD_MSC_EP_BULK_Event(usbd_os_evt_get()); 01214 } 01215 } 01216 #endif
Generated on Tue Jul 12 2022 15:37:27 by
1.7.2