From: travisutk Date: Sat, 25 Aug 2012 00:37:05 +0000 (+0000) Subject: Cleaning up USB code, getting nearer to BBB mass storage. X-Git-Url: http://git.rot13.org/?p=goodfet;a=commitdiff_plain;h=c6ec45386aabdd681547728397ee163a6267559b Cleaning up USB code, getting nearer to BBB mass storage. git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1238 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- diff --git a/client/GoodFETMAXUSB.py b/client/GoodFETMAXUSB.py index 65844d7..a918810 100644 --- a/client/GoodFETMAXUSB.py +++ b/client/GoodFETMAXUSB.py @@ -204,6 +204,38 @@ bmHXFRDNIRQ =0x80 class GoodFETMAXUSB(GoodFET): MAXUSBAPP=0x40; + def service_irqs(self): + """Handle USB interrupt events.""" + epirq=self.rreg(rEPIRQ); + usbirq=self.rreg(rUSBIRQ); + + + # Note *very* well that these interrupts are handled in order. + # You might need to alter the order or swap the elif + # statements for if statements. + + #Are we being asked for setup data? + if(epirq&bmSUDAVIRQ): #Setup Data Requested + self.wreg(rEPIRQ,bmSUDAVIRQ); #Clear the bit + self.do_SETUP(); + if(epirq&bmOUT1DAVIRQ): #OUT1-OUT packet + self.do_OUT1(); + self.wregAS(rEPIRQ,bmOUT1DAVIRQ); #Clear the bit *AFTER* servicing. + if(epirq&bmIN3BAVIRQ): #IN3-IN packet + self.do_IN3(); + self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit + if(epirq&bmIN2BAVIRQ): #IN2 packet + self.do_IN2(); + self.wreg(rEPIRQ,bmIN2BAVIRQ); #Clear the bit + #else: + # print "No idea how to service this IRQ: %02x" % epirq; + def do_IN2(self): + """Overload this.""" + def do_IN3(self): + """Overload this.""" + def do_OUT1(self): + """Overload this.""" + print "Ignoring an OUT1 interrupt."; def setup2str(self,SUD): """Converts the header of a setup packet to a string.""" return "bmRequestType=0x%02x, bRequest=0x%02x, wValue=0x%04x, wIndex=0x%04x, wLength=0x%04x" % ( @@ -612,14 +644,15 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): """Handles a standard setup request.""" setuptype=ord(SUD[bRequest]); if setuptype==SR_GET_DESCRIPTOR: self.send_descriptor(SUD); - #elif setuptype==SR_SET_FEATURE: self.feature(1); + #elif setuptype==SR_SET_FEATURE: + # self.rregAS(rFNADDR); + # # self.feature(1); elif setuptype==SR_SET_CONFIGURATION: self.set_configuration(SUD); elif setuptype==SR_GET_STATUS: self.get_status(SUD); 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); def get_interface(self,SUD): @@ -795,19 +828,8 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): self.STALL_EP0(SUD); else: 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(); - if(epirq&bmIN3BAVIRQ): #EN3-IN packet - self.do_IN3(); - + + typephase=0; typestring=" Python does USB HID!"; diff --git a/client/goodfet.maxusbmass b/client/goodfet.maxusbmass index 950d67d..68ffe3c 100755 --- a/client/goodfet.maxusbmass +++ b/client/goodfet.maxusbmass @@ -37,7 +37,6 @@ class GoodFETMAXUSBMass(GoodFETMAXUSB): 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); @@ -46,7 +45,20 @@ class GoodFETMAXUSBMass(GoodFETMAXUSB): 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.""" @@ -64,9 +76,11 @@ class GoodFETMAXUSBMass(GoodFETMAXUSB): 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): @@ -76,7 +90,6 @@ class GoodFETMAXUSBMass(GoodFETMAXUSB): self.STALL_EP0(SUD); -#0403:6001 #Device Descriptor DD=[ @@ -101,10 +114,10 @@ class GoodFETMAXUSBMass(GoodFETMAXUSB): 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=[ @@ -180,50 +193,127 @@ class GoodFETMAXUSBMass(GoodFETMAXUSB): self.STALL_EP0(SUD); else: 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); + #This would be for FTDI emulation. Not for Mass Storage. + #self.wreg(rEP3INFIFO,0x01); #Modem + #self.wreg(rEP3INFIFO,0x00); #Line + #self.wreg(rEP3INFIFO,0x00); + self.wregAS(rEP3INBC,0); + + 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(); - + 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); + 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 "Got command block 0x%02x, length %i bytes" % ( + ord(cb[0]), dtlen); + verb=ord(cb[0]); + status=00; #good, set to 1 for bad. + if verb==0x00: # Test Unit Ready + response=[0,0,0,0,0,0]; + self.writebytes(rEP3INFIFO, + response); + self.wregAS(rEP3INBC,len(response)); + while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ): + #Wait for the packet to complete before sending the next. + print "Waiting to complete inquiry." + pass; + 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.wregAS(rEP3INBC,len(response)); + while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ): + #Wait for the packet to complete before sending the next. + print "Waiting to complete inquiry." + pass; + elif verb==0x12: #Inquiry + print "Responding to CB inquiry."; + response=[ + 0x00, + 0x80, # make 0x80 for removable media + 0x05, # SPC2 + 0x02, # SPC2 + 0x1f, #Additional length. + 0x00, 0x00, 0x00, + #Manufacturer + ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0, + #Device name + ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0, + 0,0,0,0,0,0,0,0, + ord('0'),ord('.'),ord('0'),ord('1')] + self.writebytes(rEP3INFIFO, + response); + self.wregAS(rEP3INBC,len(response)); + while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ): + #Wait for the packet to complete before sending the next. + print "Waiting to complete inquiry." + pass; + else: + print "ERROR: Unknown command block verb %02x." % verb; + status=1; #Command Failed + if dtlen>0: + print "Exiting, as %i bytes are expected to be transfered toward %i." % ( + dtlen,dtdir); + + sys.exit(); + 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, + #Status byte: 00 for good, 01 for bad. + status]; + self.writebytes(rEP3INFIFO, + csw); + self.wregAS(rEP3INBC,len(csw)); + + + self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the IRQ bit. + return; #Initialize FET and set baud rate client=GoodFETMAXUSBMass(); client.serInit() - client.MAXUSBsetup(); client.massinit();