Bluetooth support for MBED with $2 Bluetooth dongles. Includes a USB host and built in support for bluetooth HID devices such as mice, keyboards and wii controllers.

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 int SCSIRequestSense(int device);
00064 
00065 int DoSCSI(int device, const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen)
00066 {
00067     CBW cbw;
00068     cbw.Signature = CBW_SIGNATURE;
00069     cbw.Tag = 0;
00070     cbw.TransferLength = transferLen;
00071     cbw.Flags = flags;
00072     cbw.LUN = 0;
00073     cbw.CBLength = cmdLen;
00074     memset(cbw.CB,0,sizeof(cbw.CB));
00075     memcpy(cbw.CB,cmd,cmdLen);
00076 
00077     int r;
00078     r = USBBulkTransfer(device,0x01,(u8*)&cbw,31);   // Send the command
00079     if (r < 0)
00080         return r;
00081 
00082     if (data)
00083     {
00084         r = USBBulkTransfer(device,flags | 1,data,transferLen);
00085         if (r < 0)
00086             return r;
00087     }
00088 
00089     CSW csw;
00090     csw.Signature = 0;
00091     r = USBBulkTransfer(device,0x81,(u8*)&csw,13);
00092     if (r < 0)
00093         return r;
00094 
00095     if (csw.Signature != CSW_SIGNATURE)
00096         return ERR_BAD_CSW_SIGNATURE;
00097 
00098     // ModeSense?
00099     if (csw.Status == 1 && cmd[0] != 3)
00100         return SCSIRequestSense(device);
00101 
00102     return csw.Status;
00103 }
00104 
00105 int SCSITestUnitReady(int device)
00106 {
00107     u8 cmd[6];
00108     memset(cmd,0,6);
00109     return DoSCSI(device,cmd,6,DEVICE_TO_HOST,0,0);
00110 }
00111 
00112 int SCSIRequestSense(int device)
00113 {
00114     u8 cmd[6] = {0x03,0,0,0,18,0};
00115     u8 result[18];
00116     int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,18);
00117     return r;
00118 }
00119 
00120 int SCSIInquiry(int device)
00121 {
00122     u8 cmd[6] = {0x12,0,0,0,36,0};
00123     u8 result[36+2];
00124     result[36] = '\n';
00125     result[37] = 0;
00126     int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,36);
00127     if (r == 0)
00128         printf((const char*)result + 8);
00129     return r;
00130 }
00131 
00132 int SCSIReadCapacity(int device, u32* blockCount, u32* blockSize)
00133 {
00134     u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0};
00135     u8 result[8];
00136     *blockSize = 0;
00137     *blockCount = 0;
00138     int r = DoSCSI(device,cmd,10,DEVICE_TO_HOST,result,8);
00139     if (r == 0)
00140     {
00141         *blockCount = BE32(result);
00142         *blockSize = BE32(result+4);
00143     }
00144     return r;
00145 }
00146 
00147 int SCSITransfer(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction)
00148 {
00149     //  USB hardware will only do 4k per transfer
00150     while (blockCount*blockSize > 4096)
00151     {
00152         int count = 4096/blockSize;
00153         int r = SCSITransfer(device,blockAddr,count,dst,blockSize,direction);
00154         dst += count*blockSize;
00155         blockAddr += count;
00156         blockCount -= count;
00157     }
00158 
00159     u8 cmd[10];
00160     memset(cmd,0,10);
00161     cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
00162     BE32(blockAddr,cmd+2);
00163     BE16(blockCount,cmd+7);
00164     return DoSCSI(device,cmd,10,direction,dst,blockSize*blockCount);
00165 }
00166 
00167 int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize)
00168 {
00169     return SCSIReadCapacity(device,blockCount,blockSize);
00170 }
00171 
00172 int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
00173 {
00174     return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST);
00175 }
00176 
00177 int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
00178 {
00179     return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE);
00180 }