A more capable USB Host. The API supports synchronous and Asynchronous control, interrupt and bulk transfers. It has built in support for hubs and hot plugging. It can support any number of devices and endpoints limited only by sram. The test shell supports mouse, keyboard and mass storage/fat.

Dependencies:   mbed

Committer:
peterbarrett1967
Date:
Fri Apr 02 22:28:01 2010 +0000
Revision:
0:5ad808014a49

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
peterbarrett1967 0:5ad808014a49 1
peterbarrett1967 0:5ad808014a49 2 /*
peterbarrett1967 0:5ad808014a49 3 Copyright (c) 2010 Peter Barrett
peterbarrett1967 0:5ad808014a49 4
peterbarrett1967 0:5ad808014a49 5 Permission is hereby granted, free of charge, to any person obtaining a copy
peterbarrett1967 0:5ad808014a49 6 of this software and associated documentation files (the "Software"), to deal
peterbarrett1967 0:5ad808014a49 7 in the Software without restriction, including without limitation the rights
peterbarrett1967 0:5ad808014a49 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
peterbarrett1967 0:5ad808014a49 9 copies of the Software, and to permit persons to whom the Software is
peterbarrett1967 0:5ad808014a49 10 furnished to do so, subject to the following conditions:
peterbarrett1967 0:5ad808014a49 11
peterbarrett1967 0:5ad808014a49 12 The above copyright notice and this permission notice shall be included in
peterbarrett1967 0:5ad808014a49 13 all copies or substantial portions of the Software.
peterbarrett1967 0:5ad808014a49 14
peterbarrett1967 0:5ad808014a49 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
peterbarrett1967 0:5ad808014a49 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
peterbarrett1967 0:5ad808014a49 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
peterbarrett1967 0:5ad808014a49 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
peterbarrett1967 0:5ad808014a49 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
peterbarrett1967 0:5ad808014a49 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
peterbarrett1967 0:5ad808014a49 21 THE SOFTWARE.
peterbarrett1967 0:5ad808014a49 22 */
peterbarrett1967 0:5ad808014a49 23
peterbarrett1967 0:5ad808014a49 24 #include "stdlib.h"
peterbarrett1967 0:5ad808014a49 25 #include "stdio.h"
peterbarrett1967 0:5ad808014a49 26 #include "string.h"
peterbarrett1967 0:5ad808014a49 27
peterbarrett1967 0:5ad808014a49 28 #include "Utils.h"
peterbarrett1967 0:5ad808014a49 29 #include "USBHost.h"
peterbarrett1967 0:5ad808014a49 30
peterbarrett1967 0:5ad808014a49 31
peterbarrett1967 0:5ad808014a49 32 int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize);
peterbarrett1967 0:5ad808014a49 33 int MassStorage_ReadBlock(int device, u32 block, u8* dst);
peterbarrett1967 0:5ad808014a49 34 int MassStorage_WriteBlock(int device, u32 block, const u8* dst);
peterbarrett1967 0:5ad808014a49 35
peterbarrett1967 0:5ad808014a49 36
peterbarrett1967 0:5ad808014a49 37 #define ERR_BAD_CSW_SIGNATURE -200
peterbarrett1967 0:5ad808014a49 38
peterbarrett1967 0:5ad808014a49 39 #define CBW_SIGNATURE 0x43425355
peterbarrett1967 0:5ad808014a49 40 #define CSW_SIGNATURE 0x53425355
peterbarrett1967 0:5ad808014a49 41
peterbarrett1967 0:5ad808014a49 42 // Command Block
peterbarrett1967 0:5ad808014a49 43 typedef struct
peterbarrett1967 0:5ad808014a49 44 {
peterbarrett1967 0:5ad808014a49 45 u32 Signature;
peterbarrett1967 0:5ad808014a49 46 u32 Tag;
peterbarrett1967 0:5ad808014a49 47 u32 TransferLength;
peterbarrett1967 0:5ad808014a49 48 u8 Flags;
peterbarrett1967 0:5ad808014a49 49 u8 LUN;
peterbarrett1967 0:5ad808014a49 50 u8 CBLength;
peterbarrett1967 0:5ad808014a49 51 u8 CB[16]; // only 6 really
peterbarrett1967 0:5ad808014a49 52 } CBW;
peterbarrett1967 0:5ad808014a49 53
peterbarrett1967 0:5ad808014a49 54 // Status block
peterbarrett1967 0:5ad808014a49 55 typedef struct
peterbarrett1967 0:5ad808014a49 56 {
peterbarrett1967 0:5ad808014a49 57 u32 Signature;
peterbarrett1967 0:5ad808014a49 58 u32 Tag;
peterbarrett1967 0:5ad808014a49 59 u32 DataResidue;
peterbarrett1967 0:5ad808014a49 60 u8 Status;
peterbarrett1967 0:5ad808014a49 61 } CSW;
peterbarrett1967 0:5ad808014a49 62
peterbarrett1967 0:5ad808014a49 63 int SCSIRequestSense(int device);
peterbarrett1967 0:5ad808014a49 64
peterbarrett1967 0:5ad808014a49 65 int DoSCSI(int device, const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen)
peterbarrett1967 0:5ad808014a49 66 {
peterbarrett1967 0:5ad808014a49 67 CBW cbw;
peterbarrett1967 0:5ad808014a49 68 cbw.Signature = CBW_SIGNATURE;
peterbarrett1967 0:5ad808014a49 69 cbw.Tag = 0;
peterbarrett1967 0:5ad808014a49 70 cbw.TransferLength = transferLen;
peterbarrett1967 0:5ad808014a49 71 cbw.Flags = flags;
peterbarrett1967 0:5ad808014a49 72 cbw.LUN = 0;
peterbarrett1967 0:5ad808014a49 73 cbw.CBLength = cmdLen;
peterbarrett1967 0:5ad808014a49 74 memset(cbw.CB,0,sizeof(cbw.CB));
peterbarrett1967 0:5ad808014a49 75 memcpy(cbw.CB,cmd,cmdLen);
peterbarrett1967 0:5ad808014a49 76
peterbarrett1967 0:5ad808014a49 77 int r;
peterbarrett1967 0:5ad808014a49 78 r = USBBulkTransfer(device,0x01,(u8*)&cbw,31); // Send the command
peterbarrett1967 0:5ad808014a49 79 if (r < 0)
peterbarrett1967 0:5ad808014a49 80 return r;
peterbarrett1967 0:5ad808014a49 81
peterbarrett1967 0:5ad808014a49 82 if (data)
peterbarrett1967 0:5ad808014a49 83 {
peterbarrett1967 0:5ad808014a49 84 r = USBBulkTransfer(device,flags | 1,data,transferLen);
peterbarrett1967 0:5ad808014a49 85 if (r < 0)
peterbarrett1967 0:5ad808014a49 86 return r;
peterbarrett1967 0:5ad808014a49 87 }
peterbarrett1967 0:5ad808014a49 88
peterbarrett1967 0:5ad808014a49 89 CSW csw;
peterbarrett1967 0:5ad808014a49 90 csw.Signature = 0;
peterbarrett1967 0:5ad808014a49 91 r = USBBulkTransfer(device,0x81,(u8*)&csw,13);
peterbarrett1967 0:5ad808014a49 92 if (r < 0)
peterbarrett1967 0:5ad808014a49 93 return r;
peterbarrett1967 0:5ad808014a49 94
peterbarrett1967 0:5ad808014a49 95 if (csw.Signature != CSW_SIGNATURE)
peterbarrett1967 0:5ad808014a49 96 return ERR_BAD_CSW_SIGNATURE;
peterbarrett1967 0:5ad808014a49 97
peterbarrett1967 0:5ad808014a49 98 // ModeSense?
peterbarrett1967 0:5ad808014a49 99 if (csw.Status == 1 && cmd[0] != 3)
peterbarrett1967 0:5ad808014a49 100 return SCSIRequestSense(device);
peterbarrett1967 0:5ad808014a49 101
peterbarrett1967 0:5ad808014a49 102 return csw.Status;
peterbarrett1967 0:5ad808014a49 103 }
peterbarrett1967 0:5ad808014a49 104
peterbarrett1967 0:5ad808014a49 105 int SCSITestUnitReady(int device)
peterbarrett1967 0:5ad808014a49 106 {
peterbarrett1967 0:5ad808014a49 107 u8 cmd[6];
peterbarrett1967 0:5ad808014a49 108 memset(cmd,0,6);
peterbarrett1967 0:5ad808014a49 109 return DoSCSI(device,cmd,6,DEVICE_TO_HOST,0,0);
peterbarrett1967 0:5ad808014a49 110 }
peterbarrett1967 0:5ad808014a49 111
peterbarrett1967 0:5ad808014a49 112 int SCSIRequestSense(int device)
peterbarrett1967 0:5ad808014a49 113 {
peterbarrett1967 0:5ad808014a49 114 u8 cmd[6] = {0x03,0,0,0,18,0};
peterbarrett1967 0:5ad808014a49 115 u8 result[18];
peterbarrett1967 0:5ad808014a49 116 int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,18);
peterbarrett1967 0:5ad808014a49 117 return r;
peterbarrett1967 0:5ad808014a49 118 }
peterbarrett1967 0:5ad808014a49 119
peterbarrett1967 0:5ad808014a49 120 int SCSIInquiry(int device)
peterbarrett1967 0:5ad808014a49 121 {
peterbarrett1967 0:5ad808014a49 122 u8 cmd[6] = {0x12,0,0,0,36,0};
peterbarrett1967 0:5ad808014a49 123 u8 result[36+2];
peterbarrett1967 0:5ad808014a49 124 result[36] = '\n';
peterbarrett1967 0:5ad808014a49 125 result[37] = 0;
peterbarrett1967 0:5ad808014a49 126 int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,36);
peterbarrett1967 0:5ad808014a49 127 if (r == 0)
peterbarrett1967 0:5ad808014a49 128 printf((const char*)result + 8);
peterbarrett1967 0:5ad808014a49 129 return r;
peterbarrett1967 0:5ad808014a49 130 }
peterbarrett1967 0:5ad808014a49 131
peterbarrett1967 0:5ad808014a49 132 int SCSIReadCapacity(int device, u32* blockCount, u32* blockSize)
peterbarrett1967 0:5ad808014a49 133 {
peterbarrett1967 0:5ad808014a49 134 u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0};
peterbarrett1967 0:5ad808014a49 135 u8 result[8];
peterbarrett1967 0:5ad808014a49 136 *blockSize = 0;
peterbarrett1967 0:5ad808014a49 137 *blockCount = 0;
peterbarrett1967 0:5ad808014a49 138 int r = DoSCSI(device,cmd,10,DEVICE_TO_HOST,result,8);
peterbarrett1967 0:5ad808014a49 139 if (r == 0)
peterbarrett1967 0:5ad808014a49 140 {
peterbarrett1967 0:5ad808014a49 141 *blockCount = BE32(result);
peterbarrett1967 0:5ad808014a49 142 *blockSize = BE32(result+4);
peterbarrett1967 0:5ad808014a49 143 }
peterbarrett1967 0:5ad808014a49 144 return r;
peterbarrett1967 0:5ad808014a49 145 }
peterbarrett1967 0:5ad808014a49 146
peterbarrett1967 0:5ad808014a49 147 int SCSITransfer(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction)
peterbarrett1967 0:5ad808014a49 148 {
peterbarrett1967 0:5ad808014a49 149 // USB hardware will only do 4k per transfer
peterbarrett1967 0:5ad808014a49 150 while (blockCount*blockSize > 4096)
peterbarrett1967 0:5ad808014a49 151 {
peterbarrett1967 0:5ad808014a49 152 int count = 4096/blockSize;
peterbarrett1967 0:5ad808014a49 153 int r = SCSITransfer(device,blockAddr,count,dst,blockSize,direction);
peterbarrett1967 0:5ad808014a49 154 dst += count*blockSize;
peterbarrett1967 0:5ad808014a49 155 blockAddr += count;
peterbarrett1967 0:5ad808014a49 156 blockCount -= count;
peterbarrett1967 0:5ad808014a49 157 }
peterbarrett1967 0:5ad808014a49 158
peterbarrett1967 0:5ad808014a49 159 u8 cmd[10];
peterbarrett1967 0:5ad808014a49 160 memset(cmd,0,10);
peterbarrett1967 0:5ad808014a49 161 cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
peterbarrett1967 0:5ad808014a49 162 BE32(blockAddr,cmd+2);
peterbarrett1967 0:5ad808014a49 163 BE16(blockCount,cmd+7);
peterbarrett1967 0:5ad808014a49 164 return DoSCSI(device,cmd,10,direction,dst,blockSize*blockCount);
peterbarrett1967 0:5ad808014a49 165 }
peterbarrett1967 0:5ad808014a49 166
peterbarrett1967 0:5ad808014a49 167 int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize)
peterbarrett1967 0:5ad808014a49 168 {
peterbarrett1967 0:5ad808014a49 169 return SCSIReadCapacity(device,blockCount,blockSize);
peterbarrett1967 0:5ad808014a49 170 }
peterbarrett1967 0:5ad808014a49 171
peterbarrett1967 0:5ad808014a49 172 int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
peterbarrett1967 0:5ad808014a49 173 {
peterbarrett1967 0:5ad808014a49 174 return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST);
peterbarrett1967 0:5ad808014a49 175 }
peterbarrett1967 0:5ad808014a49 176
peterbarrett1967 0:5ad808014a49 177 int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
peterbarrett1967 0:5ad808014a49 178 {
peterbarrett1967 0:5ad808014a49 179 return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE);
peterbarrett1967 0:5ad808014a49 180 }