X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=client%2FGoodFETMAXUSB.py;h=6085e709cf45aae05f60141dc2669422085434dc;hp=96e8ad6d16bb1a6249b6ead58e4ecd7f44c646f0;hb=f68574d90bd2edf5147e8b0fb2fe1d1c1591115a;hpb=ebd308ba418fec3765e7b55ebcddd923111ba57b diff --git a/client/GoodFETMAXUSB.py b/client/GoodFETMAXUSB.py index 96e8ad6..6085e70 100644 --- a/client/GoodFETMAXUSB.py +++ b/client/GoodFETMAXUSB.py @@ -32,6 +32,23 @@ rPINCTL=17 rREVISION=18 rFNADDR=19 rIOPINS=20 +rIOPINS1=20 #Same as rIOPINS +rIOPINS2=21 +rHIRQ=25 +rHIEN=26 +rMODE=27 +rPERADDR=28 +rHCTL=29 +rHXFR=30 +rHRSL=31 + +#Host mode registers. +rRCVFIFO =1 +rSNDFIFO =2 +rRCVBC =6 +rSNDBC =7 +rHIRQ =25 + # R11 EPIRQ register bits bmSUDAVIRQ =0x20 @@ -50,6 +67,8 @@ bmOUT0DAVIE =0x02 bmIN0BAVIE =0x01 + + # ************************ # Standard USB Requests SR_GET_STATUS =0x00 # Get Status @@ -71,7 +90,7 @@ GD_STRING =0x03 # Get device descriptor: String GD_HID =0x21 # Get descriptor: HID GD_REPORT =0x22 # Get descriptor: Report -# SETUP packet offsets +# SETUP packet header offsets bmRequestType =0 bRequest =1 wValueL =2 @@ -90,11 +109,110 @@ SET_IDLE =0x0A SET_PROTOCOL =0x0B INPUT_REPORT =1 +# PINCTL bits +bmEP3INAK =0x80 +bmEP2INAK =0x40 +bmEP1INAK =0x20 +bmFDUPSPI =0x10 +bmINTLEVEL =0x08 +bmPOSINT =0x04 +bmGPXB =0x02 +bmGPXA =0x01 + +# rUSBCTL bits +bmHOSCSTEN =0x80 +bmVBGATE =0x40 +bmCHIPRES =0x20 +bmPWRDOWN =0x10 +bmCONNECT =0x08 +bmSIGRWU =0x04 + +# USBIRQ bits +bmURESDNIRQ =0x80 +bmVBUSIRQ =0x40 +bmNOVBUSIRQ =0x20 +bmSUSPIRQ =0x10 +bmURESIRQ =0x08 +bmBUSACTIRQ =0x04 +bmRWUDNIRQ =0x02 +bmOSCOKIRQ =0x01 + +# MODE bits +bmHOST =0x01 +bmLOWSPEED =0x02 +bmHUBPRE =0x04 +bmSOFKAENAB =0x08 +bmSEPIRQ =0x10 +bmDELAYISO =0x20 +bmDMPULLDN =0x40 +bmDPPULLDN =0x80 + +# PERADDR/HCTL bits +bmBUSRST =0x01 +bmFRMRST =0x02 +bmSAMPLEBUS =0x04 +bmSIGRSM =0x08 +bmRCVTOG0 =0x10 +bmRCVTOG1 =0x20 +bmSNDTOG0 =0x40 +bmSNDTOG1 =0x80 + +# rHXFR bits +# Host XFR token values for writing the HXFR register (R30). +# OR this bit field with the endpoint number in bits 3:0 +tokSETUP =0x10 # HS=0, ISO=0, OUTNIN=0, SETUP=1 +tokIN =0x00 # HS=0, ISO=0, OUTNIN=0, SETUP=0 +tokOUT =0x20 # HS=0, ISO=0, OUTNIN=1, SETUP=0 +tokINHS =0x80 # HS=1, ISO=0, OUTNIN=0, SETUP=0 +tokOUTHS =0xA0 # HS=1, ISO=0, OUTNIN=1, SETUP=0 +tokISOIN =0x40 # HS=0, ISO=1, OUTNIN=0, SETUP=0 +tokISOOUT =0x60 # HS=0, ISO=1, OUTNIN=1, SETUP=0 +# rRSL bits +bmRCVTOGRD =0x10 +bmSNDTOGRD =0x20 +bmKSTATUS =0x40 +bmJSTATUS =0x80 +# Host error result codes, the 4 LSB's in the HRSL register. +hrSUCCESS =0x00 +hrBUSY =0x01 +hrBADREQ =0x02 +hrUNDEF =0x03 +hrNAK =0x04 +hrSTALL =0x05 +hrTOGERR =0x06 +hrWRONGPID =0x07 +hrBADBC =0x08 +hrPIDERR =0x09 +hrPKTERR =0x0A +hrCRCERR =0x0B +hrKERR =0x0C +hrJERR =0x0D +hrTIMEOUT =0x0E +hrBABBLE =0x0F +# HIRQ bits +bmBUSEVENTIRQ =0x01 # indicates BUS Reset Done or BUS Resume +bmRWUIRQ =0x02 +bmRCVDAVIRQ =0x04 +bmSNDBAVIRQ =0x08 +bmSUSDNIRQ =0x10 +bmCONDETIRQ =0x20 +bmFRAMEIRQ =0x40 +bmHXFRDNIRQ =0x80 class GoodFETMAXUSB(GoodFET): MAXUSBAPP=0x40; + + def setup2str(self,SUD): + """Converts the header of a setup packet to a string.""" + return "bmRequestType=0x%02x, bRequest=0x%02x, wValue=0x%04x, wIndex=0x%04x, wLength=0x%04x" % ( + ord(SUD[0]), ord(SUD[1]), + ord(SUD[2])+(ord(SUD[3])<<8), + ord(SUD[4])+(ord(SUD[5])<<8), + ord(SUD[6])+(ord(SUD[7])<<8) + ); + def MAXUSBsetup(self): """Move the FET into the MAXUSB application.""" self.writecmd(self.MAXUSBAPP,0x10,0,self.data); #MAXUSB/SETUP @@ -142,6 +260,116 @@ class GoodFETMAXUSB(GoodFET): ashex=ashex+(" %02x"%ord(foo)); print "GET %02x==%s" % (reg,ashex); return toret; + def ctl_write_nd(self,request): + """Control Write with no data stage. Assumes PERADDR is set + and the SUDFIFO contains the 8 setup bytes. Returns with + result code = HRSLT[3:0] (HRSL register). If there is an + error, the 4MSBits of the returned value indicate the stage 1 + or 2.""" + + # 1. Send the SETUP token and 8 setup bytes. + # Should ACK immediately. + self.writebytes(rSUDFIFO,request); + resultcode=self.send_packet(tokSETUP,0); #SETUP packet to EP0. + if resultcode: return resultcode; + + # 2. No data stage, so the last operation is to send an IN + # token to the peripheral as the STATUS (handhsake) stage of + # this control transfer. We should get NAK or the DATA1 PID. + # When we get back to the DATA1 PID the 3421 automatically + # sends the closing NAK. + resultcode=self.send_packet(tokINHS,0); #Function takes care of retries. + if resultcode: return resultcode; + + return 0; + + + def ctl_read(self,request): + """Control read transfer, used in Host mode.""" + resultcode=0; + bytes_to_read=request[6]+256*request[7]; + + ##SETUP packet + self.writebytes(rSUDFIFO,request); #Load the FIFO + resultcode=self.send_packet(tokSETUP,0); #SETUP packet to EP0 + if resultcode: + print "Failed to get ACK on SETUP request in ctl_read()." + return resultcode; + + self.wreg(rHCTL,bmRCVTOG1); #FIRST data packet in CTL transfer uses DATA1 toggle. + resultcode=self.IN_Transfer(0,bytes_to_read); + if resultcode: + print "Failed on IN Transfer in ctl_read()"; + return resultcode; + + self.IN_nak_count=self.nak_count; + + #The OUT status stage. + resultcode=self.send_packet(tokOUTHS,0); + if resultcode: + print "Failed on OUT Status stage in ctl_read()"; + return resultcode; + + return 0; #Success + + xfrdata=[]; #Ugly variable used only by a few functions. FIXME + def IN_Transfer(self,endpoint,INbytes): + """Does an IN transfer to an endpoint, used for Host mode.""" + xfrsize=INbytes; + xfrlen=0; + self.xfrdata=[]; + + while 1: + resultcode=self.send_packet(tokIN,endpoint); #IN packet to EP. NAKS taken care of. + if resultcode: return resultcode; + + pktsize=self.rreg(rRCVBC); #Numer of RXed bytes. + + #Very innefficient, move this to C if performance is needed. + for j in range(0,pktsize): + self.xfrdata=self.xfrdata+[self.rreg(rRCVFIFO)]; + xfrsize=self.xfrdata[0]; + self.wreg(rHIRQ,bmRCVDAVIRQ); #Clear IRQ + xfrlen=xfrlen+pktsize; #Add byte count to total transfer length. + + print "%i / %i" % (xfrlen,xfrsize) + + #Packet is complete if: + # 1. The device sent a short packet, =xfrsize): + self.last_transfer_size=xfrlen; + ashex=""; + for foo in self.xfrdata: + ashex=ashex+(" %02x"%foo); + print "INPACKET EP%i==%s (0x%02x bytes remain)" % (endpoint,ashex,xfrsize); + return resultcode; + + RETRY_LIMIT=3; + NAK_LIMIT=300; + def send_packet(self,token,endpoint): + """Send a packet to an endpoint as the Host, taking care of NAKs. + Don't use this for device code.""" + self.retry_count=0; + self.nak_count=0; + + #Repeat until NAK_LIMIT or RETRY_LIMIT is reached. + while self.nak_count0: toret=toret+chr(c); + return toret; + class GoodFETMAXUSBHID(GoodFETMAXUSB): """This is an example HID keyboard driver, loosely based on the MAX3420 examples.""" def hidinit(self): """Initialize a USB HID device.""" + self.usb_disconnect(); self.usb_connect(); + self.hidrun(); def hidrun(self): @@ -186,7 +578,8 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): SUD=self.readbytes(rSUDFIFO,8); #Parse the SETUP packet - print "Handling a setup packet type 0x%02x" % ord(SUD[bmRequestType]); + print "Handling a setup packet of %s" % self.setup2str(SUD); + setuptype=(ord(SUD[bmRequestType])&0x60); if setuptype==0x00: self.std_request(SUD); @@ -196,14 +589,14 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): self.vendor_request(SUD); else: print "Unknown request type 0x%02x." % ord(SUD[bmRequestType]) - self.STALL_EP0(); + self.STALL_EP0(SUD); def class_request(self,SUD): """Handle a class request.""" print "Stalling a class request."; - self.STALL_EP0(); + self.STALL_EP0(SUD); def vendor_request(self,SUD): print "Stalling a vendor request."; - self.STALL_EP0(); + self.STALL_EP0(SUD); def std_request(self,SUD): """Handles a standard setup request.""" setuptype=ord(SUD[bRequest]); @@ -216,7 +609,7 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): else: print "Stalling Unknown standard setup request type %02x" % setuptype; - self.STALL_EP0(); + self.STALL_EP0(SUD); def get_interface(self,SUD): """Handles a setup request for SR_GET_INTERFACE.""" @@ -224,9 +617,9 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): self.wreg(rEP0FIFO,0); self.wregAS(rEP0BC,1); else: - self.STALL_EP0(); + self.STALL_EP0(SUD); - #Device Descriptor +#Device Descriptor DD=[0x12, # bLength = 18d 0x01, # bDescriptorType = Device (1) 0x00,0x01, # bcdUSB(L/H) USB spec rev (BCD) @@ -237,7 +630,7 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): 0x34,0x12, # bcdDevice--1234 1,2,3, # iManufacturer, iProduct, iSerialNumber 1]; - #Configuration Descriptor +#Configuration Descriptor CD=[0x09, # bLength 0x02, # bDescriptorType = Config 0x22,0x00, # wTotalLength(L/H) = 34 bytes @@ -359,7 +752,7 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): self.wregAS(rEP0BC,sendlen); else: print "Stalling in send_descriptor() for lack of handler for %02x." % desctype; - self.STALL_EP0(); + self.STALL_EP0(SUD); def set_configuration(self,SUD): """Set the configuration.""" bmSUSPIE=0x10; @@ -388,9 +781,9 @@ class GoodFETMAXUSBHID(GoodFETMAXUSB): self.wreg(rEP0FIFO,0x00); #Second byte is always zero. self.wregAS(rEP0BC,2); else: - self.STALL_EP0(); + self.STALL_EP0(SUD); else: - self.STALL_EP0(); + self.STALL_EP0(SUD); def service_irqs(self): """Handle USB interrupt events."""