+ def vbus_on(self):
+ """Turn on the target device."""
+ self.wreg(rIOPINS2,(self.rreg(rIOPINS2)|0x08));
+ def vbus_off(self):
+ """Turn off the target device's power."""
+ self.wreg(rIOPINS2,0x00);
+ def reset_host(self):
+ """Resets the chip into host mode."""
+ self.wreg(rUSBCTL,bmCHIPRES); #Stop the oscillator.
+ self.wreg(rUSBCTL,0x00); #restart it.
+ while self.rreg(rUSBIRQ)&bmOSCOKIRQ:
+ #Hang until the PLL stabilizes.
+ pass;
+
+class GoodFETMAXUSBHost(GoodFETMAXUSB):
+ """This is a class for implemented a minimal USB host.
+ It's intended for fuzzing, rather than for daily use."""
+ def hostinit(self):
+ """Initialize the MAX3421 as a USB Host."""
+ self.usb_connect();
+ self.wreg(rPINCTL,(bmFDUPSPI|bmPOSINT));
+ self.reset_host();
+ self.vbus_off();
+ time.sleep(0.2);
+ self.vbus_on();
+
+ #self.hostrun();
+ def hostrun(self):
+ """Run as a minimal host and dump the config tables."""
+ while 1:
+ self.detect_device();
+ time.sleep(0.2);
+ self.enumerate_device();
+ self.wait_for_disconnect();
+ def detect_device(self):
+ """Waits for a device to be inserted and then returns."""
+ busstate=0;
+
+ #Activate host mode and turn on 15K pulldown resistors on D+ and D-.
+ self.wreg(rMODE,(bmDPPULLDN|bmDMPULLDN|bmHOST));
+ #Clear connection detect IRQ.
+ self.wreg(rHIRQ,bmCONDETIRQ);
+
+ print "Waiting for a device connection.";
+ while busstate==0:
+ self.wreg(rHCTL,bmSAMPLEBUS); #Update JSTATUS and KSTATUS bits.
+ busstate=self.rreg(rHRSL) & (bmJSTATUS|bmKSTATUS);
+
+ if busstate==bmJSTATUS:
+ print "Detected Full-Speed Device.";
+ self.wreg(rMODE,(bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB));
+ elif busstate==bmKSTATUS:
+ print "Detected Low-Speed Device.";
+ self.wreg(rMODE,(bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB));
+ else:
+ print "Not sure whether this is Full-Speed or Low-Speed. Please investigate.";
+ def wait_for_disconnect(self):
+ """Wait for a device to be disconnected."""
+ print "Waiting for a device disconnect.";
+
+ self.wreg(rHIRQ,bmCONDETIRQ); #Clear disconnect IRQ
+ while not (self.rreg(rHIRQ) & bmCONDETIRQ):
+ #Wait for IRQ to change.
+ pass;
+
+ #Turn off markers.
+ self.wreg(rMODE,bmDPPULLDN|bmDMPULLDN|bmHOST);
+ print "Device disconnected.";
+ self.wreg(rIOPINS2,(self.rreg(rIOPINS2) & ~0x04)); #HL1_OFF
+ self.wreg(rIOPINS1,(self.rreg(rIOPINS1) & ~0x02)); #HL4_OFF
+
+ def enumerate_device(self):
+ """Enumerates a device on the present port."""
+
+ Set_Address_to_7 = [0x00,0x05,0x07,0x00,0x00,0x00,0x00,0x00];
+ Get_Descriptor_Device = [0x80,0x06,0x00,0x01,0x00,0x00,0x00,0x00]; #len filled in
+ Get_Descriptor_Config = [0x80,0x06,0x00,0x02,0x00,0x00,0x00,0x00];
+
+
+ print "Issuing USB bus reset.";
+ self.wreg(rHCTL,bmBUSRST);
+ while self.rreg(rHCTL) & bmBUSRST:
+ #Wait for reset to complete.
+ pass;
+
+ time.sleep(0.2);
+
+ #Get the device descriptor.
+ self.wreg(rPERADDR,0); #First request to address 0.
+ self.maxPacketSize=8; #Only safe value for first check.
+ Get_Descriptor_Device[6]=8; # wLengthL
+ Get_Descriptor_Device[7]=0; # wLengthH
+
+ print "Fetching 8 bytes of Device Descriptor.";
+ self.ctl_read(Get_Descriptor_Device); # Get device descriptor into self.xfrdata;
+ self.maxPacketSize=self.xfrdata[7];
+ print "EP0 maxPacketSize is %02i bytes." % self.maxPacketSize;
+
+ # Issue another USB bus reset
+ print "Resetting the bus again."
+ self.wreg(rHCTL,bmBUSRST);
+ while self.rreg(rHCTL) & bmBUSRST:
+ #Wait for reset to complete.
+ pass;
+ time.sleep(0.2);
+
+ # Set_Address to 7 (Note: this request goes to address 0, already set in PERADDR register).
+ print "Setting address to 0x07";
+ HR = self.ctl_write_nd(Set_Address_to_7); # CTL-Write, no data stage
+ #if(print_error(HR)) return;
+
+ time.sleep(0.002); # Device gets 2 msec recovery time
+ self.wreg(rPERADDR,7); # now all transfers go to addr 7
+
+
+ #Get the device descriptor at the assigned address.
+ Get_Descriptor_Device[6]=0x12; #Fill in real descriptor length.
+ print "Fetching Device Descriptor."
+ self.ctl_read(Get_Descriptor_Device); #Result in self.xfrdata;
+
+ self.descriptor=self.xfrdata;
+ self.VID = self.xfrdata[8] + 256*self.xfrdata[9];
+ self.PID = self.xfrdata[10]+ 256*self.xfrdata[11];
+ iMFG = self.xfrdata[14];
+ iPROD = self.xfrdata[15];
+ iSERIAL = self.xfrdata[16];
+
+ self.manufacturer=self.getDescriptorString(iMFG);
+ self.product=self.getDescriptorString(iPROD);
+ self.serial=self.getDescriptorString(iSERIAL);
+
+ self.printstrings();
+
+ def printstrings(self):
+ print "Vendor ID is %04x." % self.VID;
+ print "Product ID is %04x." % self.PID;
+ print "Manufacturer: %s" % self.manufacturer;
+ print "Product: %s" % self.product;
+ print "Serial: %s" % self.serial;
+
+ def getDescriptorString(self, index):
+ """Grabs a string from the descriptor string table."""
+ # Get_Descriptor-String template. Code fills in idx at str[2].
+ Get_Descriptor_String = [0x80,0x06,index,0x03,0x00,0x00,0x40,0x00];
+
+ if index==0: return "MISSING STRING";
+
+ status=self.ctl_read(Get_Descriptor_String);
+ if status: return None;
+
+ #Since we've got a string
+ toret="";
+ for c in self.xfrdata[2:len(self.xfrdata)]:
+ if c>0: toret=toret+chr(c);
+ return toret;
+