From: travisutk Date: Tue, 17 Jul 2012 19:15:15 +0000 (+0000) Subject: USB Mass Storage emulator for Facedancer. Doesn't work yet. X-Git-Url: http://git.rot13.org/?p=goodfet;a=commitdiff_plain;h=8baf3779e15f289e442e2ee56495c5600606955a USB Mass Storage emulator for Facedancer. Doesn't work yet. git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1200 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- diff --git a/client/goodfet.maxusbmass b/client/goodfet.maxusbmass new file mode 100755 index 0000000..950d67d --- /dev/null +++ b/client/goodfet.maxusbmass @@ -0,0 +1,229 @@ +#!/usr/bin/env python + +#USB Mass Storage Emulator +#by Travis Goodspeed +#with thanks to Brandon Wilson and his Linky project. + +import sys; +import binascii; +import array; +import time; + +from GoodFETMAXUSB import *; + +class GoodFETMAXUSBMass(GoodFETMAXUSB): + """This emulates a USB Mass Storage device.""" + def massinit(self): + """Initialize a USB Mass Storage device.""" + self.usb_disconnect(); + time.sleep(1); + self.usb_connect(); + self.massrun(); + + def massrun(self): + """Main loop of the USB Mass Storage emulator.""" + print "Starting a Mass Storage device. This doesn't work yet."; + while 1: + self.service_irqs(); + def do_SETUP(self): + """Handle USB Enumeration""" + + #Grab the SETUP packet from the buffer. + SUD=self.readbytes(rSUDFIFO,8); + + #Parse the SETUP packet + print "Handling a setup packet of %s" % self.setup2str(SUD); + setuptype=(ord(SUD[bmRequestType])&0x60); + 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); + else: + print "Unknown bmRequestType=0x%02x." % ord(SUD[bmRequestType]) + self.STALL_EP0(SUD); + def class_request(self,SUD): + """Handle a class request.""" + print "Stalling a class request."; + self.STALL_EP0(SUD); + def vendor_request(self,SUD): + """Handle a vendor request.""" + request=ord(SUD[bRequest]); + print "Why the hell is there a vendor request?"; + #self.wreg(rEP0FIFO,0); + self.wregAS(rEP0BC,0); + def std_request(self,SUD): + """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_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): + """Handles a setup request for SR_GET_INTERFACE.""" + if ord(SUD[wIndexL]==0): + self.wreg(rEP0FIFO,0); + self.wregAS(rEP0BC,1); + else: + self.STALL_EP0(SUD); + + +#0403:6001 + +#Device Descriptor + DD=[ + + 0x12, #length + 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x81, 0x07, #Sandisk + 0x50, 0x51, #SDCZ2 Cruzer Mini Flash Drive (thin) + 0x00, 0x03, 0x00, 0x00, 0x00, 0x01 + + ]; + +#Configuration Descriptor + CD=[ + + 0x09, #Length + 0x02, #Type + 0x20, #Total Length + 0x00, 0x01, 0x01, 0x00, 0xE0, 0x00, 0x09, 0x04, 0x00, 0x00, + 0x02, #Num Endpoints + 0x08, #Mass Storage Bulk Only + 0x06, #SCSI + 0x50, 0x00, + + #IN EP3 + 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, + #OUT EP1 + 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00 + +]; + strDesc=[ +# STRING descriptor 0--Language string +"\x04\x03\x09\x04", +# [ +# 0x04, # bLength +# 0x03, # bDescriptorType = string +# 0x09,0x04 # wLANGID(L/H) = English-United Sates +# ], +# STRING descriptor 1--Manufacturer ID +"\x10\x03G\x00o\x00o\x00d\x00F\x00E\x00T\x00", +# STRING descriptor 2 - Product ID +"\x1C\x03M\x00A\x00S\x00S\x00 \x00E\x00m\x00u\x00l\x00a\x00t\x00o\x00r\x00", +# STRING descriptor 3 - Serial Number ID +"\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]) + + #Toward Device + if testbyte==0x80: + self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered + self.wreg(rEP0FIFO,0x00); #Second byte is always zero. + self.wregAS(rEP0BC,2); #Load byte count, arm transfer, and ack CTL. + #Toward Interface + elif testbyte==0x81: + self.wreg(rEP0FIFO,0x00); + self.wreg(rEP0FIFO,0x00); #Second byte is always zero. + self.wregAS(rEP0BC,2); + #Toward Endpoint + elif testbyte==0x82: + if(ord(SUD[wIndexL])==0x83): + print "This code almost certainly doesn't work."; + self.wreg(rEP0FIFO,0x01); #Stall EP3 + self.wreg(rEP0FIFO,0x00); #Second byte is always zero. + self.wregAS(rEP0BC,2); + else: + 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); + 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(); + +#Initialize FET and set baud rate +client=GoodFETMAXUSBMass(); +client.serInit() + + +client.MAXUSBsetup(); +client.massinit(); +