www.pudn.com > the USB Simple Terminal example (PC Host Software > usb_int.a51


; This module is common to all of the examples. 
; It services USB Requests from the SIE. 
; Interpretation of the Output Reports is handled by MAIN 
; 
 	CSEG 
ServiceSetupPacket: 
	MOV	DPTR, #SETUPDAT		; Point to Setup Packet data 
	MOVX	A, @DPTR		; Get the RequestType 
	MOV	C, ACC.7		; Bit 7 = 1 means IO device needs to send data to PC Host 
	MOV	SendData, C 
	ANL	A, #01011100b		; IF RequestType[6.4.3.2] = 1 THEN goto BadRequest 
	JNZ	BadRequest 
	MOVX	A, @DPTR		; IF RequestType[1&0] = 1 THEN goto BadRequest 
	MOV	C, ACC.0 
	ANL	C, ACC.1 
	JC	BadRequest 
	JNB	ACC.5, NotB5		; IF RequestType[5] = 1 THEN RequestType[1,0] = [1,1] 
	MOV	A, #00000011b 
NotB5:	ANL	A, #00000011b		; Set CommandIndex[5,4] = RequestType[1,0] 
	SWAP	A 
	MOV	Temp, A			; Save HI nibble of CommandIndex 
					; Set CommandIndex[3,0] = Request[3,0] 
	INC	DPTR			; Point to Request 
	MOVX	A, @DPTR 
	ANL	A, #00001111b		; Only 13 are defined today, handle in table 
	ORL	A, Temp	 
	CALL	CorrectSubroutine	; goto CommandTable(CommandIndex) 
					; Returns STALL=1 if a stall is required 
	JB	STALL, BadRequest 
       	JNB	SendData, HandShake 
	JB	IsDescriptor, LoadSUDPTR; EZ-USB has a short cut for descriptors 
                                        ; Send data in ReplyBuffer 
	MOV	DPTR, #EP0InBuffer+2 
	MOV	R0, #ReplyBuffer+3 
	MOV	Temp, #3		; Copy maximum byte count 
CopyRB:	MOV	A, @R0 
	MOVX	@DPTR, A 
	DEC	DPL 
	DEC	R0 
	DJNZ	Temp, CopyRB 
	MOV	A, @R0 			; Get real byte count 
SendEP0InBuffer: 
	MOV	DPTR, #In0ByteCount 
StartXfer: 
	MOVX	@DPTR, A		; This write initiates the transfer 
HandShake:				; Handshake with host 
	MOV	Temp, #00000010b 	; Set HSNAK to tell the SIE that we're done 
SetEP0Control: 
	MOV	DPTR, #EP0Control 
	MOVX	A, @DPTR 
	ORL	A, Temp 
	MOVX	@DPTR, A 
	RET 
LoadSUDPTR:			      	; Send the data pointed to by DPTR 
	MOV	Temp, DPL 
	MOV	A, DPH 
	MOV	DPTR, #SUDPTR 
	MOVX	@DPTR, A 
	MOV	A, Temp 
	INC	DPTR 
	JMP	StartXfer 
BadRequest:				; Invalid Request was received 
	MOV	Temp, #00000011b	; Set EP0STALL and HSNAK 
	JMP	SetEP0Control 
 
NextDPTR:				; Returns (DPTR + byte DPTR is pointing to) 
	MOVX	A, @DPTR 
BumpDPTR:				; Returns (DPTR + ACC) 
	ADD	A, DPL 
	MOV	DPL, A 
	JNC	Skip 
	INC	DPH			; Need 16 bit arithmetic here 
Skip:	RET 
 
CorrectSubroutine:			; Jump to the subroutine that DPTR is pointing to 
	MOV	DPTR, #CommandTable 
	CALL	BumpDPTR		; Point to entry 
	MOVX	A, @DPTR		; Get the offset 
	MOV	DPTR, #CommandTable 
	CALL	BumpDPTR                ; Get the routine address 
	PUSH	DPL			; Create a RETURN address on stack 
	PUSH	DPH                     ; Note: JMP @A+DPTR not used since A, DPTR needed 
	MOV	R0, #ReplyBuffer+2 
	CLR	A 
	MOV	@R0, A			; Clear ReplyBuffer 
	DEC	R0 
	MOV	@R0, A 
	DEC	R0 
	MOV	@R0, #1			; Default non-descriptor reply 
	MOV	DPTR, #SETUPDAT+2	; Point to LOW(wValue) 
	MOVX	A, @DPTR		; Many of the routines need these 
	MOV	B, A                    ; LOW(wValue) in B 
	INC	DPTR 
	MOVX	A, @DPTR            	; HIGH(wValue) in A 
	CLR	STALL 
	CLR	IsDescriptor 
	RET				; Go to service routine 
 
; Since the table only contains byte offsets, it is important that all these routines are 
; within one page (100H) of CommandTable 
; 
CommandTable: 
; First 16 commands are for the Device 
	DB Device_Get_Status - CommandTable 
	DB Device_Clear_Feature - CommandTable 
	DB Invalid - CommandTable 
	DB Device_Set_Feature - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable		; SIE implements Device_Set_Address 
	DB Get_Descriptor - CommandTable 
	DB Set_Descriptor - CommandTable 
	DB Get_Configuration - CommandTable 
	DB Set_Configuration - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
; Next 16 commands are for the Interface 
	DB Interface_Get_Status - CommandTable 
	DB Interface_Clear_Feature - CommandTable 
	DB Invalid - CommandTable 
	DB Interface_Set_Feature - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Get_Class_Descriptor - CommandTable 
	DB Set_Class_Descriptor - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Get_Interface - CommandTable 
	DB Set_Interface - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
; Next 16 commands are for the Endpoint 
	DB Endpoint_Get_Status - CommandTable 
	DB Endpoint_Clear_Feature - CommandTable 
	DB Invalid - CommandTable 
	DB Endpoint_Set_Feature - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Endpoint_Sync_Frame - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
; Next 16 commands are Class Requests 
	DB Invalid - CommandTable 
	DB Get_Report - CommandTable 
	DB Get_Idle - CommandTable 
	DB Get_Protocol - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Set_Report - CommandTable 
	DB Set_Idle - CommandTable 
	DB Set_Protocol - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
	DB Invalid - CommandTable 
; 
; Many requests are INVALID for this example 
Get_Protocol:			; We are not a Boot device 
Set_Protocol: 			; We are not a Boot device 
Set_Descriptor:			; Our Descriptors are static 
Set_Class_Descriptor:          	; Our Descriptors are static 
Set_Interface:			; We only have one Interface 
Get_Interface:			; We do not have an Alternate setting 
Device_Set_Feature: 		; We have no features that can be set or cleared 
Interface_Set_Feature: 		; We have no features that can be set or cleared 
Endpoint_Set_Feature: 		; We have no features that can be set or cleared 
Device_Clear_Feature:		; We have no features that can be set or cleared  
Interface_Clear_Feature: 	; We have no features that can be set or cleared 
Endpoint_Sync_Frame:		; We are not an Isonchronous device 
 
Invalid:			; Invalid Request made, STALL the Endpoint 
	SETB	STALL 
; 
Endpoint_Clear_Feature: 	; We have no features that can be set or cleared 
; 
	RET 
 
Set_Report:				; Host wants to sent us a Report.  
; The ONLY case in this example where host sends data to us 
	JNB	Configured, Invalid	; Need to be Configured to do this command 
	MOV	DPTR, #Out0ByteCount	; Enable EP0OutBuffer to receive data 
	MOVX	@DPTR, A 		; Any value will do, this sets OUTBSY 
        MOV	DPTR, #EP0Control	; Wait for valid data in EP0OutBuffer 
Wait40:	MOVX	A, @DPTR 
	ANL	A, #00001000b		; Check OUTBSY 
	JNZ	Wait40 
	JMP	ProcessOutputReport	; RETurn via this subroutine 
Get_Report:				; Host wants a Report 
	JNB	Configured, Invalid	; Need to be Configured to do this command  
	INC	R0			; Point to ReplyBuffer(1) 
	MOV	@R0, #18H               ; Reply with a recognizable (arbitary) value 
Reply:	RET 
Set_Idle:				; Host wants to tell us how often we should talk 
	JNB	Configured, Invalid	; Need to be Configured to do this command  
	MOV	Idle_Time, A 
	RET				; Handshake with host 
Get_Idle:				; Host must have forgotten what he told us to do 
	JNB	Configured, Invalid	; Need to be Configured to do this command  
        INC	R0			; Point to ReplyBuffer(1) 
	MOV	@R0, Idle_Time 
	RET 
Get_Configuration:			; Need to return 0 or 1 
	JNB	Configured, Configuration0 
Configuration1:				; Same bit pattern as Device_Get_Status	 
Device_Get_Status:			; Only two bits of Device Status are defined 
	INC	R0			; Point to ReplyBuffer(1) 
	MOV	@R0, #1			; Bit 1=Remote Wakeup(=0), Bit 0=Self Powered(=1) 
	RET 
Configuration0:				; Same bit pattern as Interface_Get_Status 
Interface_Get_Status:			; Interface Status is currently defined as 0 
Endpoint_Get_Status: 
        MOV	@R0, #2 
	RET 
Set_Configuration:   			; Valid values are 0 and 1 
	MOV	A, B			; Get LOW(wValue) 
	JZ	Deconfigured 
	DEC	A 
	JNZ	Invalid 
	SETB	Configured 
; It is now OK to create input reports. 
; Enable Endpoint 1 IN interrupts 
	MOV	DPTR, #IN07IEN		; Get interrupt mask 
	MOVX	A, @DPTR 
	ORL	A, #00000010b		; Set bit 1 = IN1IEN 
	MOVX	@DPTR, A 
	SETB	EP1INReady 
	SETB	TXReady			; Kick start the Serial Port 
	RET 
Deconfigured: 
	CLR	Configured 
; Disable Input Report Generation 
	MOV	DPTR, #IN07IEN		; Get interrupt mask 
	MOVX	A, @DPTR 
	ANL	A, #11111101b		; Set bit 1 = 0 (disable) 
	MOVX	@DPTR, A 
	CLR	EP1INReady 
	CLR	TXReady 
	RET 
Get_Descriptor:		   		; Host wants to know who/what we are 
	SETB	IsDescriptor 
	DEC	A			; Valid Values are 1, 2 and 3 
	MOV	DPTR, #DeviceDescriptor 
	JZ	Reply 
	DEC	A 
	MOV	DPTR, #ConfigurationDescriptor 
	JZ	Reply 
	DEC	A 
	JNZ	Invalid 
; Request is for a String Descriptor 
	MOV	DPTR, #String0		; Point to String 0 
	MOV	A, B			; Get String Index 
NextString: 
	JZ	FixUpthenReply 
	MOV	Temp, A			; Save String Index 
	CALL	NextDPTR 
	MOVX	A, @DPTR		; Get the String Length (= 0 means we're at Backstop) 
	JZ	Invalid			; Asked for a string I don't have  
	MOV	A, Temp 
	DEC	A 
	JMP	NextString		; Check if we are there yet 
Get_Class_Descriptor: 			; Valid values are 21H, 22H, 23H for Class Request 
	SETB	IsDescriptor 
	CLR	C 
	SUBB	A, #21H 
	MOV	DPTR, #HIDDescriptor 
	JZ	Reply 
	DEC	A 
	MOV	DPTR, #ReportDescriptor 
	JZ	Reply 
;	DEC	A			; This example does not use Physical Descriptors 
;	JZ	Send_Physical_Descriptor 
	JMP	Invalid 
; 
; Error check: this MUST be on within a page of CommandTable 
WithinSamePage EQU $ - CommandTable	 
; 
FixUpthenReply:				; EZ-USB Rev D has a String Descriptor bug 
					; Need to fill the IN0BUF (@ 7F00H) myself 
	MOVX	A, @DPTR		; Get the string length 
	MOV	R7, A			; Save counter 
	MOV	B, A 
	MOV	R0, #LOW(EP0InBuffer)	; PageReg = 7FH = HIGH(EP0InBuffer) 
CopySD:	MOVX	@R0, A 
	INC	R0 
	INC	DPTR 
        MOVX	A, @DPTR 
	DJNZ	R7, CopySD 
; Fixup complete, get back to the program flow 
	POP	ACC			; Get rid of the return address 
	POP	ACC 
	MOV	A, B			; Retrieve byte count 
	JMP	SendEP0InBuffer