#!/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();