; 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 CALL EP0InReady 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 ; Reply: 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 MOV DPTR, #OUT07IRQ ; Wait for valid data in EP0OutBuffer Wait4D: MOVX A, @DPTR ANL A, #00000001b JZ Wait4D MOVX @DPTR, A ; Clear the interrupt 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 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: JNB Configured, Reply ; If configured return a 1 (via 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 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 RET Deconfigured: CLR Configured 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