Fixed capacity issues; goodfet.maxusbmass now enumerates a 2MB disk.
[goodfet] / client / goodfet.maxusbmass
1 #!/usr/bin/env python
2
3 #USB Mass Storage Emulator
4 #by Travis Goodspeed
5 #with thanks to Brandon Wilson and his Linky project.
6
7 import sys;
8 import binascii;
9 import array;
10 import time;
11
12 from GoodFETMAXUSB import *;
13
14 class GoodFETMAXUSBMass(GoodFETMAXUSBDevice):
15     """This emulates a USB Mass Storage device."""
16     def massinit(self):
17         """Initialize a USB Mass Storage device."""
18         self.usb_disconnect();
19         time.sleep(1);
20         self.usb_connect();
21         self.massrun();
22         
23     def massrun(self):
24         """Main loop of the USB Mass Storage emulator."""
25         print "Starting a Mass Storage device.  This doesn't work yet.";
26         while 1:
27             self.service_irqs();
28     def do_SETUP(self):
29         """Handle USB Enumeration"""
30         
31         #Grab the SETUP packet from the buffer.
32         SUD=self.readbytes(rSUDFIFO,8);
33         
34         #Parse the SETUP packet
35         print "Handling a setup packet of %s" % self.setup2str(SUD);
36         setuptype=(ord(SUD[bmRequestType])&0x60);
37         if setuptype==0x00:
38             self.std_request(SUD);
39         elif setuptype==0x20:
40             self.class_request(SUD);
41         elif setuptype==0x40:
42             self.vendor_request(SUD);
43         else:
44             print "Unknown bmRequestType=0x%02x." % ord(SUD[bmRequestType])
45             self.STALL_EP0(SUD);
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!
56             return; #Don't stall.
57         if requesttype==0x21 and request==0xff:
58             print "Received BBB reset."
59             self.wregAS(rEP0BC,0); # ARM and fire!
60             return; #Don't stall.
61         print "Stalling an unknown class request: %s" % self.setup2str(SUD);
62         self.STALL_EP0(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);
78         else:
79             #print "Stalling Unknown standard setup request type %02x" % setuptype;
80             #self.STALL_EP0(SUD);
81             print "Accepting unknown standard setup request type %02x" % setuptype;
82             self.wregAS(rEP0BC,0);
83             
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);
89         else:
90             self.STALL_EP0(SUD);
91     
92
93
94 #Device Descriptor
95     DD=[ 
96         
97     0x12, #length
98     0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
99     0x81, 0x07, #Sandisk 
100     0x50, 0x51, #SDCZ2 Cruzer Mini Flash Drive (thin)
101     0x00, 0x03,
102     0x01, 0x02, 0x03, #Strings
103     0x01
104     
105     ];
106
107 #Configuration Descriptor
108     CD=[
109
110   0x09, #Length
111   0x02, #Type
112   0x20, #Total Length
113   0x00, 0x01, 0x01, 0x00, 0xE0, 0x00, 0x09, 0x04, 0x00, 0x00,
114   0x02, #Num Endpoints
115   0x08, #Mass Storage Bulk Only
116   0x06, #SCSI
117   0x50, 0x00,
118   
119   #OUT EP1
120   0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
121   #IN EP3
122   0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
123
124 ];
125     strDesc=[
126 # STRING descriptor 0--Language string
127 "\x04\x03\x09\x04",
128 # [
129 #         0x04,                 # bLength
130 #       0x03,                   # bDescriptorType = string
131 #       0x09,0x04               # wLANGID(L/H) = English-United Sates
132 # ],
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"
139 ];
140
141     def get_status(self,SUD):
142         """Get the USB Setup Status."""
143         testbyte=ord(SUD[bmRequestType])
144         
145         #Toward Device
146         if testbyte==0x80:
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.
150         #Toward Interface
151         elif testbyte==0x81:
152             self.wreg(rEP0FIFO,0x00);
153             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
154             self.wregAS(rEP0BC,2);
155         #Toward Endpoint
156         elif testbyte==0x82:
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);
162             else:
163                 print "Stalling unknown status.";
164                 self.STALL_EP0(SUD);
165         else:
166             print "Stalling unknown status.";
167             self.STALL_EP0(SUD);
168     
169     def do_IN3(self):
170         """Handle IN3 input event."""
171         # Do nothing here, as it'll be taken care of elsewhere.  The
172         # interrupt just means that the buffer is empty, not that we
173         # are expected to fill it.
174         
175     def do_OUT1(self):
176         """Handle an OUT1 output event."""
177         print "Got an output event, printing the result.";
178         l=self.rreg(rEP1OUTBC);
179         frame=self.readbytes(rEP1OUTFIFO,l);
180         self.handleCBW(frame);
181         
182     lastCBW="";
183     def handleCBW(self,cbw):
184         """Handles an incoming Command Block Wrapper.  See USB Mass
185         Storage Class for details."""
186         
187         if len(cbw)!=31:
188             print "Invalid CBW length of %i bytes.  Aborting." % len(cbw);
189             return;
190         sig=cbw[0:4];
191         if sig!="USBC":
192             print "Invalid CBW signature: %s.  Should be USBC; aborting." % sig;
193             return;
194         self.lastCBW=cbw;
195         
196         dtlen=ord(cbw[8])+(ord(cbw[9])<<8)+(ord(cbw[10])<<16)+(ord(cbw[11])<<24);
197         flags=ord(cbw[12]);
198         dtdir=flags&0x80; # 0x80 for dev->host, 0x00 for host->dev
199         lun=ord(cbw[13])&0x0F; # Should be zero, as we only reported one LUN.
200         cblen=ord(cbw[14])&0x1F;
201         cb=cbw[15:31];
202         self.handleCB(cb,cblen,dtlen,dtdir);
203         
204     def handleCB(self,cb,cblen,dtlen,dtdir):
205         """Handles a command block, then replies with a CSW."""
206         print "\nGot command block 0x%02x, requesting 0x%02x bytes" % (
207             ord(cb[0]), dtlen);
208         verb=ord(cb[0]);
209         status=00; #good, set to 1 for bad.
210         if verb==0x00: # Test Unit Ready
211             # Send nothing, just the success code.
212             status=0;
213         elif verb==0x03: # Request Sense
214             print "Responding to Request Sense.  Needed for Macs.";
215             response=[0x70, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0A,
216                       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
217                       0x00, 0x00,
218                       0,0,0,0,0];
219             #status=1;
220             self.writebytes(rEP3INFIFO,
221                             response);
222             self.wreg(rEP3INBC,len(response));
223         elif verb==0x12: #Inquiry
224             #print "Responding to CB inquiry.";
225             response=[
226                 0x00, # 00 for Direct, 1F for "no floppy"
227                 0x80, # make 0x80 for removable media
228                 0x00, # Version
229                 0x01, # Response Data Format
230                 0x1f, #Additional length.
231                 0x00, 0x00, 0x00,
232                 #Manufacturer
233                 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
234                 #Device name
235                 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
236                 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
237                 ord('0'),ord('.'),ord('0'),ord('1')]
238             #print "Sending %i byte reply to %i byte query." % (
239             #        len(response),dtlen);
240             #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
241             #    #Wait for the packet to complete before sending the next.
242             #    print "Waiting to complete inquiry."
243             #    pass;
244             self.writebytes(rEP3INFIFO,
245                             response);
246             self.wregAS(rEP3INBC,
247                         dtlen);
248                         #len(response));
249             #self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
250             #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
251             #    #Wait for the packet to complete before sending the next.
252             #    print "Waiting to complete inquiry."
253             #    pass;
254         elif verb==0x1e: #Prevent/Allow Removal
255             # Give a good status to pretend we understand.
256             status=0x00;
257         elif verb==0x1A: #Mode Sense (6)
258             # I should probably send six bytes here.
259             response=[0x12,0,0,0, 0,0,0,0x1C];
260             self.writebytes(rEP3INFIFO,
261                             response);
262             self.wregAS(rEP3INBC,
263                         len(response));
264         elif verb==0x23: #Read Format Capacity
265             response=[
266                 0x00, 0,0x00,0x08, #Capacity list length.
267                 0,0x00,x10,0x00,   # Number of sectors, implying 10MB.
268                 0x01,0x00,            #reserved/desciptor code.
269                 0x02,0x00             # 512 bytes/sector.  Why is this twice?
270                 ];
271             self.writebytes(rEP3INFIFO,
272                             response);
273             self.wregAS(rEP3INBC,
274                         len(response));
275         elif verb==0x25: #Read Capacity
276             response=[
277                 0x00, 0,0x0f,0xFF, # Last LBA; might have endianness backward.
278                 0x00,0x00,0x02,0x00   # Block length of 512 bytes.
279                 ];
280             self.writebytes(rEP3INFIFO,
281                             response);
282             self.wregAS(rEP3INBC,
283                         len(response));
284         elif verb==0x28: #READ SECTOR
285             print "Haven't implemented READ SECTOR.";
286             sys.exit();
287         elif verb==0x2A: #WRITE SECTOR
288             print "Haven't implemented WRITE SECTOR.";
289             sys.exit();
290         else:
291             print "ERROR: Unknown SCSI command block verb %02x." % verb;
292             status=1; #Command Failed
293             if dtlen>0:
294                 print "Perhaps I should send %i bytes of dummy data here." % dtlen;
295             sys.exit(1);
296         cbw=self.lastCBW;
297         
298         #Now we need to send the CSW.
299         csw=[
300             #Standard prefix.
301             ord('U'),ord('S'),ord('B'),ord('S'),
302             #CBW key; must be the same as the one we're replying to.
303             ord(cbw[4]),ord(cbw[5]),ord(cbw[6]),ord(cbw[7]),
304             #CSW Data Residue, probably oughtn't be zeroed.
305             0,0,0,0,
306             #Status byte: 00 for good, 01 for bad.
307             status];
308         self.writebytes(rEP3INFIFO,
309                         csw);
310         self.wregAS(rEP3INBC,len(csw));
311         
312         
313         return;
314 #Initialize FET and set baud rate
315 client=GoodFETMAXUSBMass();
316 client.serInit()
317
318 client.MAXUSBsetup();
319 client.massinit();
320