From: travisutk Date: Sun, 1 Apr 2012 21:27:53 +0000 (+0000) Subject: With a MAX3421 and the MAXUSB module, the GoodFET can now do both USB Host and USB... X-Git-Url: http://git.rot13.org/?p=goodfet;a=commitdiff_plain;h=35580fd76085fbc1c80000097cbd72e34ad5edee;ds=inline With a MAX3421 and the MAXUSB module, the GoodFET can now do both USB Host and USB Device. git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1127 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- diff --git a/client/GoodFETMAXUSB.py b/client/GoodFETMAXUSB.py index 96e8ad6..30fb06e 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 @@ -90,8 +109,97 @@ 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; @@ -142,6 +250,114 @@ 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)]; + self.wreg(rHIRQ,bmRCVDAVIRQ); #Clear IRQ + xfrlen=xfrlen+pktsize; #Add byte count to total transfer length. + + + #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" % (endpoint,ashex); + 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.""" diff --git a/client/goodfet.maxusbhost b/client/goodfet.maxusbhost new file mode 100755 index 0000000..92b56c6 --- /dev/null +++ b/client/goodfet.maxusbhost @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +#GoodFET MAXIM MAX3421 Host +#by Travis Goodspeed + +import sys; +import binascii; +import array; + +from GoodFETMAXUSB import GoodFETMAXUSBHost; + +#Initialize FET and set baud rate +client=GoodFETMAXUSBHost(); +client.serInit() + + +client.MAXUSBsetup(); +client.hostinit(); +