Added empty handles for ejecting a disk and padding the INQUIRY.
[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(GoodFETMAXUSBDevice):
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,1);
105             #Don't send reply twice.
106             return;
107             
108         
109         print "Blindly accepting unhandled vendor request %02x" % request;
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         0x10,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         0x72,0x83,              # idProduct(L/H)--6001
143         0x01,0x00,              # bcdDevice--1234
144         1,2,3,                  # iManufacturer, iProduct, iSerialNumber
145         1                       # One configuration.
146         ];
147 #Configuration Descriptor
148     CD=[0x09,                   # bLength
149         0x02,                   # bDescriptorType = Config
150         0x20,0x00,              # wTotalLength(L/H) = 34 bytes (0x22)
151         0x01,                   # bNumInterfaces
152         0x01,                   # bConfigValue
153         0x00,                   # iConfiguration
154         0xE0,                   # bmAttributes. b7=1 b6=self-powered b5=RWU supported
155         0x01,                   # MaxPower is 2 ma
156 # INTERFACE Descriptor
157         0x09,                   # length = 9
158         0x04,                   # type = IF
159         0x00,                   # IF #0
160         0x00,                   # bAlternate Setting
161         0x02,                   # bNum Endpoints
162         0xFF,                   # bInterfaceClass = FF=vendor
163         0xFF,0xFF,              # bInterfaceSubClass, bInterfaceProtocol
164         0x02,                   # iInterface
165 # IN Endpoint Descriptor
166         0x07,                   # bLength
167         0x05,                   # bDescriptorType (Endpoint)
168         0x83,                   # bEndpointAddress (EP3-IN)             
169         0x02,                   # bmAttributes  (bulk)
170         64,0,                   # wMaxPacketSize (64)
171         00,
172 # OUT Endpoint Descriptor
173         0x07,                   # bLength
174         0x05,                   # bDescriptorType (Endpoint)
175         0x01,                   # bEndpointAddress (EP1-OUT)            
176         0x02,                   # bmAttributes  (bulk)
177         64,0,                   # wMaxPacketSize (64)
178         00];
179     strDesc=[
180 # STRING descriptor 0--Language string
181 "\x04\x03\x09\x04",
182 # [
183 #         0x04,                 # bLength
184 #       0x03,                   # bDescriptorType = string
185 #       0x09,0x04               # wLANGID(L/H) = English-United Sates
186 # ],
187 # STRING descriptor 1--Manufacturer ID
188 "\x10\x03G\x00o\x00o\x00d\x00F\x00E\x00T\x00",
189 # STRING descriptor 2 - Product ID
190 "\x18\x03F\x00T\x00D\x00I\x00 \x00E\x00m\x00u\x00l\x00a\x00t\x00o\x00r\x00 \x00 \x00 \x00 \x00 \x00",
191 # STRING descriptor 3 - Serial Number ID
192 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
193 ];
194
195
196     def set_configuration(self,SUD):
197         """Set the configuration."""
198         bmSUSPIE=0x10;
199         configval=ord(SUD[wValueL]);
200         if(configval>0):
201             self.SETBIT(rUSBIEN,bmSUSPIE);
202         self.rregAS(rFNADDR);
203     def get_status(self,SUD):
204         """Get the USB Setup Status."""
205         testbyte=ord(SUD[bmRequestType])
206         
207         #Toward Device
208         if testbyte==0x80:
209             self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
210             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
211             self.wregAS(rEP0BC,2);    #Load byte count, arm transfer, and ack CTL.
212         #Toward Interface
213         elif testbyte==0x81:
214             self.wreg(rEP0FIFO,0x00);
215             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
216             self.wregAS(rEP0BC,2);
217         #Toward Endpoint
218         elif testbyte==0x82:
219             if(ord(SUD[wIndexL])==0x83):
220                 self.wreg(rEP0FIFO,0x01); #Stall EP3
221                 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
222                 self.wregAS(rEP0BC,2);
223             else:
224                 self.STALL_EP0(SUD);
225         else:
226             self.STALL_EP0(SUD);
227     def service_irqs(self):
228         """Handle USB interrupt events."""
229         
230         epirq=self.rreg(rEPIRQ);
231         usbirq=self.rreg(rUSBIRQ);
232         
233         #Are we being asked for setup data?
234         if(epirq&bmSUDAVIRQ): #Setup Data Requested
235             self.wreg(rEPIRQ,bmSUDAVIRQ); #Clear the bit
236             self.do_SETUP();
237         elif(epirq&bmIN3BAVIRQ): #EN3-IN packet
238             self.do_IN3();
239             #self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
240         elif(epirq&bmOUT1DAVIRQ): #OUT1-OUT packet
241             self.do_OUT1();
242             self.wregAS(rEPIRQ,bmOUT1DAVIRQ); #Clear the bit *AFTER* servicing.
243         #else:
244         #    self.do_IN3();
245     
246     typestring="GoodFET emulates FTDI properly, if you can read this!\n";
247     typepos=0;
248     
249     def type_IN3(self):
250         """Type next letter in buffer."""
251         if self.typepos>=len(self.typestring):
252             self.typepos=0;
253             self.typeletter(' ');
254         else:
255             self.typeletter(self.typestring[self.typepos]);
256             self.typepos=self.typepos+1;
257         return;
258     def typeletter(self,key):
259         """Type a letter on IN3.  Zero for keyup."""
260         if type(key)==str: key=ord(key);
261         
262         self.wreg(rEP3INFIFO,0x01);      #Modem Status
263         self.wreg(rEP3INFIFO,0x00);      #Line Status
264         self.wreg(rEP3INFIFO,key);
265         self.wregAS(rEP3INBC,3);
266     def do_IN3(self):
267         """Handle IN3 input event."""
268         #Don't bother clearing interrupt flag, that's done by sending the reply.
269         self.type_IN3();
270     def do_OUT1(self):
271         """Handle an OUT1 output event."""
272         print "Got an output event, printing the result.";
273         l=self.rreg(rEP1OUTBC);
274         frame=self.readbytesAS(rEP1OUTFIFO,l);
275         print "FTDI OUT: %s" % frame[1:len(frame)];
276         #self.type_IN3();
277
278 #Initialize FET and set baud rate
279 client=GoodFETMAXUSBFTDI();
280 client.serInit()
281
282
283 client.MAXUSBsetup();
284 client.hidinit();
285