2 # GoodFET Client Library for Maxim USB Chips.
4 # (C) 2012 Travis Goodspeed <travis at radiantmachines.com>
6 # This code is being rewritten and refactored. You've been warned!
9 import sys, time, string, cStringIO, struct, glob, os;
11 from GoodFET import GoodFET;
35 rIOPINS1=20 #Same as rIOPINS
53 # R11 EPIRQ register bits
61 # R12 EPIEN register bits
72 # ************************
73 # Standard USB Requests
74 SR_GET_STATUS =0x00 # Get Status
75 SR_CLEAR_FEATURE =0x01 # Clear Feature
76 SR_RESERVED =0x02 # Reserved
77 SR_SET_FEATURE =0x03 # Set Feature
78 SR_SET_ADDRESS =0x05 # Set Address
79 SR_GET_DESCRIPTOR =0x06 # Get Descriptor
80 SR_SET_DESCRIPTOR =0x07 # Set Descriptor
81 SR_GET_CONFIGURATION =0x08 # Get Configuration
82 SR_SET_CONFIGURATION =0x09 # Set Configuration
83 SR_GET_INTERFACE =0x0a # Get Interface
84 SR_SET_INTERFACE =0x0b # Set Interface
86 # Get Descriptor codes
87 GD_DEVICE =0x01 # Get device descriptor: Device
88 GD_CONFIGURATION =0x02 # Get device descriptor: Configuration
89 GD_STRING =0x03 # Get device descriptor: String
90 GD_HID =0x21 # Get descriptor: HID
91 GD_REPORT =0x22 # Get descriptor: Report
93 # SETUP packet offsets
103 # HID bRequest values
161 # Host XFR token values for writing the HXFR register (R30).
162 # OR this bit field with the endpoint number in bits 3:0
163 tokSETUP =0x10 # HS=0, ISO=0, OUTNIN=0, SETUP=1
164 tokIN =0x00 # HS=0, ISO=0, OUTNIN=0, SETUP=0
165 tokOUT =0x20 # HS=0, ISO=0, OUTNIN=1, SETUP=0
166 tokINHS =0x80 # HS=1, ISO=0, OUTNIN=0, SETUP=0
167 tokOUTHS =0xA0 # HS=1, ISO=0, OUTNIN=1, SETUP=0
168 tokISOIN =0x40 # HS=0, ISO=1, OUTNIN=0, SETUP=0
169 tokISOOUT =0x60 # HS=0, ISO=1, OUTNIN=1, SETUP=0
176 # Host error result codes, the 4 LSB's in the HRSL register.
195 bmBUSEVENTIRQ =0x01 # indicates BUS Reset Done or BUS Resume
204 class GoodFETMAXUSB(GoodFET):
206 def MAXUSBsetup(self):
207 """Move the FET into the MAXUSB application."""
208 self.writecmd(self.MAXUSBAPP,0x10,0,self.data); #MAXUSB/SETUP
209 print "Connected to MAX342x Rev. %x" % (self.rreg(rREVISION));
210 self.wreg(rPINCTL,0x18); #Set duplex and negative INT level.
212 def MAXUSBtrans8(self,byte):
213 """Read and write 8 bits by MAXUSB."""
214 data=self.MAXUSBtrans([byte]);
217 def MAXUSBtrans(self,data):
218 """Exchange data by MAXUSB."""
220 self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
224 """Peek 8 bits from a register."""
226 self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
227 return ord(self.data[1]);
228 def rregAS(self,reg):
229 """Peek 8 bits from a register, setting AS."""
231 self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
232 return ord(self.data[1]);
233 def wreg(self,reg,value):
234 """Poke 8 bits into a register."""
235 data=[(reg<<3)|2,value];
236 self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
238 def wregAS(self,reg,value):
239 """Poke 8 bits into a register, setting AS."""
240 data=[(reg<<3)|3,value];
241 self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
243 def readbytes(self,reg,length):
244 """Peek some bytes from a register."""
245 data=[(reg<<3)]+range(0,length);
246 self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
247 toret=self.data[1:len(self.data)];
250 ashex=ashex+(" %02x"%ord(foo));
251 print "GET %02x==%s" % (reg,ashex);
253 def ctl_write_nd(self,request):
254 """Control Write with no data stage. Assumes PERADDR is set
255 and the SUDFIFO contains the 8 setup bytes. Returns with
256 result code = HRSLT[3:0] (HRSL register). If there is an
257 error, the 4MSBits of the returned value indicate the stage 1
260 # 1. Send the SETUP token and 8 setup bytes.
261 # Should ACK immediately.
262 self.writebytes(rSUDFIFO,request);
263 resultcode=self.send_packet(tokSETUP,0); #SETUP packet to EP0.
264 if resultcode: return resultcode;
266 # 2. No data stage, so the last operation is to send an IN
267 # token to the peripheral as the STATUS (handhsake) stage of
268 # this control transfer. We should get NAK or the DATA1 PID.
269 # When we get back to the DATA1 PID the 3421 automatically
270 # sends the closing NAK.
271 resultcode=self.send_packet(tokINHS,0); #Function takes care of retries.
272 if resultcode: return resultcode;
277 def ctl_read(self,request):
278 """Control read transfer, used in Host mode."""
280 bytes_to_read=request[6]+256*request[7];
283 self.writebytes(rSUDFIFO,request); #Load the FIFO
284 resultcode=self.send_packet(tokSETUP,0); #SETUP packet to EP0
286 print "Failed to get ACK on SETUP request in ctl_read()."
289 self.wreg(rHCTL,bmRCVTOG1); #FIRST data packet in CTL transfer uses DATA1 toggle.
290 resultcode=self.IN_Transfer(0,bytes_to_read);
292 print "Failed on IN Transfer in ctl_read()";
295 self.IN_nak_count=self.nak_count;
297 #The OUT status stage.
298 resultcode=self.send_packet(tokOUTHS,0);
300 print "Failed on OUT Status stage in ctl_read()";
305 xfrdata=[]; #Ugly variable used only by a few functions. FIXME
306 def IN_Transfer(self,endpoint,INbytes):
307 """Does an IN transfer to an endpoint, used for Host mode."""
313 resultcode=self.send_packet(tokIN,endpoint); #IN packet to EP. NAKS taken care of.
314 if resultcode: return resultcode;
316 pktsize=self.rreg(rRCVBC); #Numer of RXed bytes.
318 #Very innefficient, move this to C if performance is needed.
319 for j in range(0,pktsize):
320 self.xfrdata=self.xfrdata+[self.rreg(rRCVFIFO)];
321 self.wreg(rHIRQ,bmRCVDAVIRQ); #Clear IRQ
322 xfrlen=xfrlen+pktsize; #Add byte count to total transfer length.
325 #Packet is complete if:
326 # 1. The device sent a short packet, <maxPacketSize
327 # 2. INbytes have been transfered.
328 if (pktsize<self.maxPacketSize) or (xfrlen>=xfrsize):
329 self.last_transfer_size=xfrlen;
331 for foo in self.xfrdata:
332 ashex=ashex+(" %02x"%foo);
333 print "INPACKET EP%i==%s" % (endpoint,ashex);
338 def send_packet(self,token,endpoint):
339 """Send a packet to an endpoint as the Host, taking care of NAKs.
340 Don't use this for device code."""
344 #Repeat until NAK_LIMIT or RETRY_LIMIT is reached.
345 while self.nak_count<self.NAK_LIMIT and self.retry_count<self.RETRY_LIMIT:
346 self.wreg(rHXFR,(token|endpoint)); #launch the transfer
347 while not (self.rreg(rHIRQ) & bmHXFRDNIRQ):
348 # wait for the completion IRQ
350 self.wreg(rHIRQ,bmHXFRDNIRQ); #Clear IRQ
351 resultcode = (self.rreg(rHRSL) & 0x0F); # get the result
352 if (resultcode==hrNAK):
353 self.nak_count=self.nak_count+1;
354 elif (resultcode==hrTIMEOUT):
355 self.retry_count=self.retry_count+1;
361 def writebytes(self,reg,tosend):
362 """Poke some bytes into a register."""
364 if type(tosend)==str:
365 data=chr((reg<<3)|2)+tosend;
367 data=[(reg<<3)|2]+tosend;
370 ashex=ashex+(" %02x"%foo);
371 print "PUT %02x:=%s" % (reg,ashex)
372 self.writecmd(self.MAXUSBAPP,0x00,len(data),data);
373 def usb_connect(self):
374 """Connect the USB port."""
376 #disconnect D+ pullup if host turns off VBUS
377 self.wreg(rUSBCTL,0x48);
379 """Stall for an unknown event."""
381 self.wreg(rEPSTALLS,0x23); #All three stall bits.
382 def SETBIT(self,reg,val):
383 """Set a bit in a register."""
384 self.wreg(reg,self.rreg(reg)|val);
386 """Turn on the target device."""
387 self.wreg(rIOPINS2,(self.rreg(rIOPINS2)|0x08));
389 """Turn off the target device's power."""
390 self.wreg(rIOPINS2,0x00);
391 def reset_host(self):
392 """Resets the chip into host mode."""
393 self.wreg(rUSBCTL,bmCHIPRES); #Stop the oscillator.
394 self.wreg(rUSBCTL,0x00); #restart it.
395 while self.rreg(rUSBIRQ)&bmOSCOKIRQ:
396 #Hang until the PLL stabilizes.
399 class GoodFETMAXUSBHost(GoodFETMAXUSB):
400 """This is a class for implemented a minimal USB host.
401 It's intended for fuzzing, rather than for daily use."""
403 """Initialize the MAX3421 as a USB Host."""
405 self.wreg(rPINCTL,(bmFDUPSPI|bmPOSINT));
413 """Run as a minimal host and dump the config tables."""
415 self.detect_device();
417 self.enumerate_device();
418 self.wait_for_disconnect();
419 def detect_device(self):
420 """Waits for a device to be inserted and then returns."""
423 #Activate host mode and turn on 15K pulldown resistors on D+ and D-.
424 self.wreg(rMODE,(bmDPPULLDN|bmDMPULLDN|bmHOST));
425 #Clear connection detect IRQ.
426 self.wreg(rHIRQ,bmCONDETIRQ);
428 print "Waiting for a device connection.";
430 self.wreg(rHCTL,bmSAMPLEBUS); #Update JSTATUS and KSTATUS bits.
431 busstate=self.rreg(rHRSL) & (bmJSTATUS|bmKSTATUS);
433 if busstate==bmJSTATUS:
434 print "Detected Full-Speed Device.";
435 self.wreg(rMODE,(bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB));
436 elif busstate==bmKSTATUS:
437 print "Detected Low-Speed Device.";
438 self.wreg(rMODE,(bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB));
440 print "Not sure whether this is Full-Speed or Low-Speed. Please investigate.";
441 def wait_for_disconnect(self):
442 """Wait for a device to be disconnected."""
443 print "Waiting for a device disconnect.";
445 self.wreg(rHIRQ,bmCONDETIRQ); #Clear disconnect IRQ
446 while not (self.rreg(rHIRQ) & bmCONDETIRQ):
447 #Wait for IRQ to change.
451 self.wreg(rMODE,bmDPPULLDN|bmDMPULLDN|bmHOST);
452 print "Device disconnected.";
453 self.wreg(rIOPINS2,(self.rreg(rIOPINS2) & ~0x04)); #HL1_OFF
454 self.wreg(rIOPINS1,(self.rreg(rIOPINS1) & ~0x02)); #HL4_OFF
456 def enumerate_device(self):
457 """Enumerates a device on the present port."""
459 Set_Address_to_7 = [0x00,0x05,0x07,0x00,0x00,0x00,0x00,0x00];
460 Get_Descriptor_Device = [0x80,0x06,0x00,0x01,0x00,0x00,0x00,0x00]; #len filled in
461 Get_Descriptor_Config = [0x80,0x06,0x00,0x02,0x00,0x00,0x00,0x00];
464 print "Issuing USB bus reset.";
465 self.wreg(rHCTL,bmBUSRST);
466 while self.rreg(rHCTL) & bmBUSRST:
467 #Wait for reset to complete.
472 #Get the device descriptor.
473 self.wreg(rPERADDR,0); #First request to address 0.
474 self.maxPacketSize=8; #Only safe value for first check.
475 Get_Descriptor_Device[6]=8; # wLengthL
476 Get_Descriptor_Device[7]=0; # wLengthH
478 print "Fetching 8 bytes of Device Descriptor.";
479 self.ctl_read(Get_Descriptor_Device); # Get device descriptor into self.xfrdata;
480 self.maxPacketSize=self.xfrdata[7];
481 print "EP0 maxPacketSize is %02i bytes." % self.maxPacketSize;
483 # Issue another USB bus reset
484 print "Resetting the bus again."
485 self.wreg(rHCTL,bmBUSRST);
486 while self.rreg(rHCTL) & bmBUSRST:
487 #Wait for reset to complete.
491 # Set_Address to 7 (Note: this request goes to address 0, already set in PERADDR register).
492 print "Setting address to 0x07";
493 HR = self.ctl_write_nd(Set_Address_to_7); # CTL-Write, no data stage
494 #if(print_error(HR)) return;
496 time.sleep(0.002); # Device gets 2 msec recovery time
497 self.wreg(rPERADDR,7); # now all transfers go to addr 7
500 #Get the device descriptor at the assigned address.
501 Get_Descriptor_Device[6]=0x12; #Fill in real descriptor length.
502 print "Fetching Device Descriptor."
503 self.ctl_read(Get_Descriptor_Device); #Result in self.xfrdata;
505 self.descriptor=self.xfrdata;
506 self.VID = self.xfrdata[8] + 256*self.xfrdata[9];
507 self.PID = self.xfrdata[10]+ 256*self.xfrdata[11];
508 iMFG = self.xfrdata[14];
509 iPROD = self.xfrdata[15];
510 iSERIAL = self.xfrdata[16];
512 self.manufacturer=self.getDescriptorString(iMFG);
513 self.product=self.getDescriptorString(iPROD);
514 self.serial=self.getDescriptorString(iSERIAL);
518 def printstrings(self):
519 print "Vendor ID is %04x." % self.VID;
520 print "Product ID is %04x." % self.PID;
521 print "Manufacturer: %s" % self.manufacturer;
522 print "Product: %s" % self.product;
523 print "Serial: %s" % self.serial;
525 def getDescriptorString(self, index):
526 """Grabs a string from the descriptor string table."""
527 # Get_Descriptor-String template. Code fills in idx at str[2].
528 Get_Descriptor_String = [0x80,0x06,index,0x03,0x00,0x00,0x40,0x00];
530 if index==0: return "MISSING STRING";
532 status=self.ctl_read(Get_Descriptor_String);
533 if status: return None;
535 #Since we've got a string
537 for c in self.xfrdata[2:len(self.xfrdata)]:
538 if c>0: toret=toret+chr(c);
541 class GoodFETMAXUSBHID(GoodFETMAXUSB):
542 """This is an example HID keyboard driver, loosely based on the
545 """Initialize a USB HID device."""
550 """Main loop of the USB HID emulator."""
551 print "Starting a HID device. This won't return.";
555 """Handle USB Enumeration"""
557 #Grab the SETUP packet from the buffer.
558 SUD=self.readbytes(rSUDFIFO,8);
560 #Parse the SETUP packet
561 print "Handling a setup packet type 0x%02x" % ord(SUD[bmRequestType]);
562 setuptype=(ord(SUD[bmRequestType])&0x60);
564 self.std_request(SUD);
565 elif setuptype==0x20:
566 self.class_request(SUD);
567 elif setuptype==0x40:
568 self.vendor_request(SUD);
570 print "Unknown request type 0x%02x." % ord(SUD[bmRequestType])
572 def class_request(self,SUD):
573 """Handle a class request."""
574 print "Stalling a class request.";
576 def vendor_request(self,SUD):
577 print "Stalling a vendor request.";
579 def std_request(self,SUD):
580 """Handles a standard setup request."""
581 setuptype=ord(SUD[bRequest]);
582 if setuptype==SR_GET_DESCRIPTOR: self.send_descriptor(SUD);
583 elif setuptype==SR_SET_FEATURE: self.feature(1);
584 elif setuptype==SR_SET_CONFIGURATION: self.set_configuration(SUD);
585 elif setuptype==SR_GET_STATUS: self.get_status(SUD);
586 elif setuptype==SR_SET_ADDRESS: self.rregAS(rFNADDR);
587 elif setuptype==SR_GET_INTERFACE: self.get_interface(SUD);
589 print "Stalling Unknown standard setup request type %02x" % setuptype;
593 def get_interface(self,SUD):
594 """Handles a setup request for SR_GET_INTERFACE."""
595 if ord(SUD[wIndexL]==0):
596 self.wreg(rEP0FIFO,0);
597 self.wregAS(rEP0BC,1);
602 DD=[0x12, # bLength = 18d
603 0x01, # bDescriptorType = Device (1)
604 0x00,0x01, # bcdUSB(L/H) USB spec rev (BCD)
605 0x00,0x00,0x00, # bDeviceClass, bDeviceSubClass, bDeviceProtocol
606 0x40, # bMaxPacketSize0 EP0 is 64 bytes
607 0x6A,0x0B, # idVendor(L/H)--Maxim is 0B6A
608 0x46,0x53, # idProduct(L/H)--5346
609 0x34,0x12, # bcdDevice--1234
610 1,2,3, # iManufacturer, iProduct, iSerialNumber
612 #Configuration Descriptor
614 0x02, # bDescriptorType = Config
615 0x22,0x00, # wTotalLength(L/H) = 34 bytes
616 0x01, # bNumInterfaces
618 0x00, # iConfiguration
619 0xE0, # bmAttributes. b7=1 b6=self-powered b5=RWU supported
620 0x01, # MaxPower is 2 ma
621 # INTERFACE Descriptor
625 0x00, # bAlternate Setting
626 0x01, # bNum Endpoints
627 0x03, # bInterfaceClass = HID
628 0x00,0x00, # bInterfaceSubClass, bInterfaceProtocol
630 # HID Descriptor--It's at CD[18]
632 0x21, # bDescriptorType = HID
633 0x10,0x01, # bcdHID(L/H) Rev 1.1
634 0x00, # bCountryCode (none)
635 0x01, # bNumDescriptors (one report descriptor)
636 0x22, # bDescriptorType (report)
637 43,0, # CD[25]: wDescriptorLength(L/H) (report descriptor size is 43 bytes)
638 # Endpoint Descriptor
640 0x05, # bDescriptorType (Endpoint)
641 0x83, # bEndpointAddress (EP3-IN)
642 0x03, # bmAttributes (interrupt)
643 64,0, # wMaxPacketSize (64)
646 # STRING descriptor 0--Language string
650 # 0x03, # bDescriptorType = string
651 # 0x09,0x04 # wLANGID(L/H) = English-United Sates
653 # STRING descriptor 1--Manufacturer ID
654 "\x0c\x03M\x00a\x00x\x00i\x00m\x00",
657 # 0x03, # bDescriptorType = string
658 # 'M',0,'a',0,'x',0,'i',0,'m',0 # text in Unicode
660 # STRING descriptor 2 - Product ID
661 "\x18\x03M\x00A\x00X\x003\x004\x002\x000\x00E\x00 \x00E\x00n\x00u\x00m\x00 \x00C\x00o\x00d\x00e\x00",
663 # 0x03, # bDescriptorType = string
664 # 'M',0,'A',0,'X',0,'3',0,'4',0,'2',0,'0',0,'E',0,' ',0,
665 # 'E',0,'n',0,'u',0,'m',0,' ',0,'C',0,'o',0,'d',0,'e',0
669 # STRING descriptor 3 - Serial Number ID
670 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
672 # 0x03, # bDescriptorType = string
685 0x05,0x01, # Usage Page (generic desktop)
686 0x09,0x06, # Usage (keyboard)
687 0xA1,0x01, # Collection
688 0x05,0x07, # Usage Page 7 (keyboard/keypad)
689 0x19,0xE0, # Usage Minimum = 224
690 0x29,0xE7, # Usage Maximum = 231
691 0x15,0x00, # Logical Minimum = 0
692 0x25,0x01, # Logical Maximum = 1
693 0x75,0x01, # Report Size = 1
694 0x95,0x08, # Report Count = 8
695 0x81,0x02, # Input(Data,Variable,Absolute)
696 0x95,0x01, # Report Count = 1
697 0x75,0x08, # Report Size = 8
698 0x81,0x01, # Input(Constant)
699 0x19,0x00, # Usage Minimum = 0
700 0x29,0x65, # Usage Maximum = 101
701 0x15,0x00, # Logical Minimum = 0,
702 0x25,0x65, # Logical Maximum = 101
703 0x75,0x08, # Report Size = 8
704 0x95,0x01, # Report Count = 1
705 0x81,0x00, # Input(Data,Variable,Array)
707 def send_descriptor(self,SUD):
708 """Send the USB descriptors based upon the setup data."""
710 reqlen=ord(SUD[wLengthL])+256*ord(SUD[wLengthH]); #16-bit length
711 desctype=ord(SUD[wValueH]);
713 if desctype==GD_DEVICE:
716 elif desctype==GD_CONFIGURATION:
719 elif desctype==GD_STRING:
720 desclen=self.strDesc[ord(SUD[wValueL])][0];
721 ddata=self.strDesc[ord(SUD[wValueL])];
722 elif desctype==GD_REPORT:
726 #TODO Configuration, String, Hid, and Report
729 sendlen=min(reqlen,desclen);
730 self.writebytes(rEP0FIFO,ddata);
731 self.wregAS(rEP0BC,sendlen);
733 print "Stalling in send_descriptor() for lack of handler for %02x." % desctype;
735 def set_configuration(self,SUD):
736 """Set the configuration."""
738 configval=ord(SUD[wValueL]);
740 self.SETBIT(rUSBIEN,bmSUSPIE);
741 self.rregAS(rFNADDR);
742 def get_status(self,SUD):
743 """Get the USB Setup Status."""
744 testbyte=ord(SUD[bmRequestType])
748 self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
749 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
750 self.wregAS(rEP0BC,2); #Load byte count, arm transfer, and ack CTL.
753 self.wreg(rEP0FIFO,0x00);
754 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
755 self.wregAS(rEP0BC,2);
758 if(ord(SUD[wIndexL])==0x83):
759 self.wreg(rEP0FIFO,0x01); #Stall EP3
760 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
761 self.wregAS(rEP0BC,2);
766 def service_irqs(self):
767 """Handle USB interrupt events."""
769 epirq=self.rreg(rEPIRQ);
770 usbirq=self.rreg(rUSBIRQ);
772 #Are we being asked for setup data?
773 if(epirq&bmSUDAVIRQ): #Setup Data Requested
774 self.wreg(rEPIRQ,bmSUDAVIRQ); #Clear the bit
776 if(epirq&bmIN3BAVIRQ): #EN3-IN packet
781 typestring=" Python does USB HID!";
784 def asc2hid(self,ascii):
785 """Translate ASCII to an USB keycode."""
787 if a>='a' and a<='z':
788 return ord(a)-ord('a')+4;
789 elif a>='A' and a<='Z':
790 return ord(a)-ord('A')+4;
796 """Type next letter in buffer."""
797 if self.typepos>=len(self.typestring):
799 elif self.typephase==0:
804 self.typeletter(self.typestring[self.typepos]);
805 self.typepos=self.typepos+1;
807 def typeletter(self,key):
808 """Type a letter on IN3. Zero for keyup."""
809 #if type(key)==str: key=ord(key);
811 self.wreg(rEP3INFIFO,0);
812 self.wreg(rEP3INFIFO,0);
813 self.wreg(rEP3INFIFO,self.asc2hid(key));
814 self.wreg(rEP3INBC,3);
816 """Handle IN3 event."""
817 #Don't bother clearing interrupt flag, that's done by sending the reply.