Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbd_msc.c Source File

usbd_msc.c

Go to the documentation of this file.
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