📄 hub_ep0.asm
字号:
mov COMMAND_BUFFER+2, RXDAT ; wValue MSB
mov COMMAND_BUFFER+5, RXDAT ; wIndex LSB
mov COMMAND_BUFFER+4, RXDAT ; wIndex MSB
mov COMMAND_BUFFER+7, RXDAT ; wLength LSB
mov COMMAND_BUFFER+6, RXDAT ; wLength MSB
setb RXFFRC ; Update receive FIFO state
clr RXSETUP
push DPX ; Processing the jump table will
; corrupt DPX. Save it here
lCall ProcessSetup
pop DPX ; Restore DPX
ReturnSetup:
Ret
;COMMENT *------------------------------------------------------------
;Function name : ProcessSetup
;Brief Description : Process a Setup token recd. on EP0. Thile some of the
; : code may look sifficult to understand the end result is not.
; : The following simply prepares a byte of data for use in a jump table.
; : The code compresses the 8 byte bmRequestValue into 4 1/2
; : bits by removing bits 2,3 & 4. These bits are never used
; : and it allows the jump table to be signfigantly smaller.
; : By using this jump table, the code size reduces by several
; : hundred bytes over the entire code!
; : THIS FIRMWARE IS ASSUMES BITS 2,3 & 4 are zero!!!!
; : By compressing the byte down, we limit the size
; : of the jump table.
;Regs preserved : No reg. is saved
;--------------------------------------------------------------------*
;SCOPE
ProcessSetup:
; The First step is setting up the Stage tracing variable by examing the
; bmRequest value. This will tell us if this is a control Write
; or control read command. For right now we will assume that this
; is a no data command and will therefore pre-initilize the data
; byte counters used to send data back, to zero.
mov gbFControlBufferBytesLeft, #00h
mov gbFControlBufferBytesLeft + 1, #00h
mov A, bmRequestType
jb ACC.7, SetupGetCommand
SetupSetCommand:
mov gbSetupSeqRX, #DATA_PHASE ; Advance State Machine to next state
mov gbSetupSeqTX, #STATUS_PHASE
; Now check to see if this is a control write with a data stage.
mov A, wLength
orl A, wLength+1
jz DoJumpTable ; If this is a no data command then process it
ret ; If we are expecting data then don't
; process the command yet. Exit and wait
; for the rest of the data to come in.
SetupGetCommand:
mov gbSetupSeqRX, #STATUS_PHASE ; Advance State Machine to next state
mov gbSetupSeqTX, #DATA_PHASE
DoJumpTable:
; This table will jump to the correct subroutine
; to handle the type of command contained in bmRequestType
; The new jmp table will be compressed by shifting and rotating
; out bits, 2,3 & 4.
; Place bmRequestType in the following order and then do the jump table
; on it.
; xx65107x
; if bits 65 == 11, Reserved = Error
; Unless you have time, don't spend a lot of time tracing the algorythm
; It's fancy and it works. If you don't understand it go ask someone for a quarter.
mov A, bmRequestType ; Get the value.
anl A, #0E3h ; Clear out bits 2,3,4 since
; we don't need these
; Reg A now looks like 765xxx10
RL A ; Put bits 1,0,& 7 in new placement
RL A ; Leave LSB cleared so jump is the number of words.
; xxxx1076
CheckBit6: ; 6 is currently in bit 0 position,
jnb ACC.0, CheckBit5 ; Convert it to bit 5 position
setb ACC.5 ; xx6x107x
CheckBit5: ; Bit 5 is currently at 7 position
jnb ACC.7, CheckValidType ; Convert it to bit 4 position
setb ACC.4 ; xx65107x
CheckValidType: ;
jnb ACC.5, GoodCommand ; If this bit (6) is clear we know
; it's a valid value
jb ACC.4, ReservedCommand ; Bit (6) was set, if bit 5 is set it's
; a reserved command.
ljmp GoodCommand
ReservedCommand:
orl EPCON, #0C0h ; Stall EP0.
ret
; THis code will branch to the correct jump statement
; in the bmRequestJumpTable below.
GoodCommand:
anl A, #3Eh
mov B, A
rr A
anl A, #1fH
clr CY
ADD A, B
mov DPTR, #bmRequestJumpTable
mov DPXL, #LOW HIGH16(GoodCommand) ; Get Page of Jump Table.
; Low byte of the upper 16 bits of the 32 bit address of the
; jump table.
; Is this code in RAM or ROM
jmp @A+DPTR ; Used because I use RISM sometimes
; which places code in RAM
;---------------------------------------
;-- bmRequest Jump Table ---------------
;-- The order of these are based on the
;-- compresion algorythm used above.
;-- Each of these instructions occupy two bytes of
;-- ROM. Do not change AJMP to LJMP as the algorytm depends on the
;-- 2 byte length of AJMP. LJMP is 3 bytes long
;-- ------------------------------------
bmRequestJumpTable:
LJMP StandardSetDeviceCommand
LJMP StandardGetDeviceCommand
LJMP StandardSetInterfaceCommand
LJMP StandardGetInterfaceCommand
LJMP StandardSetEndpointCommand
LJMP StandardGetEndpointCommand
LJMP StandardSetOtherCommand
LJMP StandardGetOtherCommand
LJMP ClassSetDeviceCommand
LJMP ClassGetDeviceCommand
LJMP ClassSetInterfaceCommand
LJMP ClassGetInterfaceCommand
LJMP ClassSetEndpointCommand
LJMP ClassGetEndpointCommand
LJMP ClassSetOtherCommand
LJMP ClassGetOtherCommand
LJMP VendorSetDeviceCommand
LJMP VendorGetDeviceCommand
LJMP VendorSetInterfaceCommand
LJMP VendorGetInterfaceCommand
LJMP VendorSetEndpointCommand
LJMP VendorGetEndpointCommand
LJMP VendorSetOtherCommand
LJMP VendorGetOtherCommand
;-----------------------------------------------------------------
;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs
;S
;S STANDARD TYPE COMMANDS FIRST
;S
;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs
;-----------------------------------------------------------------
;COMMENT *------------------------------------------------------------
;Function name : GetStandardDeviceCommand:
;Brief Description : Process a Get Standard Device Command Setup Token
; : This can only be a Get (Device or Configuration) Descriptor,
; : or Get Device Status, Get Configuration.
;Regs preserved : No reg. is saved
;--------------------------------------------------------------------*
;SCOPE
StandardGetDeviceCommand:
mov A, bRequest
cjne A, #GET_DESCRIPTOR, CheckGetConfiguration
mov A, bDescriptorType
cjne A, #DEVICE_DESCR, CheckConfigDescriptor
; ********************** GET DESCRIPTOR, DEVICE *******************
mov gbFControlBufferLocation, #LOW HIGH16(BEGIN_DEVICE_DESCRIPTOR)
mov gbFControlBufferLocation+1, #HIGH LOW16(BEGIN_DEVICE_DESCRIPTOR)
mov gbFControlBufferLocation+2, #LOW LOW16(BEGIN_DEVICE_DESCRIPTOR)
mov A, #12h
mov B, #00h
ljmp LoadBuffer
CheckConfigDescriptor:
cjne A, #CONFIG_DESCR, CheckStringDescriptor
; ********************** GET DESCRIPTOR, CONFIGURATION ************
mov gbFControlBufferLocation, #LOW HIGH16(BEGIN_CONFIG_DESCRIPTOR)
mov gbFControlBufferLocation+1, #HIGH LOW16(BEGIN_CONFIG_DESCRIPTOR)
mov gbFControlBufferLocation+2, #LOW LOW16(BEGIN_CONFIG_DESCRIPTOR)
mov A, #LOW (END_CONFIG_DESCRIPTOR - BEGIN_CONFIG_DESCRIPTOR)
mov B, #HIGH (END_CONFIG_DESCRIPTOR - BEGIN_CONFIG_DESCRIPTOR)
ljmp LoadBuffer
CheckStringDescriptor:
cjne A, #STRING_DESCR, ReturnBADSTDGetDeviceCommand
; ********************** GET DESCRIPTOR, CONFIGURATION ************
mov gbFControlBufferLocation, #LOW HIGH16(STRING_1)
mov gbFControlBufferLocation+1, #HIGH LOW16(STRING_1)
mov gbFControlBufferLocation+2, #LOW LOW16(STRING_1)
mov A, #LOW (STRING_2-STRING_1)
mov B, #HIGH(STRING_2-STRING_1)
ljmp LoadBuffer
LoadBuffer: ; Compare to see which is shorter.
; The amount asked for or the amount
; availible.
push ACC
push B
clr CY ; A=Actual-wLength=AskedFor
subb A, wLength+1
mov A, B
subb A, wLength
jc AskedFor_IsLarger
LengthsMatch:
wLengthIsSmaller: ; If Asked for is smaller, replace
; actual with asked for.
pop B
pop ACC
mov B, wLength
mov A, wLength+1
sjmp LoadIt
AskedFor_IsLarger:
pop B
pop ACC
LoadIt: ; From now on, wLength = bytes remaining.
mov gbFControlBufferBytesLeft, B
mov gbFControlBufferBytesLeft+1, A
lcall LoadControlTXFifo
ljmp ReturnSTDGetDeviceCommand
CheckGetConfiguration:
cjne A, #GET_CONFIGURATION, CheckGetStatus
;------------------------------------------------
;- GET CONFIGURATION
;------------------------------------------------
mov R11, CurrentConfiguration
mov TXDAT, A
mov TXCNTL,#01h
ljmp ReturnSTDGetDeviceCommand
CheckGetStatus:
cjne A, #GET_STATUS, ReturnSTDGetDeviceCommand
;------------------------------------------------
;- GET DEVICE STATUS
;------------------------------------------------
jnb HRWUPE, NotRWUEnabled
mov A, #03h ; RWU Enabled and self powered
sjmp DoneGetDeviceStatus
NotRWUEnabled:
mov A, #01h ; RWU Not Enabled and self powered
DoneGetDeviceStatus:
mov TXDAT, A
mov TXDAT, #00h
mov TXCNTL,#02h
ljmp ReturnSTDGetDeviceCommand
ReturnBADSTDGetDeviceCommand:
orl EPCON, #0C0h ; Stall EP0
ReturnSTDGetDeviceCommand:
ret
;COMMENT *------------------------------------------------------------
;Function name : StandardGetEndpointCommand:
;Brief Description : Process a Standard Set Endpoint Command Setup Token
; : This can only be a Set,Clear Feature - Endpoint Stall
; :
;Regs preserved : No reg. is saved
;--------------------------------------------------------------------*
;SCOPE
StandardGetEndpointCommand:
mov A, bRequest
cjne A, #GET_STATUS, ReturnBadSTDGetEPCommand
;------------------------------------------------
;- GET ENDPOINT STATUS
;------------------------------------------------
mov A, wIndex + 1
anl A, #0Fh ; Mask off all but the endpoint value
orl EPINDEX,A ; Point the Index register at the
mov A, wIndex + 1 ; Start by clearing out R0
jb ACC.7, GetInStallStatus
GetOutStallStatus:
mov A, EPCON
jnb ACC.6, NotStalled
mov A, #01 ; Return Stalled
ljmp DoneWithCommand
GetInStallStatus:
mov A, wIndex +1
anl A, #0Fh
cjne A, #00, GetEp1InStall
mov A, EPCON
jnb ACC.7, NotStalled
mov A, #01
sjmp DoneWithCommand
GetEp1InStall:
mov A, HSTAT ; GET EP1 Stall Information
anl A, #020h ; Mask off all but stall bit.
jz NotStalled
mov A, #01h
sjmp DoneWithCommand
NotStalled:
mov A, #00h
DoneWithCommand:
anl EPINDEX,#80h ; Point the index back to EP0
mov TXDAT, A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -