3 #DFU USB Device Emulator
11 from GoodFETMAXUSB import *;
13 class GoodFETMAXUSBDFU(GoodFETMAXUSBDevice):
15 """This emulates the DFU USB to Serial chips."""
16 def dfuinit(self,vid=0xFFFF,pid=0x0004):
17 """Initialize a USB DFU device."""
18 self.usb_disconnect();
22 def dfurun(self,vid,pid):
23 """Main loop of the USB DFU emulator."""
24 print "Starting a DFU device as %04X:%04X" % (vid,pid);
28 self.DD[9]=(vid>>8)&0xFF;
30 self.DD[11]=(pid>>8)&0xFF;
32 #Run the service loop.
36 """Handle USB Enumeration"""
37 #Grab the SETUP packet from the buffer.
38 SUD=self.readbytes(rSUDFIFO,8);
40 #Parse the SETUP packet
41 #print "Handling a setup packet of %s" % self.setup2str(SUD);
42 setuptype=(ord(SUD[bmRequestType])&0x60);
44 self.std_request(SUD);
46 self.class_request(SUD);
48 self.vendor_request(SUD);
50 print "Unknown request type 0x%02x." % ord(SUD[bmRequestType])
52 def printblock(self,block,data):
53 """Prints a block, perhaps inserting it into the dump file."""
56 s=s+("%02x "%ord(foo));
57 print "BLOCK %04x : %s" % (block,s);
58 sys.stdout.flush(); #Needed for the tee command.
60 def handle_dfu_download(self,SUD):
61 """Sometimes this comes from a Class request, sometimes a Vendor."""
62 #Compute the total length, though we'll be accepting 64-byte chunks.
65 (ord(SUD[wLengthH])<<8)
67 block=ord(SUD[wValueL])+ (ord(SUD[wValueH])<<8);
70 while not(self.rreg(rEPIRQ)&bmOUT0DAVIRQ): pass;
71 b=b+self.readbytes(rEP0FIFO,min(l,64));
72 self.wreg(rEPIRQ,bmOUT0DAVIRQ); #Clear the bit
73 if self.usbverbose: print "Got %i/%i bytes." % (len(b),l);
75 self.printblock(block,b);
78 #Signify that we got everything.
79 self.wregAS(rEP0BC,0);
81 if self.usbverbose: print "Completed data block.";
87 dfustate=DFUIDLE; #Some clients get picky about this.
88 def class_request(self,SUD):
89 """Handle a class request."""
91 request=ord(SUD[bRequest]);
93 if request==0: #DETACH
94 print "DFU DETACH; this probably means the download is complete.";
95 self.wregAS(rEP0BC,0);
97 elif request==1: #Download
98 self.handle_dfu_download(SUD);
99 self.dfustate=self.DFUDNIDLE;
101 elif request==2: #Upload
102 print "TODO Implement uploads.";
104 elif request==3: #GetStatus
105 self.writebytes(rEP0FIFO,
107 self.wregAS(rEP0BC,6);
109 elif request==4: #ClearStatus
111 elif request==5: #GetState
112 print "Returning state of %02x." % self.dfustate
113 #Send some sort of reply.
114 #self.wreg(rEP0FIFO,0x02); #DFU IDLE
115 self.wreg(rEP0FIFO,self.dfustate);
116 self.wregAS(rEP0BC,1);
117 #Don't send reply twice.
119 elif request==6: #Abort
121 self.dfustate=self.DFUDNIDLE;
122 self.wregAS(rEP0BC,0);
125 print "Blindly accepting unhandled class request %02x" % request;
126 self.wregAS(rEP0BC,0);
127 def vendor_request(self,SUD):
128 """Handle an DFU vendor request."""
129 request=ord(SUD[bRequest]);
131 print "Blindly accepting unhandled vendor request %02x" % request;
132 self.wregAS(rEP0BC,0);
133 def std_request(self,SUD):
134 """Handles a standard setup request."""
135 setuptype=ord(SUD[bRequest]);
136 if setuptype==SR_GET_DESCRIPTOR: self.send_descriptor(SUD);
137 #elif setuptype==SR_SET_FEATURE: self.feature(1);
138 elif setuptype==SR_SET_CONFIGURATION: self.set_configuration(SUD);
139 elif setuptype==SR_GET_STATUS: self.get_status(SUD);
140 elif setuptype==SR_SET_ADDRESS: self.rregAS(rFNADDR);
141 elif setuptype==SR_GET_INTERFACE: self.get_interface(SUD);
143 print "Stalling Unknown standard setup request type %02x" % setuptype;
146 def get_interface(self,SUD):
147 """Handles a setup request for SR_GET_INTERFACE."""
148 if ord(SUD[wIndexL]==0):
149 self.wreg(rEP0FIFO,0);
150 self.wregAS(rEP0BC,1);
157 #Device Descriptor; be sure to overwrite VID and PID.
158 DD=[0x12, # bLength = 18d
159 0x01, # bDescriptorType = Device (1)
160 0x10,0x01, # bcdUSB(L/H) USB spec rev (BCD)
161 0x00,0x00,0x00, # bDeviceClass, bDeviceSubClass, bDeviceProtocol
162 0x40, # bMaxPacketSize0 EP0 is 64 bytes
163 0x03,0x04, # idVendor(L/H)-- Offset 8,9
164 0x72,0x83, # idProduct(L/H)-- Offset 10,11
165 0x01,0x00, # bcdDevice--1234
166 1,2,3, # iManufacturer, iProduct, iSerialNumber
167 1 # One configuration.
169 #Configuration Descriptor
171 0x02, # bDescriptorType = Config
172 0x20,0x00, # wTotalLength(L/H) = 34 bytes (0x22)
173 0x01, # bNumInterfaces
175 0x00, # iConfiguration
176 0xE0, # bmAttributes. b7=1 b6=self-powered b5=RWU supported
177 0x01, # MaxPower is 2 ma
178 # INTERFACE Descriptor
182 0x00, # bAlternate Setting
183 0x02, # bNum Endpoints
184 0xFE, # bInterfaceClass = FF=vendor
185 0x01,0x02, # bInterfaceSubClass, bInterfaceProtocol
187 # IN Endpoint Descriptor, unused.
189 0x05, # bDescriptorType (Endpoint)
190 0x83, # bEndpointAddress (EP3-IN)
191 0x02, # bmAttributes (bulk)
192 64,0, # wMaxPacketSize (64)
194 # OUT Endpoint Descriptor, unused.
196 0x05, # bDescriptorType (Endpoint)
197 0x01, # bEndpointAddress (EP1-OUT)
198 0x02, # bmAttributes (bulk)
199 64,0, # wMaxPacketSize (64)
202 # STRING descriptor 0--Language string
206 # 0x03, # bDescriptorType = string
207 # 0x09,0x04 # wLANGID(L/H) = English-United Sates
209 # STRING descriptor 1--Manufacturer ID
210 "\x10\x03G\x00o\x00o\x00d\x00F\x00E\x00T\x00",
211 # STRING descriptor 2 - Product ID
212 "\x18\x03D\x00F\x00U\x00 \x00 \x00E\x00m\x00u\x00l\x00a\x00t\x00o\x00r\x00 \x00 \x00 \x00 \x00 \x00",
213 # STRING descriptor 3 - Serial Number ID
214 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
218 def set_configuration(self,SUD):
219 """Set the configuration."""
221 configval=ord(SUD[wValueL]);
223 self.SETBIT(rUSBIEN,bmSUSPIE);
224 self.rregAS(rFNADDR);
225 def get_status(self,SUD):
226 """Get the USB Setup Status."""
227 testbyte=ord(SUD[bmRequestType])
231 self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
232 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
233 self.wregAS(rEP0BC,2); #Load byte count, arm transfer, and ack CTL.
236 self.wreg(rEP0FIFO,0x00);
237 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
238 self.wregAS(rEP0BC,2);
241 if(ord(SUD[wIndexL])==0x83):
242 self.wreg(rEP0FIFO,0x01); #Stall EP3
243 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
244 self.wregAS(rEP0BC,2);
249 def service_irqs(self):
250 """Handle USB interrupt events."""
252 epirq=self.rreg(rEPIRQ);
253 usbirq=self.rreg(rUSBIRQ);
255 #Are we being asked for setup data?
256 if(epirq&bmSUDAVIRQ): #Setup Data Requested
257 self.wreg(rEPIRQ,bmSUDAVIRQ); #Clear the bit
259 elif(epirq&bmIN3BAVIRQ): #EN3-IN packet
262 self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
263 elif(epirq&bmOUT1DAVIRQ): #OUT1-OUT packet
266 self.wregAS(rEPIRQ,bmOUT1DAVIRQ); #Clear the bit *AFTER* servicing.
270 typestring="GoodFET emulates DFU properly, if you can read this!\n";
273 def typeletter(self,key):
274 """Type a letter on IN3. Zero for keyup."""
275 if type(key)==str: key=ord(key);
277 self.wreg(rEP3INFIFO,0x01); #Modem Status
278 self.wreg(rEP3INFIFO,0x00); #Line Status
279 self.wreg(rEP3INFIFO,key);
280 self.wregAS(rEP3INBC,3);
282 """Handle IN3 input event."""
283 #Don't bother clearing interrupt flag, that's done by sending the reply.
286 """Handle an OUT1 output event."""
288 Got an output event, but it's not part of the DFU standard so this
289 client can't know what to do with it. Usually, this needs some sort
290 of acknowledgment to tell the host that you are switching into.
293 l=self.rreg(rEP1OUTBC);
294 frame=self.readbytesAS(rEP1OUTFIFO,l);
295 print "DFU OUT1: %s" % frame[1:len(frame)];
300 print "Usage: %s VID PID" % sys.argv[0];
302 print """Example VID/PID pairs:
303 \tFFFF 0004 -- Ubertooth ( Works )
304 \t0483 DF11 -- STM32 (Untested)
305 \t03EB 2F.. -- Atmel DFU (Untested)
306 \t05AC 1227 -- Apple iBoot (Untested)
311 #Initialize FET and set baud rate
312 client=GoodFETMAXUSBDFU();
315 vid=int(sys.argv[1],16);
316 pid=int(sys.argv[2],16);
318 client.MAXUSBsetup();
321 The DFU emulator is now running. Any firmware which is downloaded to
322 the virtual device will be locked to this console, beginning with the
325 client.dfuinit(vid,pid);