Fixed FTDI emulation.
[goodfet] / client / goodfet.maxusbftdi
1 #!/usr/bin/env python
2
3 #FTDI USB Device Emulator
4 #by Travis Goodspeed
5
6 import sys;
7 import binascii;
8 import array;
9 import time;
10
11 from GoodFETMAXUSB import *;
12
13 class GoodFETMAXUSBFTDI(GoodFETMAXUSB):
14     """This emulates the FTDI USB to Serial chips."""
15     def hidinit(self):
16         """Initialize a USB FTDI device."""
17         self.usb_disconnect();
18         time.sleep(1);
19         self.usb_connect();
20         self.ftdirun();
21         
22     def ftdirun(self):
23         """Main loop of the USB FTDI emulator."""
24         print "Starting a FTDI device.  This won't return.";
25         while 1:
26             self.service_irqs();
27             #self.typeletter_empty();
28     def do_SETUP(self):
29         """Handle USB Enumeration"""
30         
31         #Grab the SETUP packet from the buffer.
32         SUD=self.readbytes(rSUDFIFO,8);
33         
34         #Parse the SETUP packet
35         print "Handling a setup packet of %s" % self.setup2str(SUD);
36         setuptype=(ord(SUD[bmRequestType])&0x60);
37         if setuptype==0x00:
38             self.std_request(SUD);
39         elif setuptype==0x20:
40             self.class_request(SUD);
41         elif setuptype==0x40:
42             self.vendor_request(SUD);
43         else:
44             print "Unknown request type 0x%02x." % ord(SUD[bmRequestType])
45             self.STALL_EP0(SUD);
46     def ftdi_request(self,SUD):
47         """Handle an FTDI request."""
48         
49     def class_request(self,SUD):
50         """Handle a class request."""
51         print "Stalling a class request.";
52         self.STALL_EP0(SUD);
53     def vendor_request(self,SUD):
54         """Handle an FTDI vendor request."""
55         request=ord(SUD[bRequest]);
56         
57         if request==0:   #reset
58             pass
59         elif request==1: #modem_ctrl
60             valuel=ord(SUD[wValueL])
61             valueh=ord(SUD[wValueH]);
62             dtr=valuel&1;
63             rts=(valuel&2)>>1;
64             dtren=valueh&1;
65             rtsen=(valueh&2)>>1;
66             
67             if dtren: print "DTR is enabled, value %i" % dtr;
68             if rtsen: print "RTS is enabled, value %i" % rts;
69             
70             pass;
71         elif request==2: #set_flow_ctrl
72             indexh=ord(SUD[wIndexH]);
73             indexl=ord(SUD[wIndexL]);
74             if indexh==0:
75                 print "SET_FLOW_CTRL to no handshaking.";
76             if indexl&1:
77                 print "SET_FLOW_CTRL for RTS/CTS handshaking.";
78             if indexl&2:
79                 print "SET_FLOW_CTRL for DTR/DSR handshaking.";
80             if indexl&4:
81                 print "SET_FLOW_CTRL for XON/XOFF handshaking.";
82             
83             pass;
84         elif request==3: #set_baud_rate
85             print "Baud rate set to %i." % ord(SUD[wValueL]);
86             pass;
87         elif request==4: #set_data
88             pass;
89         elif request==5: #get_status
90             print "I don't know how to send the status.";
91             pass; #FIXME
92         elif request==6: #set_event_char
93             pass;
94         elif request==7: #set_error_char
95             pass;
96         elif request==9: #set_latency_timer
97             print "Expected to set latency timer to 0x%02x." % ord(SUD[wValueL]);
98             pass;
99         elif request==0x0a: #get_latency_timer
100             print "Bullshitting a value for the latency timer."
101             #Send some sort of reply.
102             self.wreg(rEP0FIFO,0x01);
103             self.wreg(rEP0FIFO,0x00);
104             self.wregAS(rEP0BC,2);
105             #Don't send reply twice.
106             return;
107             
108         
109         print "Blindly accepting vendor request";
110         #self.wreg(rEP0FIFO,0);
111         self.wregAS(rEP0BC,0);
112     def std_request(self,SUD):
113         """Handles a standard setup request."""
114         setuptype=ord(SUD[bRequest]);
115         if setuptype==SR_GET_DESCRIPTOR: self.send_descriptor(SUD);
116         #elif setuptype==SR_SET_FEATURE: self.feature(1);
117         elif setuptype==SR_SET_CONFIGURATION: self.set_configuration(SUD);
118         elif setuptype==SR_GET_STATUS: self.get_status(SUD);
119         elif setuptype==SR_SET_ADDRESS: self.rregAS(rFNADDR);
120         elif setuptype==SR_GET_INTERFACE: self.get_interface(SUD);
121         else:
122             print "Stalling Unknown standard setup request type %02x" % setuptype;
123             self.STALL_EP0(SUD);
124     
125     def get_interface(self,SUD):
126         """Handles a setup request for SR_GET_INTERFACE."""
127         if ord(SUD[wIndexL]==0):
128             self.wreg(rEP0FIFO,0);
129             self.wregAS(rEP0BC,1);
130         else:
131             self.STALL_EP0(SUD);
132     
133
134 #0403:6001
135
136 #Device Descriptor
137     DD=[0x12,                   # bLength = 18d
138         0x01,                   # bDescriptorType = Device (1)
139         0x10,0x01,              # bcdUSB(L/H) USB spec rev (BCD)
140         0x00,0x00,0x00,         # bDeviceClass, bDeviceSubClass, bDeviceProtocol
141         0x40,                   # bMaxPacketSize0 EP0 is 64 bytes
142         0x03,0x04,              # idVendor(L/H)--FTDI is 0403
143         0x72,0x83,              # idProduct(L/H)--6001
144         0x01,0x00,              # bcdDevice--1234
145         1,2,3,                  # iManufacturer, iProduct, iSerialNumber
146         1                       # One configuration.
147         ];
148 #Configuration Descriptor
149     CD=[0x09,                   # bLength
150         0x02,                   # bDescriptorType = Config
151         0x20,0x00,              # wTotalLength(L/H) = 34 bytes (0x22)
152         0x01,                   # bNumInterfaces
153         0x01,                   # bConfigValue
154         0x00,                   # iConfiguration
155         0xE0,                   # bmAttributes. b7=1 b6=self-powered b5=RWU supported
156         0x01,                   # MaxPower is 2 ma
157 # INTERFACE Descriptor
158         0x09,                   # length = 9
159         0x04,                   # type = IF
160         0x00,                   # IF #0
161         0x00,                   # bAlternate Setting
162         0x02,                   # bNum Endpoints
163         0xFF,                   # bInterfaceClass = FF=vendor
164         0xFF,0xFF,              # bInterfaceSubClass, bInterfaceProtocol
165         0x02,                   # iInterface
166 # IN Endpoint Descriptor
167         0x07,                   # bLength
168         0x05,                   # bDescriptorType (Endpoint)
169         0x83,                   # bEndpointAddress (EP3-IN)             
170         0x02,                   # bmAttributes  (bulk)
171         64,0,                   # wMaxPacketSize (64)
172         00,
173 # OUT Endpoint Descriptor
174         0x07,                   # bLength
175         0x05,                   # bDescriptorType (Endpoint)
176         0x01,                   # bEndpointAddress (EP1-OUT)            
177         0x02,                   # bmAttributes  (bulk)
178         64,0,                   # wMaxPacketSize (64)
179         00];
180     strDesc=[
181 # STRING descriptor 0--Language string
182 "\x04\x03\x09\x04",
183 # [
184 #         0x04,                 # bLength
185 #       0x03,                   # bDescriptorType = string
186 #       0x09,0x04               # wLANGID(L/H) = English-United Sates
187 # ],
188 # STRING descriptor 1--Manufacturer ID
189 "\x10\x03G\x00o\x00o\x00d\x00F\x00E\x00T\x00",
190 # STRING descriptor 2 - Product ID
191 "\x18\x03F\x00T\x00D\x00I\x00 \x00E\x00m\x00u\x00l\x00a\x00t\x00o\x00r\x00 \x00 \x00 \x00 \x00 \x00",
192 # STRING descriptor 3 - Serial Number ID
193 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
194 ];
195
196     def send_descriptor(self,SUD):
197         """Send the USB descriptors based upon the setup data."""
198         desclen=0;
199         reqlen=ord(SUD[wLengthL])+256*ord(SUD[wLengthH]); #16-bit length
200         desctype=ord(SUD[wValueH]);
201         
202         if desctype==GD_DEVICE:
203             desclen=self.DD[0];
204             ddata=self.DD;
205         elif desctype==GD_CONFIGURATION:
206             desclen=self.CD[2];
207             ddata=self.CD;
208         elif desctype==GD_STRING:
209             desclen=self.strDesc[ord(SUD[wValueL])][0];
210             ddata=self.strDesc[ord(SUD[wValueL])];
211         
212         #TODO Configuration, String, Hid, and Report
213         
214         if desclen>0:
215             sendlen=min(reqlen,desclen);
216             self.writebytes(rEP0FIFO,ddata);
217             self.wregAS(rEP0BC,sendlen);
218         else:
219             print "Stalling in send_descriptor() for lack of handler for %02x." % desctype;
220             self.STALL_EP0(SUD);
221     def set_configuration(self,SUD):
222         """Set the configuration."""
223         bmSUSPIE=0x10;
224         configval=ord(SUD[wValueL]);
225         if(configval>0):
226             self.SETBIT(rUSBIEN,bmSUSPIE);
227         self.rregAS(rFNADDR);
228     def get_status(self,SUD):
229         """Get the USB Setup Status."""
230         testbyte=ord(SUD[bmRequestType])
231         
232         #Toward Device
233         if testbyte==0x80:
234             self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
235             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
236             self.wregAS(rEP0BC,2);    #Load byte count, arm transfer, and ack CTL.
237         #Toward Interface
238         elif testbyte==0x81:
239             self.wreg(rEP0FIFO,0x00);
240             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
241             self.wregAS(rEP0BC,2);
242         #Toward Endpoint
243         elif testbyte==0x82:
244             if(ord(SUD[wIndexL])==0x83):
245                 self.wreg(rEP0FIFO,0x01); #Stall EP3
246                 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
247                 self.wregAS(rEP0BC,2);
248             else:
249                 self.STALL_EP0(SUD);
250         else:
251             self.STALL_EP0(SUD);
252     def service_irqs(self):
253         """Handle USB interrupt events."""
254         
255         epirq=self.rreg(rEPIRQ);
256         usbirq=self.rreg(rUSBIRQ);
257         
258         #Are we being asked for setup data?
259         if(epirq&bmSUDAVIRQ): #Setup Data Requested
260             self.wreg(rEPIRQ,bmSUDAVIRQ); #Clear the bit
261             self.do_SETUP();
262         elif(epirq&bmIN3BAVIRQ): #EN3-IN packet
263             self.do_IN3();
264             #self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
265         elif(epirq&bmOUT1DAVIRQ): #OUT1-OUT packet
266             self.do_OUT1();
267             self.wregAS(rEPIRQ,bmOUT1DAVIRQ); #Clear the bit *AFTER* servicing.
268         #else:
269         #    self.do_IN3();
270     
271     typestring="GoodFET emulates FTDI properly, if you can read this!\n";
272     typepos=0;
273     
274     def type_IN3(self):
275         """Type next letter in buffer."""
276         if self.typepos>=len(self.typestring):
277             self.typepos=0;
278             self.typeletter(' ');
279         else:
280             self.typeletter(self.typestring[self.typepos]);
281             self.typepos=self.typepos+1;
282         return;
283     def typeletter(self,key):
284         """Type a letter on IN3.  Zero for keyup."""
285         if type(key)==str: key=ord(key);
286         
287         self.wreg(rEP3INFIFO,0x01);      #Modem Status
288         self.wreg(rEP3INFIFO,0x00);      #Line Status
289         self.wreg(rEP3INFIFO,key);
290         self.wregAS(rEP3INBC,3);
291     def do_IN3(self):
292         """Handle IN3 input event."""
293         #Don't bother clearing interrupt flag, that's done by sending the reply.
294         self.type_IN3();
295     def do_OUT1(self):
296         """Handle an OUT1 output event."""
297         print "Got an output event, printing the result.";
298         l=self.rreg(rEP1OUTBC);
299         frame=self.readbytesAS(rEP1OUTFIFO,l);
300         print "FTDI OUT: %s" % frame[1:len(frame)];
301         #self.type_IN3();
302
303 #Initialize FET and set baud rate
304 client=GoodFETMAXUSBFTDI();
305 client.serInit()
306
307
308 client.MAXUSBsetup();
309 client.hidinit();
310