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