bf257c891f44968013a3538764db5815f0c293b2
[goodfet] / client / GoodFETMAXUSB.py
1 #!/usr/bin/env python
2 # GoodFET Client Library for Maxim USB Chips.
3
4 # (C) 2012 Travis Goodspeed <travis at radiantmachines.com>
5 #
6 # This code is being rewritten and refactored.  You've been warned!
7
8 import sys, time, string, cStringIO, struct, glob, os;
9
10 from GoodFET import GoodFET;
11
12 #Handy registers.
13 rEP0FIFO=0
14 rEP1OUTFIFO=1
15 rEP2INFIFO=2
16 rEP3INFIFO=3
17 rSUDFIFO=4
18 rEP0BC=5
19 rEP1OUTBC=6
20 rEP2INBC=7
21 rEP3INBC=8
22 rEPSTALLS=9
23 rCLRTOGS=10
24 rEPIRQ=11
25 rEPIEN=12
26 rUSBIRQ=13
27 rUSBIEN=14
28 rUSBCTL=15
29 rCPUCTL=16
30 rPINCTL=17
31 rREVISION=18
32 rFNADDR=19
33 rIOPINS=20
34
35 # R11 EPIRQ register bits
36 bmSUDAVIRQ =0x20
37 bmIN3BAVIRQ =0x10
38 bmIN2BAVIRQ =0x08
39 bmOUT1DAVIRQ= 0x04
40 bmOUT0DAVIRQ= 0x02
41 bmIN0BAVIRQ =0x01
42
43 # R12 EPIEN register bits
44 bmSUDAVIE   =0x20
45 bmIN3BAVIE  =0x10
46 bmIN2BAVIE  =0x08
47 bmOUT1DAVIE =0x04
48 bmOUT0DAVIE =0x02
49 bmIN0BAVIE  =0x01
50
51
52 # ************************
53 # Standard USB Requests
54 SR_GET_STATUS           =0x00   # Get Status
55 SR_CLEAR_FEATURE        =0x01   # Clear Feature
56 SR_RESERVED             =0x02   # Reserved
57 SR_SET_FEATURE          =0x03   # Set Feature
58 SR_SET_ADDRESS          =0x05   # Set Address
59 SR_GET_DESCRIPTOR       =0x06   # Get Descriptor
60 SR_SET_DESCRIPTOR       =0x07   # Set Descriptor
61 SR_GET_CONFIGURATION    =0x08   # Get Configuration
62 SR_SET_CONFIGURATION    =0x09   # Set Configuration
63 SR_GET_INTERFACE        =0x0a   # Get Interface
64 SR_SET_INTERFACE        =0x0b   # Set Interface
65
66 # Get Descriptor codes  
67 GD_DEVICE               =0x01   # Get device descriptor: Device
68 GD_CONFIGURATION        =0x02   # Get device descriptor: Configuration
69 GD_STRING               =0x03   # Get device descriptor: String
70 GD_HID                  =0x21   # Get descriptor: HID
71 GD_REPORT               =0x22   # Get descriptor: Report
72
73 # SETUP packet offsets
74 bmRequestType           =0
75 bRequest                =1
76 wValueL                 =2
77 wValueH                 =3
78 wIndexL                 =4
79 wIndexH                 =5
80 wLengthL                =6
81 wLengthH                =7
82
83 # HID bRequest values
84 GET_REPORT              =1
85 GET_IDLE                =2
86 GET_PROTOCOL            =3
87 SET_REPORT              =9
88 SET_IDLE                =0x0A
89 SET_PROTOCOL            =0x0B
90 INPUT_REPORT            =1
91
92
93
94
95 class GoodFETMAXUSB(GoodFET):
96     MAXUSBAPP=0x40;
97     def MAXUSBsetup(self):
98         """Move the FET into the MAXUSB application."""
99         self.writecmd(self.MAXUSBAPP,0x10,0,self.data); #MAXUSB/SETUP
100         print "Connected to MAX342x Rev. %x" % (self.rreg(rREVISION));
101         self.wreg(rPINCTL,0x18); #Set duplex and negative INT level.
102         
103     def MAXUSBtrans8(self,byte):
104         """Read and write 8 bits by MAXUSB."""
105         data=self.MAXUSBtrans([byte]);
106         return ord(data[0]);
107     
108     def MAXUSBtrans(self,data):
109         """Exchange data by MAXUSB."""
110         self.data=data;
111         self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
112         return self.data;
113
114     def rreg(self,reg):
115         """Peek 8 bits from a register."""
116         data=[reg<<3,0];
117         self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
118         return ord(self.data[1]);
119     def rregAS(self,reg):
120         """Peek 8 bits from a register, setting AS."""
121         data=[(reg<<3)|1,0];
122         self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
123         return ord(self.data[1]);
124     def wreg(self,reg,value):
125         """Poke 8 bits into a register."""
126         data=[(reg<<3)|2,value];
127         self.writecmd(self.MAXUSBAPP,0x00,len(data),data);        
128         return value;
129     def wregAS(self,reg,value):
130         """Poke 8 bits into a register, setting AS."""
131         data=[(reg<<3)|3,value];
132         self.writecmd(self.MAXUSBAPP,0x00,len(data),data);        
133         return value;
134     def readbytes(self,reg,length):
135         """Peek some bytes from a register."""
136         data=[(reg<<3)]+range(0,length);
137         self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
138         toret=self.data[1:len(self.data)];
139         ashex="";
140         for foo in toret:
141             ashex=ashex+(" %02x"%ord(foo));
142         print "GET %02x==%s" % (reg,ashex);
143         return toret;
144     def writebytes(self,reg,tosend):
145         """Poke some bytes into a register."""
146         data="";
147         if type(tosend)==str:
148             data=chr((reg<<3)|2)+tosend;
149         else:
150             data=[(reg<<3)|2]+tosend;
151             ashex="";
152             for foo in tosend:
153                 ashex=ashex+(" %02x"%foo);
154             print "PUT %02x:=%s" % (reg,ashex)
155         self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
156     def usb_connect(self):
157         """Connect the USB port."""
158         
159         #disconnect D+ pullup if host turns off VBUS
160         self.wreg(rUSBCTL,0x48);
161     def STALL_EP0(self):
162         """Stall for an unknown event."""
163         print "Stalling.";
164         self.wreg(rEPSTALLS,0x23); #All three stall bits.
165     def SETBIT(self,reg,val):
166         """Set a bit in a register."""
167         self.wreg(reg,self.rreg(reg)|val);
168 class GoodFETMAXUSBHID(GoodFETMAXUSB):
169     """This is an example HID keyboard driver, loosely based on the
170     MAX3420 examples."""
171     def hidinit(self):
172         """Initialize a USB HID device."""
173         self.usb_connect();
174         self.hidrun();
175         
176     def hidrun(self):
177         """Main loop of the USB HID emulator."""
178         print "Starting a HID device.  This won't return.";
179         while 1:
180             self.service_irqs();
181     def do_SETUP(self):
182         """Handle USB Enumeration"""
183         
184         #Grab the SETUP packet from the buffer.
185         SUD=self.readbytes(rSUDFIFO,8);
186         
187         #Parse the SETUP packet
188         print "Handling a setup packet type 0x%02x" % ord(SUD[bmRequestType]);
189         setuptype=(ord(SUD[bmRequestType])&0x60);
190         if setuptype==0x00:
191             self.std_request(SUD);
192         elif setuptype==0x20:
193             self.class_request(SUD);
194         elif setuptype==0x40:
195             self.vendor_request(SUD);
196         else:
197             print "Unknown request type 0x%02x." % ord(SUD[bmRequestType])
198             self.STALL_EP0();
199     def class_request(self,SUD):
200         """Handle a class request."""
201         print "Stalling a class request.";
202         self.STALL_EP0();
203     def vendor_request(self,SUD):
204         print "Stalling a vendor request.";
205         self.STALL_EP0();
206     def std_request(self,SUD):
207         """Handles a standard setup request."""
208         setuptype=ord(SUD[bRequest]);
209         if setuptype==SR_GET_DESCRIPTOR: self.send_descriptor(SUD);
210         elif setuptype==SR_SET_FEATURE: self.feature(1);
211         elif setuptype==SR_SET_CONFIGURATION: self.set_configuration(SUD);
212         elif setuptype==SR_GET_STATUS: self.get_status(SUD);
213         elif setuptype==SR_SET_ADDRESS: self.rregAS(rFNADDR);
214         elif setuptype==SR_GET_INTERFACE: self.get_interface(SUD);
215         else:
216             print "Stalling Unknown standard setup request type %02x" % setuptype;
217             
218             self.STALL_EP0();
219     
220     def get_interface(self,SUD):
221         """Handles a setup request for SR_GET_INTERFACE."""
222         if ord(SUD[wIndexL]==0):
223             self.wreg(rEP0FIFO,0);
224             self.wregAS(rEP0BC,1);
225         else:
226             self.STALL_EP0();
227     
228     #Device Descriptor
229     DD=[0x12,                   # bLength = 18d
230         0x01,                   # bDescriptorType = Device (1)
231         0x00,0x01,              # bcdUSB(L/H) USB spec rev (BCD)
232         0x00,0x00,0x00,         # bDeviceClass, bDeviceSubClass, bDeviceProtocol
233         0x40,                   # bMaxPacketSize0 EP0 is 64 bytes
234         0x6A,0x0B,              # idVendor(L/H)--Maxim is 0B6A
235         0x46,0x53,              # idProduct(L/H)--5346
236         0x34,0x12,              # bcdDevice--1234
237         1,2,3,                  # iManufacturer, iProduct, iSerialNumber
238         1];
239     #Configuration Descriptor
240     CD=[0x09,                   # bLength
241         0x02,                   # bDescriptorType = Config
242         0x22,0x00,              # wTotalLength(L/H) = 34 bytes
243         0x01,                   # bNumInterfaces
244         0x01,                   # bConfigValue
245         0x00,                   # iConfiguration
246         0xE0,                   # bmAttributes. b7=1 b6=self-powered b5=RWU supported
247         0x01,                   # MaxPower is 2 ma
248 # INTERFACE Descriptor
249         0x09,                   # length = 9
250         0x04,                   # type = IF
251         0x00,                   # IF #0
252         0x00,                   # bAlternate Setting
253         0x01,                   # bNum Endpoints
254         0x03,                   # bInterfaceClass = HID
255         0x00,0x00,              # bInterfaceSubClass, bInterfaceProtocol
256         0x00,                   # iInterface
257 # HID Descriptor--It's at CD[18]
258         0x09,                   # bLength
259         0x21,                   # bDescriptorType = HID
260         0x10,0x01,              # bcdHID(L/H) Rev 1.1
261         0x00,                   # bCountryCode (none)
262         0x01,                   # bNumDescriptors (one report descriptor)
263         0x22,                   # bDescriptorType       (report)
264         43,0,                   # CD[25]: wDescriptorLength(L/H) (report descriptor size is 43 bytes)
265 # Endpoint Descriptor
266         0x07,                   # bLength
267         0x05,                   # bDescriptorType (Endpoint)
268         0x83,                   # bEndpointAddress (EP3-IN)             
269         0x03,                   # bmAttributes  (interrupt)
270         64,0,                   # wMaxPacketSize (64)
271         10];
272     strDesc=[
273 # STRING descriptor 0--Language string
274 "\x04\x03\x09\x04",
275 # [
276 #         0x04,                 # bLength
277 #       0x03,                   # bDescriptorType = string
278 #       0x09,0x04               # wLANGID(L/H) = English-United Sates
279 # ],
280 # STRING descriptor 1--Manufacturer ID
281 "\x0c\x03M\x00a\x00x\x00i\x00m\x00",
282 # [
283 #         12,                   # bLength
284 #       0x03,                   # bDescriptorType = string
285 #       'M',0,'a',0,'x',0,'i',0,'m',0 # text in Unicode
286 # ], 
287 # STRING descriptor 2 - Product ID
288 "\x18\x03M\x00A\x00X\x003\x004\x002\x000\x00E\x00 \x00E\x00n\x00u\x00m\x00 \x00C\x00o\x00d\x00e\x00",
289 # [     24,                     # bLength
290 #       0x03,                   # bDescriptorType = string
291 #       'M',0,'A',0,'X',0,'3',0,'4',0,'2',0,'0',0,'E',0,' ',0,
292 #         'E',0,'n',0,'u',0,'m',0,' ',0,'C',0,'o',0,'d',0,'e',0
293 # ],
294
295
296 # STRING descriptor 3 - Serial Number ID
297 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
298 # [       20,                   # bLength
299 #       0x03,                   # bDescriptorType = string
300 #       'S',0,                          
301 #       '/',0,
302 #       'N',0,
303 #       ' ',0,
304 #       '3',0,
305 #       '4',0,
306 #       '2',0,
307 #       '0',0,
308 #         'E',0,
309 # ]
310 ];
311     RepD=[
312         0x05,0x01,              # Usage Page (generic desktop)
313         0x09,0x06,              # Usage (keyboard)
314         0xA1,0x01,              # Collection
315         0x05,0x07,              #   Usage Page 7 (keyboard/keypad)
316         0x19,0xE0,              #   Usage Minimum = 224
317         0x29,0xE7,              #   Usage Maximum = 231
318         0x15,0x00,              #   Logical Minimum = 0
319         0x25,0x01,              #   Logical Maximum = 1
320         0x75,0x01,              #   Report Size = 1
321         0x95,0x08,              #   Report Count = 8
322         0x81,0x02,              #  Input(Data,Variable,Absolute)
323         0x95,0x01,              #   Report Count = 1
324         0x75,0x08,              #   Report Size = 8
325         0x81,0x01,              #  Input(Constant)
326         0x19,0x00,              #   Usage Minimum = 0
327         0x29,0x65,              #   Usage Maximum = 101
328         0x15,0x00,              #   Logical Minimum = 0,
329         0x25,0x65,              #   Logical Maximum = 101
330         0x75,0x08,              #   Report Size = 8
331         0x95,0x01,              #   Report Count = 1
332         0x81,0x00,              #  Input(Data,Variable,Array)
333         0xC0]
334     def send_descriptor(self,SUD):
335         """Send the USB descriptors based upon the setup data."""
336         desclen=0;
337         reqlen=ord(SUD[wLengthL])+256*ord(SUD[wLengthH]); #16-bit length
338         desctype=ord(SUD[wValueH]);
339         
340         if desctype==GD_DEVICE:
341             desclen=self.DD[0];
342             ddata=self.DD;
343         elif desctype==GD_CONFIGURATION:
344             desclen=self.CD[2];
345             ddata=self.CD;
346         elif desctype==GD_STRING:
347             desclen=self.strDesc[ord(SUD[wValueL])][0];
348             ddata=self.strDesc[ord(SUD[wValueL])];
349         elif desctype==GD_REPORT:
350             desclen=self.CD[25];
351             ddata=self.RepD;
352         
353         #TODO Configuration, String, Hid, and Report
354         
355         if desclen>0:
356             sendlen=min(reqlen,desclen);
357             self.writebytes(rEP0FIFO,ddata);
358             self.wregAS(rEP0BC,sendlen);
359         else:
360             print "Stalling in send_descriptor() for lack of handler for %02x." % desctype;
361             self.STALL_EP0();
362     def set_configuration(self,SUD):
363         """Set the configuration."""
364         bmSUSPIE=0x10;
365         configval=ord(SUD[wValueL]);
366         if(configval>0):
367             self.SETBIT(rUSBIEN,bmSUSPIE);
368         self.rregAS(rFNADDR);
369     def get_status(self,SUD):
370         """Get the USB Setup Status."""
371         testbyte=ord(SUD[bmRequestType])
372         
373         #Toward Device
374         if testbyte==0x80:
375             self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
376             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
377             self.wregAS(rEP0BC,2);    #Load byte count, arm transfer, and ack CTL.
378         #Toward Interface
379         elif testbyte==0x81:
380             self.wreg(rEP0FIFO,0x00);
381             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
382             self.wregAS(rEP0BC,2);
383         #Toward Endpoint
384         elif testbyte==0x82:
385             if(ord(SUD[wIndexL])==0x83):
386                 self.wreg(rEP0FIFO,0x01); #Stall EP3
387                 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
388                 self.wregAS(rEP0BC,2);
389             else:
390                 self.STALL_EP0();
391         else:
392             self.STALL_EP0();
393     def service_irqs(self):
394         """Handle USB interrupt events."""
395         
396         epirq=self.rreg(rEPIRQ);
397         usbirq=self.rreg(rUSBIRQ);
398         
399         #Are we being asked for setup data?
400         if(epirq&bmSUDAVIRQ): #Setup Data Requested
401             self.wreg(rEPIRQ,bmSUDAVIRQ); #Clear the bit
402             self.do_SETUP();
403         if(epirq&bmIN3BAVIRQ): #EN3-IN packet
404             self.do_IN3();
405         
406     
407     typephase=0;
408     typestring="                      Python does USB HID!";
409     typepos=0;
410     
411     def asc2hid(self,ascii):
412         """Translate ASCII to an USB keycode."""
413         a=ascii;
414         if a>='a' and a<='z':
415             return ord(a)-ord('a')+4;
416         elif a>='A' and a<='Z':
417             return ord(a)-ord('A')+4;
418         elif a==' ':
419             return 0x2C; #space
420         else:
421             return 0; #key-up
422     def type_IN3(self):
423         """Type next letter in buffer."""
424         if self.typepos>=len(self.typestring):
425             self.typeletter(0);
426         elif self.typephase==0:
427             self.typephase=1;
428             self.typeletter(0);
429         else:
430             typephase=0;
431             self.typeletter(self.typestring[self.typepos]);
432             self.typepos=self.typepos+1;
433         return;
434     def typeletter(self,key):
435         """Type a letter on IN3.  Zero for keyup."""
436         #if type(key)==str: key=ord(key);
437         #Send a key-up.
438         self.wreg(rEP3INFIFO,0);
439         self.wreg(rEP3INFIFO,0);
440         self.wreg(rEP3INFIFO,self.asc2hid(key));
441         self.wreg(rEP3INBC,3);
442     def do_IN3(self):
443         """Handle IN3 event."""
444         #Don't bother clearing interrupt flag, that's done by sending the reply.
445         self.type_IN3();
446