3 #USB Mass Storage Emulator
5 #with thanks to Brandon Wilson and his Linky project.
12 from GoodFETMAXUSB import *;
14 class GoodFETMAXUSBMass(GoodFETMAXUSB):
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)
101 0x00, 0x03, 0x00, 0x00, 0x00, 0x01
105 #Configuration Descriptor
111 0x00, 0x01, 0x01, 0x00, 0xE0, 0x00, 0x09, 0x04, 0x00, 0x00,
113 0x08, #Mass Storage Bulk Only
118 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
120 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
124 # STRING descriptor 0--Language string
128 # 0x03, # bDescriptorType = string
129 # 0x09,0x04 # wLANGID(L/H) = English-United Sates
131 # STRING descriptor 1--Manufacturer ID
132 "\x10\x03G\x00o\x00o\x00d\x00F\x00E\x00T\x00",
133 # STRING descriptor 2 - Product ID
134 "\x1C\x03M\x00A\x00S\x00S\x00 \x00E\x00m\x00u\x00l\x00a\x00t\x00o\x00r\x00",
135 # STRING descriptor 3 - Serial Number ID
136 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
139 def send_descriptor(self,SUD):
140 """Send the USB descriptors based upon the setup data."""
142 reqlen=ord(SUD[wLengthL])+256*ord(SUD[wLengthH]); #16-bit length
143 desctype=ord(SUD[wValueH]);
145 if desctype==GD_DEVICE:
148 elif desctype==GD_CONFIGURATION:
151 elif desctype==GD_STRING:
152 desclen=self.strDesc[ord(SUD[wValueL])][0];
153 ddata=self.strDesc[ord(SUD[wValueL])];
155 #TODO Configuration, String, Hid, and Report
158 sendlen=min(reqlen,desclen);
159 self.writebytes(rEP0FIFO,ddata);
160 self.wregAS(rEP0BC,sendlen);
162 print "Stalling in send_descriptor() for lack of handler for %02x." % desctype;
164 def set_configuration(self,SUD):
165 """Set the configuration."""
167 configval=ord(SUD[wValueL]);
169 self.SETBIT(rUSBIEN,bmSUSPIE);
170 self.rregAS(rFNADDR);
171 def get_status(self,SUD):
172 """Get the USB Setup Status."""
173 testbyte=ord(SUD[bmRequestType])
177 self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
178 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
179 self.wregAS(rEP0BC,2); #Load byte count, arm transfer, and ack CTL.
182 self.wreg(rEP0FIFO,0x00);
183 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
184 self.wregAS(rEP0BC,2);
187 if(ord(SUD[wIndexL])==0x83):
188 print "This code almost certainly doesn't work.";
189 self.wreg(rEP0FIFO,0x01); #Stall EP3
190 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
191 self.wregAS(rEP0BC,2);
198 """Handle IN3 input event."""
199 #Don't bother clearing interrupt flag, that's done by sending the reply.
200 print "Got an input event, no idea what to do about it.";
201 #This would be for FTDI emulation. Not for Mass Storage.
202 #self.wreg(rEP3INFIFO,0x01); #Modem
203 #self.wreg(rEP3INFIFO,0x00); #Line
204 #self.wreg(rEP3INFIFO,0x00);
205 self.wregAS(rEP3INBC,0);
209 """Handle an OUT1 output event."""
210 print "Got an output event, printing the result.";
211 l=self.rreg(rEP1OUTBC);
212 frame=self.readbytesAS(rEP1OUTFIFO,l);
213 self.handleCBW(frame);
215 def handleCBW(self,cbw):
216 """Handles an incoming Command Block Wrapper. See USB Mass
217 Storage Class for details."""
220 print "Invalid CBW length of %i bytes. Aborting." % len(cbw);
223 print "Invalid CBW signature: %s. Should be USBC; aborting." % sig;
227 dtlen=ord(cbw[8])+(ord(cbw[9])<<8)+(ord(cbw[10])<<16)+(ord(cbw[11])<<24);
229 dtdir=flags&0x80; # 0x80 for dev->host, 0x00 for host->dev
230 lun=ord(cbw[13])&0x0F; # Should be zero, as we only reported one LUN.
231 cblen=ord(cbw[14])&0x1F;
233 self.handleCB(cb,cblen,dtlen,dtdir);
235 def handleCB(self,cb,cblen,dtlen,dtdir):
236 """Handles a command block, then replies with a CSW."""
237 print "Got command block 0x%02x, length %i bytes" % (
240 status=00; #good, set to 1 for bad.
241 if verb==0x00: # Test Unit Ready
242 response=[0,0,0,0,0,0];
243 self.writebytes(rEP3INFIFO,
245 self.wregAS(rEP3INBC,len(response));
246 while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
247 #Wait for the packet to complete before sending the next.
248 print "Waiting to complete inquiry."
250 elif verb==0x03: # Request Sense
251 print "Responding to Request Sense. Needed for Macs.";
252 response=[0x70, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0A,
253 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
257 self.writebytes(rEP3INFIFO,
259 self.wregAS(rEP3INBC,len(response));
260 while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
261 #Wait for the packet to complete before sending the next.
262 print "Waiting to complete inquiry."
264 elif verb==0x12: #Inquiry
265 print "Responding to CB inquiry.";
268 0x80, # make 0x80 for removable media
271 0x1f, #Additional length.
274 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0,
276 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0,
278 ord('0'),ord('.'),ord('0'),ord('1')]
279 self.writebytes(rEP3INFIFO,
281 self.wregAS(rEP3INBC,len(response));
282 while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
283 #Wait for the packet to complete before sending the next.
284 print "Waiting to complete inquiry."
287 print "ERROR: Unknown command block verb %02x." % verb;
288 status=1; #Command Failed
290 print "Exiting, as %i bytes are expected to be transfered toward %i." % (
296 #Now we need to send the CSW.
299 ord('U'),ord('S'),ord('B'),ord('S'),
300 #CBW key; must be the same as the one we're replying to.
301 ord(cbw[4]),ord(cbw[5]),ord(cbw[6]),ord(cbw[7]),
302 #CSW Data Residue, probably oughtn't be zeroed.
304 #Status byte: 00 for good, 01 for bad.
306 self.writebytes(rEP3INFIFO,
308 self.wregAS(rEP3INBC,len(csw));
311 self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the IRQ bit.
313 #Initialize FET and set baud rate
314 client=GoodFETMAXUSBMass();
317 client.MAXUSBsetup();