3 #USB Mass Storage Emulator
5 #with thanks to Brandon Wilson and his Linky project.
12 from GoodFETMAXUSB import *;
14 class GoodFETMAXUSBMass(GoodFETMAXUSBDevice):
15 """This emulates a USB Mass Storage device."""
17 """Initialize a USB Mass Storage device."""
18 self.usb_disconnect();
24 """Main loop of the USB Mass Storage emulator."""
25 print "Starting a Mass Storage device. This doesn't work yet.";
29 """Handle USB Enumeration"""
31 #Grab the SETUP packet from the buffer.
32 SUD=self.readbytes(rSUDFIFO,8);
34 #Parse the SETUP packet
35 print "Handling a setup packet of %s" % self.setup2str(SUD);
36 setuptype=(ord(SUD[bmRequestType])&0x60);
38 self.std_request(SUD);
40 self.class_request(SUD);
42 self.vendor_request(SUD);
44 print "Unknown bmRequestType=0x%02x." % ord(SUD[bmRequestType])
46 def class_request(self,SUD):
47 """Handle a class request."""
48 requesttype=ord(SUD[bmRequestType]);
49 request=ord(SUD[bRequest]);
50 if requesttype==0xA1 and request==0xFE:
51 print "Reporting 0 as the maximum LUN.";
52 #This is a Get Max LUN request.
53 #Return 1-byte maximum Logical Unit Number
54 self.wreg(rEP0FIFO,0x00); # Just one LUN.
55 self.wregAS(rEP0BC,1); # ARM and fire!
57 if requesttype==0x21 and request==0xff:
58 print "Received BBB reset."
59 self.wregAS(rEP0BC,0); # ARM and fire!
61 print "Stalling an unknown class request: %s" % self.setup2str(SUD);
63 def vendor_request(self,SUD):
64 """Handle a vendor request."""
65 request=ord(SUD[bRequest]);
66 print "Why the hell is there a vendor request?";
67 #self.wreg(rEP0FIFO,0);
68 self.wregAS(rEP0BC,0);
69 def std_request(self,SUD):
70 """Handles a standard setup request."""
71 setuptype=ord(SUD[bRequest]);
72 if setuptype==SR_GET_DESCRIPTOR: self.send_descriptor(SUD);
73 #elif setuptype==SR_SET_FEATURE: self.feature(1);
74 elif setuptype==SR_SET_CONFIGURATION: self.set_configuration(SUD);
75 elif setuptype==SR_GET_STATUS: self.get_status(SUD);
76 elif setuptype==SR_SET_ADDRESS: self.rregAS(rFNADDR);
77 elif setuptype==SR_GET_INTERFACE: self.get_interface(SUD);
79 #print "Stalling Unknown standard setup request type %02x" % setuptype;
81 print "Accepting unknown standard setup request type %02x" % setuptype;
82 self.wregAS(rEP0BC,0);
84 def get_interface(self,SUD):
85 """Handles a setup request for SR_GET_INTERFACE."""
86 if ord(SUD[wIndexL]==0):
87 self.wreg(rEP0FIFO,0);
88 self.wregAS(rEP0BC,1);
98 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
100 0x50, 0x51, #SDCZ2 Cruzer Mini Flash Drive (thin)
102 0x01, 0x02, 0x03, #Strings
107 #Configuration Descriptor
113 0x00, 0x01, 0x01, 0x00, 0xE0, 0x00, 0x09, 0x04, 0x00, 0x00,
115 0x08, #Mass Storage Bulk Only
120 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
122 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
126 # STRING descriptor 0--Language string
130 # 0x03, # bDescriptorType = string
131 # 0x09,0x04 # wLANGID(L/H) = English-United Sates
133 # STRING descriptor 1--Manufacturer ID
134 "\x10\x03G\x00o\x00o\x00d\x00F\x00E\x00T\x00",
135 # STRING descriptor 2 - Product ID
136 "\x1C\x03M\x00A\x00S\x00S\x00 \x00E\x00m\x00u\x00l\x00a\x00t\x00o\x00r\x00",
137 # STRING descriptor 3 - Serial Number ID
138 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
141 def get_status(self,SUD):
142 """Get the USB Setup Status."""
143 testbyte=ord(SUD[bmRequestType])
147 self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
148 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
149 self.wregAS(rEP0BC,2); #Load byte count, arm transfer, and ack CTL.
152 self.wreg(rEP0FIFO,0x00);
153 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
154 self.wregAS(rEP0BC,2);
157 if(ord(SUD[wIndexL])==0x83):
158 print "This code almost certainly doesn't work.";
159 self.wreg(rEP0FIFO,0x01); #Stall EP3
160 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
161 self.wregAS(rEP0BC,2);
163 print "Stalling unknown status.";
166 print "Stalling unknown status.";
170 """Handle IN3 input event."""
171 #Don't bother clearing interrupt flag, that's done by sending the reply.
172 print "Got an input event, no idea what to do about it.";
173 #This would be for FTDI emulation. Not for Mass Storage.
174 #self.wreg(rEP3INFIFO,0x01); #Modem
175 #self.wreg(rEP3INFIFO,0x00); #Line
176 #self.wreg(rEP3INFIFO,0x00);
177 #self.wregAS(rEP3INBC,0);
181 """Handle an OUT1 output event."""
182 print "Got an output event, printing the result.";
183 l=self.rreg(rEP1OUTBC);
184 frame=self.readbytes(rEP1OUTFIFO,l);
185 self.handleCBW(frame);
187 def handleCBW(self,cbw):
188 """Handles an incoming Command Block Wrapper. See USB Mass
189 Storage Class for details."""
192 print "Invalid CBW length of %i bytes. Aborting." % len(cbw);
196 print "Invalid CBW signature: %s. Should be USBC; aborting." % sig;
200 dtlen=ord(cbw[8])+(ord(cbw[9])<<8)+(ord(cbw[10])<<16)+(ord(cbw[11])<<24);
202 dtdir=flags&0x80; # 0x80 for dev->host, 0x00 for host->dev
203 lun=ord(cbw[13])&0x0F; # Should be zero, as we only reported one LUN.
204 cblen=ord(cbw[14])&0x1F;
206 self.handleCB(cb,cblen,dtlen,dtdir);
208 def handleCB(self,cb,cblen,dtlen,dtdir):
209 """Handles a command block, then replies with a CSW."""
210 print "\nGot command block 0x%02x, requesting 0x%02x bytes" % (
213 status=00; #good, set to 1 for bad.
214 if verb==0x00: # Test Unit Ready
215 response=[0,0,0,0,0,0];
216 self.writebytes(rEP3INFIFO,
218 self.wreg(rEP3INBC,len(response));
219 while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
220 #Wait for the packet to complete before sending the next.
221 print "Waiting to complete inquiry."
223 elif verb==0x03: # Request Sense
224 print "Responding to Request Sense. Needed for Macs.";
225 response=[0x70, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0A,
226 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
230 self.writebytes(rEP3INFIFO,
232 self.wreg(rEP3INBC,len(response));
233 #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
234 # #Wait for the packet to complete before sending the next.
235 # print "Waiting to complete inquiry."
237 elif verb==0x12: #Inquiry
238 #print "Responding to CB inquiry.";
240 0x00, # 00 for Direct, 1F for "no floppy"
241 0x80, # make 0x80 for removable media
243 0x01, # Response Data Format
244 0x1f, #Additional length.
247 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
249 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
250 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
251 ord('0'),ord('.'),ord('0'),ord('1')]
252 #print "Sending %i byte reply to %i byte query." % (
253 # len(response),dtlen);
254 #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
255 # #Wait for the packet to complete before sending the next.
256 # print "Waiting to complete inquiry."
258 self.writebytes(rEP3INFIFO,
260 self.wregAS(rEP3INBC,
263 #self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
264 #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
265 # #Wait for the packet to complete before sending the next.
266 # print "Waiting to complete inquiry."
269 print "ERROR: Unknown command block verb %02x." % verb;
270 status=1; #Command Failed
272 print "Exiting, as %i bytes are expected to be transfered toward %i." % (
278 #Now we need to send the CSW.
281 ord('U'),ord('S'),ord('B'),ord('S'),
282 #CBW key; must be the same as the one we're replying to.
283 ord(cbw[4]),ord(cbw[5]),ord(cbw[6]),ord(cbw[7]),
284 #CSW Data Residue, probably oughtn't be zeroed.
286 #Status byte: 00 for good, 01 for bad.
288 self.writebytes(rEP3INFIFO,
290 self.wregAS(rEP3INBC,len(csw));
293 self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the IRQ bit.
295 #Initialize FET and set baud rate
296 client=GoodFETMAXUSBMass();
299 client.MAXUSBsetup();