from GoodFETMAXUSB import *;
-class GoodFETMAXUSBMass(GoodFETMAXUSB):
+class GoodFETMAXUSBMass(GoodFETMAXUSBDevice):
"""This emulates a USB Mass Storage device."""
def massinit(self):
"""Initialize a USB Mass Storage device."""
if setuptype==0x00:
self.std_request(SUD);
elif setuptype==0x20:
- print "XXXXXXXXXX Got a class request."
self.class_request(SUD);
elif setuptype==0x40:
self.vendor_request(SUD);
self.STALL_EP0(SUD);
def class_request(self,SUD):
"""Handle a class request."""
- print "Stalling a class request.";
+ requesttype=ord(SUD[bmRequestType]);
+ request=ord(SUD[bRequest]);
+ if requesttype==0xA1 and request==0xFE:
+ print "Reporting 0 as the maximum LUN.";
+ #This is a Get Max LUN request.
+ #Return 1-byte maximum Logical Unit Number
+ self.wreg(rEP0FIFO,0x00); # Just one LUN.
+ self.wregAS(rEP0BC,1); # ARM and fire!
+ return; #Don't stall.
+ if requesttype==0x21 and request==0xff:
+ print "Received BBB reset."
+ self.wregAS(rEP0BC,0); # ARM and fire!
+ return; #Don't stall.
+ print "Stalling an unknown class request: %s" % self.setup2str(SUD);
self.STALL_EP0(SUD);
def vendor_request(self,SUD):
"""Handle a vendor request."""
elif setuptype==SR_SET_ADDRESS: self.rregAS(rFNADDR);
elif setuptype==SR_GET_INTERFACE: self.get_interface(SUD);
else:
- print "Stalling Unknown standard setup request type %02x" % setuptype;
- self.STALL_EP0(SUD);
-
+ #print "Stalling Unknown standard setup request type %02x" % setuptype;
+ #self.STALL_EP0(SUD);
+ print "Accepting unknown standard setup request type %02x" % setuptype;
+ self.wregAS(rEP0BC,0);
+
def get_interface(self,SUD):
"""Handles a setup request for SR_GET_INTERFACE."""
if ord(SUD[wIndexL]==0):
self.STALL_EP0(SUD);
-#0403:6001
#Device Descriptor
DD=[
0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x81, 0x07, #Sandisk
0x50, 0x51, #SDCZ2 Cruzer Mini Flash Drive (thin)
- 0x00, 0x03, 0x00, 0x00, 0x00, 0x01
+ 0x00, 0x03,
+ 0x01, 0x02, 0x03, #Strings
+ 0x01
];
0x06, #SCSI
0x50, 0x00,
+ #OUT EP1
+ 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
#IN EP3
0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
- #OUT EP1
- 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00
];
strDesc=[
"\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
];
- def send_descriptor(self,SUD):
- """Send the USB descriptors based upon the setup data."""
- desclen=0;
- reqlen=ord(SUD[wLengthL])+256*ord(SUD[wLengthH]); #16-bit length
- desctype=ord(SUD[wValueH]);
-
- if desctype==GD_DEVICE:
- desclen=self.DD[0];
- ddata=self.DD;
- elif desctype==GD_CONFIGURATION:
- desclen=self.CD[2];
- ddata=self.CD;
- elif desctype==GD_STRING:
- desclen=self.strDesc[ord(SUD[wValueL])][0];
- ddata=self.strDesc[ord(SUD[wValueL])];
-
- #TODO Configuration, String, Hid, and Report
-
- if desclen>0:
- sendlen=min(reqlen,desclen);
- self.writebytes(rEP0FIFO,ddata);
- self.wregAS(rEP0BC,sendlen);
- else:
- print "Stalling in send_descriptor() for lack of handler for %02x." % desctype;
- self.STALL_EP0(SUD);
- def set_configuration(self,SUD):
- """Set the configuration."""
- bmSUSPIE=0x10;
- configval=ord(SUD[wValueL]);
- if(configval>0):
- self.SETBIT(rUSBIEN,bmSUSPIE);
- self.rregAS(rFNADDR);
def get_status(self,SUD):
"""Get the USB Setup Status."""
testbyte=ord(SUD[bmRequestType])
self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
self.wregAS(rEP0BC,2);
else:
+ print "Stalling unknown status.";
self.STALL_EP0(SUD);
else:
+ print "Stalling unknown status.";
self.STALL_EP0(SUD);
- def service_irqs(self):
- """Handle USB interrupt events."""
-
- epirq=self.rreg(rEPIRQ);
- usbirq=self.rreg(rUSBIRQ);
-
- #Are we being asked for setup data?
- if(epirq&bmSUDAVIRQ): #Setup Data Requested
- self.wreg(rEPIRQ,bmSUDAVIRQ); #Clear the bit
- self.do_SETUP();
- elif(epirq&bmIN3BAVIRQ): #EN3-IN packet
- self.do_IN3();
- #self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
- elif(epirq&bmOUT1DAVIRQ): #OUT1-OUT packet
- self.do_OUT1();
- self.wregAS(rEPIRQ,bmOUT1DAVIRQ); #Clear the bit *AFTER* servicing.
- #else:
- # self.do_IN3();
-
- typestring="GoodFET emulates Mass properly, if you can read this!\n";
- typepos=0;
def do_IN3(self):
"""Handle IN3 input event."""
- #Don't bother clearing interrupt flag, that's done by sending the reply.
- #self.type_IN3();
- print "Got an input event, no idea what to do about it.";
- self.wreg(rEP3INFIFO,0x01); #Modem Status
- self.wreg(rEP3INFIFO,0x00); #Line Status
- self.wreg(rEP3INFIFO,0x00);
- self.wregAS(rEP3INBC,3);
+ # Do nothing here, as it'll be taken care of elsewhere. The
+ # interrupt just means that the buffer is empty, not that we
+ # are expected to fill it.
+
def do_OUT1(self):
"""Handle an OUT1 output event."""
print "Got an output event, printing the result.";
l=self.rreg(rEP1OUTBC);
- frame=self.readbytesAS(rEP1OUTFIFO,l);
- print "Mass OUT: %s" % frame[1:len(frame)];
- #self.type_IN3();
-
+ frame=self.readbytes(rEP1OUTFIFO,l);
+ self.handleCBW(frame);
+
+ lastCBW="";
+ def handleCBW(self,cbw):
+ """Handles an incoming Command Block Wrapper. See USB Mass
+ Storage Class for details."""
+
+ if len(cbw)!=31:
+ print "Invalid CBW length of %i bytes. Aborting." % len(cbw);
+ return;
+ sig=cbw[0:4];
+ if sig!="USBC":
+ print "Invalid CBW signature: %s. Should be USBC; aborting." % sig;
+ return;
+ self.lastCBW=cbw;
+
+ dtlen=ord(cbw[8])+(ord(cbw[9])<<8)+(ord(cbw[10])<<16)+(ord(cbw[11])<<24);
+ flags=ord(cbw[12]);
+ dtdir=flags&0x80; # 0x80 for dev->host, 0x00 for host->dev
+ lun=ord(cbw[13])&0x0F; # Should be zero, as we only reported one LUN.
+ cblen=ord(cbw[14])&0x1F;
+ cb=cbw[15:31];
+ self.handleCB(cb,cblen,dtlen,dtdir);
+
+ def handleCB(self,cb,cblen,dtlen,dtdir):
+ """Handles a command block, then replies with a CSW."""
+ print "\nGot command block 0x%02x, requesting 0x%02x bytes" % (
+ ord(cb[0]), dtlen);
+ verb=ord(cb[0]);
+ status=00; #good, set to 1 for bad.
+ if verb==0x00: # Test Unit Ready
+ # Send nothing, just the success code.
+ status=0;
+ elif verb==0x03: # Request Sense
+ print "Responding to Request Sense. Needed for Macs.";
+ response=[0x70, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0A,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x00, 0x00,
+ 0,0,0,0,0];
+ #status=1;
+ self.writebytes(rEP3INFIFO,
+ response);
+ self.wreg(rEP3INBC,len(response));
+ elif verb==0x12: #Inquiry
+ #print "Responding to CB inquiry.";
+ response=[
+ 0x00, # 00 for Direct, 1F for "no floppy"
+ 0x80, # make 0x80 for removable media
+ 0x00, # Version
+ 0x01, # Response Data Format
+ 0x1f, #Additional length.
+ 0x00, 0x00, 0x00,
+ #Manufacturer
+ ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
+ #Device name
+ ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ ord('0'),ord('.'),ord('0'),ord('1')]
+ #print "Sending %i byte reply to %i byte query." % (
+ # len(response),dtlen);
+ #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
+ # #Wait for the packet to complete before sending the next.
+ # print "Waiting to complete inquiry."
+ # pass;
+ self.writebytes(rEP3INFIFO,
+ response);
+ self.wregAS(rEP3INBC,
+ dtlen);
+ #len(response));
+ #self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
+ #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
+ # #Wait for the packet to complete before sending the next.
+ # print "Waiting to complete inquiry."
+ # pass;
+ elif verb==0x1e: #Prevent/Allow Removal
+ # Give a good status to pretend we understand.
+ status=0x00;
+ elif verb==0x1A: #Mode Sense (6)
+ # I should probably send six bytes here.
+ response=[0x12,0,0,0, 0,0,0,0x1C];
+ self.writebytes(rEP3INFIFO,
+ response);
+ self.wregAS(rEP3INBC,
+ len(response));
+ elif verb==0x23: #Read Format Capacity
+ response=[
+ 0x00, 0,0x00,0x08, #Capacity list length.
+ 0,0x00,x10,0x00, # Number of sectors, implying 10MB.
+ 0x01,0x00, #reserved/desciptor code.
+ 0x02,0x00 # 512 bytes/sector. Why is this twice?
+ ];
+ self.writebytes(rEP3INFIFO,
+ response);
+ self.wregAS(rEP3INBC,
+ len(response));
+ elif verb==0x25: #Read Capacity
+ response=[
+ 0x00, 0,0x0f,0xFF, # Last LBA; might have endianness backward.
+ 0x00,0x00,0x02,0x00 # Block length of 512 bytes.
+ ];
+ self.writebytes(rEP3INFIFO,
+ response);
+ self.wregAS(rEP3INBC,
+ len(response));
+ elif verb==0x28: #READ SECTOR
+ print "Haven't implemented READ SECTOR.";
+ sys.exit();
+ elif verb==0x2A: #WRITE SECTOR
+ print "Haven't implemented WRITE SECTOR.";
+ sys.exit();
+ else:
+ print "ERROR: Unknown SCSI command block verb %02x." % verb;
+ status=1; #Command Failed
+ if dtlen>0:
+ print "Perhaps I should send %i bytes of dummy data here." % dtlen;
+ sys.exit(1);
+ cbw=self.lastCBW;
+
+ #Now we need to send the CSW.
+ csw=[
+ #Standard prefix.
+ ord('U'),ord('S'),ord('B'),ord('S'),
+ #CBW key; must be the same as the one we're replying to.
+ ord(cbw[4]),ord(cbw[5]),ord(cbw[6]),ord(cbw[7]),
+ #CSW Data Residue, probably oughtn't be zeroed.
+ 0,0,0,0,
+ #Status byte: 00 for good, 01 for bad.
+ status];
+ self.writebytes(rEP3INFIFO,
+ csw);
+ self.wregAS(rEP3INBC,len(csw));
+
+
+ return;
#Initialize FET and set baud rate
client=GoodFETMAXUSBMass();
client.serInit()
-
client.MAXUSBsetup();
client.massinit();