📄 usbmain.asm
字号:
;
;
USB_EP0_ISR:
push A ; save accumulator on stack
mov A,[0f8h] ; get fifo 1st byte
mov [EP0_fifo_shadow],A ; save it
iord EP_A0_Counter
mov [EP_A0_counter_shadow],A
iord EP_A0_Mode ;
mov [EP0_mode_shadow],A ; save mode
and A,ACK_BIT ; if nothing was ACKed
jz .exit ; get out now
disable_EP0_int ; prevent further interrupts while we process this one
mov A,1 ; flag that we need to do something
mov [EP0_FLAG],A
.exit:
pop A
reti
;========================================================================
; EP0 -- handle a request that came in on EP0.
;
;The EP0 ISR, in combination with the automatic mode switching of the SIE,
;allows the processing of EP0 traffic to take place in the main loop in a
;non time-critical fashion. By the time the code has reached this point,
;the incoming EP0 event has been recorded by the ISR and must be parsed here.
;
;========================================================================
EP0:
.start:
mov A,[EP0_mode_shadow] ;get the copy of the mode register
and A, EP0_SETUP_RCV ;if a setup was received
jz .out
call EP0_setup ; handle it
jmp .exit ; and exit
.out:
mov A,[EP0_mode_shadow] ;if an out was received
and A, EP0_OUT_RCV
jz .in
call EP0_out ; handle it
jmp .exit ; and exit
.in:
mov A,[EP0_mode_shadow] ;if an in was received
and A,EP0_IN_RCV
jz .exit
call EP0_in ; handle it
.exit:
iord EP_A0_Mode ; get mode reg
and A,EP0_SETUP_RCV ; if setup bit is set
jz .exit1
enable_EP0_int ;get out now
ret
.exit1:
di ;
mov A,[EP0_Next_Mode] ;write the next mode
iowr EP_A0_Mode ;
enable_EP0_int ;re-enable interrupts
ei ;
ret ;and return
;========================================================================
; EP0_setup handles the setup stage of a transaction
;
;========================================================================
EP0_setup:
mov A,NAKINOUT
iowr EP_A0_Mode
iord EP_A0_Counter ; check if data is valid
and A, DATAVALID
jz stall_in_out ; otherwise STALL IN/OUT
iord EP_A0_Counter ; make sure we received 10 data bytes
and A, COUNT_MASK ; (8 data bytes + 2 CRC bytes)
cmp A, 0Ah
jnz stall_in_out ; otherwise STALL IN/OUT
iord EP_A0_Counter ; check if data toggle is 0
and A, DATATOGGLE
jnz stall_in_out ; otherwise STALL IN/OUT
call StageOne ; parse SETUP packet
ret
;========================================================================
; EP0_out handles the out stage of a transaction
;
;========================================================================
EP0_out:
;in the case of the keyboard,an ACKed out occurs either in the case of
;the status phase of a control read, or the data out phase of a control write.
mov A,[EP0_mode_shadow] ;get contents of mode
and A,USB_MODE_MASK
cmp A,NAKOUTSTATUSIN ;if we've just acked an out
jnz stall_in_out
call Control_write ;go process it
ret
;========================================================================
; EP0_in handles the in stage of a transaction
;
;========================================================================
EP0_in:
;an ACKed IN occurs either in the case of the status phase of a control write,
;or the data in phase of a control read.
mov A,[EP0_mode_shadow]
and A,USB_MODE_MASK
cmp A,NAKIN_STATUSOUT ;this indicates we've acked an in
jnz stall_in_out
call next_control_read ;so prepare for the next one
ret
stall_in_out: ; accept SETUP, stall IN/OUT
call SendStall
ret
;========================================================================
; look for valid combinations of bmRequestType and bRequest.
; all of the interesting combinations are in the table bRequest_table,
; represented as 2-byte quantities
;
;========================================================================
StageOne:
mov X,bRequest_table_len ;initialize X to size of table
.loop:
dec X ;decrement by 2 to point to entry
jc SendStall ;if result is minus, we didn't find an entry
dec X
mov A,X ;move index to A
index bRequest_table ;get table entry and compare with bmRequestType
cmp A,[bmRequestType]
jnz .loop ;no match, try next entry
mov A,X ;now get next table entry and compare with bRequest
index bRequest_table+1
cmp A,[bRequest]
jnz .loop ;no match, try next entry
.found:
mov A,X ;X contains entry into jump table
jacc jmp_tbl
;
XPAGEOFF
jmp_tbl:
jmp ClearRemoteWakeup
jmp SetRemoteWakeup
jmp SetAddress
jmp SetConfiguration
jmp SetInterface
jmp ClearEndpointStall
jmp SetEndpointStall
jmp GetDeviceStatus
jmp GetDescriptor
jmp GetConfiguration
jmp GetInterface
jmp GetInterfaceStatus
jmp GetInterfaceStatus
jmp GetDescriptor
jmp GetInterface
jmp GetEndpointStatus
jmp GetDescriptor
jmp GetInterface
jmp SetReport
jmp SetIdle
jmp SetProtocol
jmp SetReport
jmp SetIdle
jmp SetProtocol
jmp GetReport
jmp GetIdle
jmp GetProtocol
;the following table contains valid pairs of bmRequestType and bRequest.
;The offset into the table matches the offset into the above jump table
bRequest_table:
db 00,01,00,03,00,05,00,09 ;clear remote wkp,set remote wkp,set address,set config
db 01,11 ;set interface
db 02,01,02,03 ;clear endpoint stall, set endpoint stall
db 80h,00,80h,06,80h,08,80h,10 ;get device status, descriptor, configuration ,interface
db 81h,00,81h,01,81h,06,81h,10 ;get interface status,get interface status, descriptor,get interface
db 82h,00,82h,06,82h,10 ;get endpoint status, descriptor,get interface
db 21h,09,21h,10,21h,11 ;set report,set idle, set protocol
db 22h,09,22h,10,22h,11 ;set report,set idle, set protocol
db A1h,01,A1h,02,A1h,03 ;get report,get idle, get protocol
end_bRequest_table:
bRequest_table_len: EQU (end_bRequest_table - bRequest_table)
XPAGEON
;-----------------------------------------------------------------------
; Stall unsupported functions
;-----------------------------------------------------------------------
SendStall: ; stall unsupported functions
mov A, STALL
mov [EP0_Next_Mode],A
ret
;========================================================================
; stage three ... process the request
;========================================================================
; Remote wakeup is the ability to wakeup a system from power down mode
; when the user presses a key. These routines
; allow the host to enable/disable the ability to request remote wakeup.
;
; Disable the remote wakeup capability.
ClearRemoteWakeup:
mov A,[wValueHi]
cmp A,0
jnz SendStall
mov A, [wValue] ; load wValue
cmp A, device_remote_wakeup ; test for valid feature
jnz SendStall ; stall unsupported features
mov A, DISABLE_REMOTE_WAKEUP ; disable remote wakeup
mov [remote_wakeup_status], A
call no_data_control ; handshake with host
ret ; return
; Enable the remote wakeup capability.
SetRemoteWakeup:
mov A, [wValue] ; load wValue
cmp A, device_remote_wakeup ; test for valid feature
jnz SendStall ; stall unsupported features
mov A, ENABLE_REMOTE_WAKEUP ; enable remote wakeup
mov [remote_wakeup_status], A
call no_data_control ; handshake with host
ret ; return
; Set the device address to the wValue in the SETUP packet at
; the completion of the current transaction.
SetAddress:
call no_data_control_wait ; handshake with host
iord EP_A0_Mode ; read mode register
and A, EP0_SETUP_RCV ; did we receive premature SETUP?
jnz done_SetAddress ; yes, abort the set address
mov A, [wValue] ; load wValue
or A, ADDRESS_ENABLE_BIT ; enable USB address
iowr USB_Device_Address ; write new USB device address
done_SetAddress:
ret ; return
; Set the configuration of the device to either unconfigured (0) or
; configured (1) based on wValue in the SETUP packet. According to
; the USB spec (page 178), a Set Configuration also clears the endpoint
; stall condition and re-initializes endpoints using data 0/1 toggle to
; Data0.
SetConfiguration:
mov A,[wValueHi]
cmp A,0
jnz SendStall
mov A, [wValue] ; load wValue lsb
cmp A, UNCONFIGURED ; the only config. values that are
jnz check_value_is_configured ; valid are 0 and 1
jmp set_config_value
check_value_is_configured:
cmp A, CONFIGURED
jnz SendStall
set_config_value:
mov [configuration_status], A ; store configuration byte
mov A, 0
mov [ep1_stall_status], A ; not stalled
mov [ep2_stall_status], A ; not stalled
iord EP_A1_Counter ; clear data 0/1 bit for EP1
and A, ~DATATOGGLE
iowr EP_A1_Counter
iord EP_A2_Counter ; clear data 0/1 bit for EP2
and A, ~DATATOGGLE
iowr EP_A2_Counter
mov A, [configuration_status]
cmp A, UNCONFIGURED
jnz device_configured
; device is unconfigured
mov A, DISABLED ; Disable endpoint 1 and 2
iowr EP_A1_Mode
iowr EP_A2_Mode
mov A, ENUMERATE ; disable endpoint interrupts
iowr Endpoint_Interrupt
mov A,(CAPS_LOCK_LED + NUM_LOCK_LED + SCROLL_LOCK_LED)
call ksc_writeLED
jmp done_SetConfiguration
; device is configured
device_configured:
mov A, NAKIN ; NAK IN packets until data is
iowr EP_A1_Mode ; ready on endpoint one and two
iowr EP_A2_Mode
mov A, EP0_EP1_EP2 ; enable endpoint one and two interrupts
iowr Endpoint_Interrupt
mov A,0
call ksc_writeLED
done_SetConfiguration:
call no_data_control ; handshake with host
ret ; return
; Clear the endpoint stall feature for the selected endpoint. This
; should also set the data 0/1 bit to Data0 if endpoint one is selected.
ClearEndpointStall:
mov A, [configuration_status]
cmp A, UNCONFIGURED
jz SendStall
mov A, [wValue] ; load wValue (which feature)
cmp A, endpoint_stall ; test for valid feature
jnz SendStall ; stall unsupported features
; clear endpoint stall feature
mov A,[wIndexHi]
cmp A,0
jnz SendStall
mov A,[wIndex]
cmp A,81h
jz .clear1
cmp A,82h
jnz SendStall
mov A,0
mov [ep2_stall_status], A ; not stalled
iord EP_A2_Counter ; clear data 0/1 bit for EP2
and A, ~DATATOGGLE
iowr EP_A2_Counter
mov A, NAKIN ; NAK IN packets until data is
iowr EP_A2_Mode ; ready on endpoint two
jmp .done
.clear1:
mov A,0
mov [ep1_stall_status], A ; not stalled
iord EP_A1_Counter ; clear data 0/1 bit for EP1
and A, ~DATATOGGLE
iowr EP_A1_Counter
mov A, NAKIN ; NAK IN packets until data is
iowr EP_A1_Mode ; ready on endpoint one
.done:
call no_data_control ; handshake with host
ret ; return
; host may attempt to set the interface to an alternate setting. We do not
; support any alternate setting, but if the alternate setting number is 0
; then we should not stall that request
SetInterface:
call Interface0
jz .set
call Interface1
jnz SendStall
.set:
mov A, [wValue] ; which alternate setting is requested?
or A, [wValueHi]
jnz SendStall ; if host requested alternate setting 0
iord EP_A1_Counter ; clear data 0/1 bit for EP1
and A, ~DATATOGGLE
iowr EP_A1_Counter
iord EP_A2_Counter ; clear data 0/1 bit for EP2
and A, ~DATATOGGLE
iowr EP_A2_Counter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -