Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MassStorage.cpp Source File

MassStorage.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Peter Barrett
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "stdlib.h"
00025 #include "stdio.h"
00026 #include "string.h"
00027 
00028 #include "Utils.h"
00029 #include "USBHost.h"
00030 
00031 
00032 int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize);
00033 int MassStorage_ReadBlock(int device, u32 block, u8* dst);
00034 int MassStorage_WriteBlock(int device, u32 block, const u8* dst);
00035 
00036 
00037 #define ERR_BAD_CSW_SIGNATURE -200
00038 
00039 #define CBW_SIGNATURE  0x43425355
00040 #define CSW_SIGNATURE  0x53425355
00041 
00042 //  Command Block
00043 typedef struct
00044 {
00045     u32 Signature;
00046     u32 Tag;
00047     u32 TransferLength;
00048     u8 Flags;
00049     u8 LUN;
00050     u8 CBLength;
00051     u8 CB[16];   // only 6 really
00052 } CBW;
00053 
00054 //  Status block
00055 typedef struct
00056 {
00057     u32 Signature;
00058     u32 Tag;
00059     u32 DataResidue;
00060     u8 Status;
00061 } CSW;
00062 
00063 
00064 //Eli Add 
00065 unsigned char epin = 0x81;
00066 unsigned char epout = 0x01;
00067 
00068 void SetSCSIEndPoints(unsigned char in,unsigned char out)
00069 {
00070     epin = in;
00071     epout = out;
00072 }
00073 
00074 
00075 int SCSIRequestSense();
00076    
00077  int DoSCSI(const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen) {
00078         CBW cbw;
00079         cbw.Signature = CBW_SIGNATURE;
00080         cbw.Tag = 0;
00081         cbw.TransferLength = transferLen;
00082         cbw.Flags = flags;
00083         cbw.LUN = 0;
00084         cbw.CBLength = cmdLen;
00085         memset(cbw.CB,0,sizeof(cbw.CB));
00086         memcpy(cbw.CB,cmd,cmdLen);
00087 
00088         int r;
00089         //r = USBBulkTransfer(device,0x01,(u8*)&cbw,31);   // Send the command
00090         r = USBBulkTransfer(USB_Disk_Device,epout,(u8*)&cbw,31);   // Send the command
00091         if (r < 0) {
00092             printf("first transfer returns %d\n", r);
00093             return r;
00094         }
00095         if (data) {
00096             //r = USBBulkTransfer(device,flags | 1,data,transferLen);
00097             r = USBBulkTransfer(USB_Disk_Device,flags ? epin : epout,data,transferLen);
00098             if (r < 0) {
00099                 printf("second transfer returns %d (flags=%02xH)\n", r, flags);
00100                 return r;
00101             }
00102         }
00103 
00104         CSW csw;
00105         csw.Signature = 0;
00106         //r = USBBulkTransfer(device,0x81,(u8*)&csw,13);
00107         r = USBBulkTransfer(USB_Disk_Device,epin,(u8*)&csw,13);
00108         if (r < 0) {
00109             printf("third transfer returns %d\n", r);
00110             return r;
00111         }
00112         if (csw.Signature != CSW_SIGNATURE)
00113             return ERR_BAD_CSW_SIGNATURE;
00114 
00115         // ModeSense?
00116         if (csw.Status == 1 && cmd[0] != 3)
00117             return SCSIRequestSense();
00118 
00119         return csw.Status;
00120     }
00121  
00122  
00123      int SCSITestUnitReady() {
00124         u8 cmd[6];
00125         memset(cmd,0,6);
00126         return DoSCSI(cmd,6,DEVICE_TO_HOST,0,0);
00127     }
00128 
00129     int SCSIRequestSense() {
00130         u8 cmd[6] = {0x03,0,0,0,18,0};
00131         u8 result[18];
00132         int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,18);
00133         return r;
00134     }
00135 
00136     int SCSIInquiry() {
00137         u8 cmd[6] = {0x12,0,0,0,36,0};
00138         u8 result[36+2];
00139         result[36] = '\n';
00140         result[37] = 0;
00141         int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,36);
00142         if (r == 0)
00143             printf((const char*)result + 8);
00144         return r;
00145     }
00146     int SCSIReadCapacity(u32* blockCount, u32* blockSize) {
00147         u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0};
00148         u8 result[8];
00149         *blockSize = 0;
00150         *blockCount = 0;
00151         int r = DoSCSI(cmd,10,DEVICE_TO_HOST,result,8);
00152         if (r == 0) {
00153             *blockCount = BE32(result);
00154             *blockSize = BE32(result+4);
00155         }
00156         return r;
00157     }
00158 
00159     int SCSITransfer(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction) {
00160         //  USB hardware will only do 4k per transfer
00161         while (blockCount*blockSize > 4096) {
00162             int count = 4096/blockSize;
00163             int r = SCSITransfer(blockAddr,count,dst,blockSize,direction);
00164             dst += count*blockSize;
00165             blockAddr += count;
00166             blockCount -= count;
00167         }
00168 
00169         u8 cmd[10];
00170         memset(cmd,0,10);
00171         cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
00172         BE32(blockAddr,cmd+2);
00173         BE16(blockCount,cmd+7);
00174         return DoSCSI(cmd,10,direction,dst,blockSize*blockCount);
00175     }
00176 
00177 int MassStorage_ReadCapacity(u32* blockCount, u32* blockSize)
00178 {
00179     return SCSIReadCapacity(blockCount,blockSize);
00180 }
00181 
00182 int MassStorage_Read(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
00183 {
00184     return SCSITransfer(blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST);
00185 }
00186 
00187 int MassStorage_Write(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
00188 {
00189     return SCSITransfer(blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE);
00190 }
00191 
00192 
00193 
00194