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