Almost identical to USBHostShell; reads all endpoint descriptors

Dependents:   myBlueUSB mbed_TANK_Kinect myBlueUSB_ros myBlueUSB_localfix

Revision:
3:58c785c2b381
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MassStorage.h	Fri Jul 01 09:13:39 2011 +0000
@@ -0,0 +1,149 @@
+#ifndef MASSSTORAGE_H
+#define MASSSTORAGE_H
+
+#include "Utils.h"
+#include "USBHost.h"
+
+
+#define ERR_BAD_CSW_SIGNATURE -200
+
+#define CBW_SIGNATURE  0x43425355
+#define CSW_SIGNATURE  0x53425355
+
+#define BULK_ENDPOINT_IN    0x81
+#define BULK_ENDPOINT_OUT   0x02
+
+//  Command Block
+typedef struct {
+    u32 Signature;
+    u32 Tag;
+    u32 TransferLength;
+    u8 Flags;
+    u8 LUN;
+    u8 CBLength;
+    u8 CB[16];   // only 6 really
+} CBW;
+
+//  Status block
+typedef struct {
+    u32 Signature;
+    u32 Tag;
+    u32 DataResidue;
+    u8 Status;
+} CSW;
+
+class USBSCSI {
+protected:
+    int _device;
+    unsigned char epin, epout;
+public:
+    USBSCSI() : _device(0) {}
+
+    void SetDevice(int device, unsigned char in, unsigned char out)
+    {
+        _device = device;
+        epin = in;
+        epout = out;
+    }
+protected:    
+    int DoSCSI(const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen) {
+        CBW cbw;
+        cbw.Signature = CBW_SIGNATURE;
+        cbw.Tag = 0;
+        cbw.TransferLength = transferLen;
+        cbw.Flags = flags;
+        cbw.LUN = 0;
+        cbw.CBLength = cmdLen;
+        memset(cbw.CB,0,sizeof(cbw.CB));
+        memcpy(cbw.CB,cmd,cmdLen);
+
+        int r;
+        //r = USBBulkTransfer(device,0x01,(u8*)&cbw,31);   // Send the command
+        r = USBBulkTransfer(_device,epout,(u8*)&cbw,31);   // Send the command
+        if (r < 0) {
+            printf("first transfer returns %d\n", r);
+            return r;
+        }
+        if (data) {
+            //r = USBBulkTransfer(device,flags | 1,data,transferLen);
+            r = USBBulkTransfer(_device,flags ? epin : epout,data,transferLen);
+            if (r < 0) {
+                printf("second transfer returns %d (flags=%02xH)\n", r, flags);
+                return r;
+            }
+        }
+
+        CSW csw;
+        csw.Signature = 0;
+        //r = USBBulkTransfer(device,0x81,(u8*)&csw,13);
+        r = USBBulkTransfer(_device,epin,(u8*)&csw,13);
+        if (r < 0) {
+            printf("third transfer returns %d\n", r);
+            return r;
+        }
+        if (csw.Signature != CSW_SIGNATURE)
+            return ERR_BAD_CSW_SIGNATURE;
+
+        // ModeSense?
+        if (csw.Status == 1 && cmd[0] != 3)
+            return SCSIRequestSense();
+
+        return csw.Status;
+    }
+
+    int SCSITestUnitReady() {
+        u8 cmd[6];
+        memset(cmd,0,6);
+        return DoSCSI(cmd,6,DEVICE_TO_HOST,0,0);
+    }
+
+    int SCSIRequestSense() {
+        u8 cmd[6] = {0x03,0,0,0,18,0};
+        u8 result[18];
+        int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,18);
+        return r;
+    }
+
+    int SCSIInquiry() {
+        u8 cmd[6] = {0x12,0,0,0,36,0};
+        u8 result[36+2];
+        result[36] = '\n';
+        result[37] = 0;
+        int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,36);
+        if (r == 0)
+            printf((const char*)result + 8);
+        return r;
+    }
+
+    int SCSIReadCapacity(u32* blockCount, u32* blockSize) {
+        u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0};
+        u8 result[8];
+        *blockSize = 0;
+        *blockCount = 0;
+        int r = DoSCSI(cmd,10,DEVICE_TO_HOST,result,8);
+        if (r == 0) {
+            *blockCount = BE32(result);
+            *blockSize = BE32(result+4);
+        }
+        return r;
+    }
+
+    int SCSITransfer(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction) {
+        //  USB hardware will only do 4k per transfer
+        while (blockCount*blockSize > 4096) {
+            int count = 4096/blockSize;
+            int r = SCSITransfer(blockAddr,count,dst,blockSize,direction);
+            dst += count*blockSize;
+            blockAddr += count;
+            blockCount -= count;
+        }
+
+        u8 cmd[10];
+        memset(cmd,0,10);
+        cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
+        BE32(blockAddr,cmd+2);
+        BE16(blockCount,cmd+7);
+        return DoSCSI(cmd,10,direction,dst,blockSize*blockCount);
+    }
+};
+#endif
\ No newline at end of file