📄 kbusb.asm
字号:
;========================================================================
; FILE: usbkey.asm
;
; This file contains the code that implements the usb-specific
; routines to handle key scans.
;========================================================================
USB_NO_REPORT: equ 0
USB_REPORT_ERROR: equ 1
USB_REPORT_KEY: equ 2
;========================================================================
; Send keyboard report to host
;========================================================================
;========================================================================
; Send keyboard report to host
;========================================================================
Send_Keyboard_Report:
mov A,[usb_tx_required]
cmp A,0 ; if nothing to report
jz .idle ; check idle status
cmp A,USB_REPORT_ERROR ; else if we've got to send an error report
jnz .send
cmp A,[last_key_report] ; and the last one sent was not an error
jnz .send ; we can send this one too
.idle: ; else check idle status
mov A, [kbd_idle_period_ctr] ; if idle_period is zero, then we only send
cmp A, 0 ; reports on change
jz .exit ; exit task
dec A
mov [kbd_idle_period_ctr],A ; decrement idle period
jnz .exit ; and exit if idle period not expired
mov A,[last_key_report] ; otherwize get type of last report
.send: ;ok, we're REALLY going to send a new report
push A
iord EP_A1_Mode ; are we currently transmitting a report?
and A, USB_MODE_MASK
cmp A, ACKIN
pop A ; pop current request into A
jz .out ; yes, then exit (so we don't mess up
; the current transmission)
;
mov [last_key_report],A
mov A,0
mov [usb_tx_required],A
call Copy_report_buffer_to_EP1 ; copy report buffer to EP1 FIFO
call Enable_EP1_Transmission ; enable EP1 transmission
.out:
mov A,[kbd_idle_period]
mov [kbd_idle_period_ctr],A ;reset idle period
.exit:
ret
;========================================================================
; Copy report_buffer contents to EP1 FIFO
;========================================================================
Copy_report_buffer_to_EP1:
push A ; save registers on stack
push X
mov X, 7 ;count 8 of the darn things
copy_report_buffer_loop:
mov A,[last_key_report]
cmp A,USB_REPORT_ERROR
jz .error
mov A, [X + usb_report_buffer] ;assume we're sending a key stroke
jmp .next
.error:
mov A,X
index key_error_buffer ;else get error code byte
.next:
mov [X + KBBuffer], A ;put it into ep0 fifo
dec X
jnc copy_report_buffer_loop ;do next one
pop X ; restore registers from stack
pop A
ret
XPAGEOFF
key_error_buffer:
db 00,00,01,01,01,01,01,01
XPAGEON
;========================================================================
; Enable transmission from EP1 FIFO
;========================================================================
Enable_EP1_Transmission:
push A ; save accumulator on stack
iord EP_A1_Counter
and A, DATATOGGLE ; keep data toggle setting
or A, 8h ; packet size
iowr EP_A1_Counter
mov A, ACKIN ; enable packet transmission
iowr EP_A1_Mode
pop A ; restore accumulator
ret ; return
;========================================================================
; FUNCTION:usb_scan_keys
;
; This is the main entry point for the start of key scanning.
; This function calls the key scanner, which will generate calls to
; usbkey_putkey from the internal scanning loop of the key scanner.
;
;
;
;========================================================================
usbkey_scan_keys:
call ksc_scan_keys ; scan the keys
jc .send_error ; phantom situation,send error to host
mov A, [usb_key_count] ; are there more than 6 keys pressed?
cmp A, 7
jnc .send_error ; yes, then send error to host
mov A,0 ; no errors, clear the error byte
mov [usb_current_state],A ; and return
jmp .exit
.send_error:
mov A,USB_REPORT_ERROR ; there's currently an error,
mov [usb_tx_required],A
mov [usb_current_state],A ; mark as such
.exit:
ret
;========================================================================
; FUNCTION:usbkey_putkey
;
;handles key presses in usb environment.
;
; This function is called from within the key scanning loop, each time a
; valid key event has been recognized. A key event is defined as whenever
; an individual key changes state, either up or down. the key is
; identified by a unique number in the accumulator from 1 to XXX,
; where XXX is GENERALLY the corresponding AT101 keyboard number, with
; few execptions (see at101.inc).
;========================================================================
usbkey_putkey:
; call usb_power_key
; jc .done_putkey
call ksc_modifier ;check for a modifier
jnc .non_modifiers
mov A, USB_REPORT_KEY ; show that a report is required
mov [usb_tx_required], A
mov A,[ksc_mod0]
mov [usb_last_mod],A
jmp .done_putkey
.non_modifiers:
index usb_usage_table
push X ; save X on stack
push A ; save key code on stack
mov A, USB_REPORT_KEY ; show that a report is required
mov [usb_tx_required], A
mov A, [ksc_down_up]
cmp A, 0
jnz .add_key_to_buffer ; key down
; otherwise, key is up
.remove_key_from_buffer: ; key is up, so remove if from buffer
mov A, [usb_key_count]
cmp A, 0 ; decrement key count (unless it's 0)
jz .skip_decrement_key_count
dec [usb_key_count]
.skip_decrement_key_count:
mov X, 2
.find_key_in_buffer: ; find the key in the report buffer
pop A
push A
cmp A, [X + usb_report_buffer]
jz .clear_buffer_position
inc X
mov A, X
cmp A, 8
jc .find_key_in_buffer
pop A
jmp .non_modifiers_done ; done search
.clear_buffer_position: ; key found in buffer, so clear position
pop A
mov A, 0
mov [X + usb_report_buffer], A
jmp .non_modifiers_done
.add_key_to_buffer: ; key went down, so put it in the buffer
mov A, [usb_key_count]
cmp A, FFh ; increment key count (unless it's 255)
jz .skip_increment_key_count
inc [usb_key_count]
.skip_increment_key_count:
mov X, 2
.find_free_buffer_position: ; find a free buffer position
mov A, 0
cmp A, [X + usb_report_buffer]
jz .put_key_in_buffer_position
inc X
mov A, X
cmp A, 8
jc .find_free_buffer_position
pop A
jmp .non_modifiers_done ; could not find a free position
; more than 6 keys pressed
.put_key_in_buffer_position: ; found a free buffer position, so put key code there
pop A
mov [X + usb_report_buffer], A
.non_modifiers_done:
pop X
.done_putkey:
ret
; XPAGEOFF
;power_key_table:
; db AT101KB_POWER,AT101KB_SLEEP,AT101KB_WAKE
;power_bit_table:
; db 1,2,4
;
; XPAGEON
NUM_POWER_KEYS: equ 3
;========================================================================
; FUNCTION:usb_power_key
;
;handles power, sleep, and wake key presses in usb environment.
;
; This function was invented to trap the power, sleep, and wake key presses
; and maintain a single byte whose format is as follows:
;
; bit 1: 1 = power key pressed
; bit 2: 1 = sleep key pressed
; bit 3 1 = wake key pressed
;
; if any of these three keys changes state, the corresponding bit in the
; bit field is modified and the usb_power_flag is set to indicate that the
; state of the power keys has changed.
;========================================================================
;usb_power_key:
;
; push X
; push A
;
; mov X,usb_power_keys
;
;.lp0:
; mov [ksc_work],A ;store key in work byte
; mov A,(NUM_POWER_KEYS - 1) ;initialize A to number of power keys
;.lp1:
; push A ;save index
; index power_key_table ;get lookup
; cmp A,[ksc_work] ;compare to key
; pop A ;restore index
; jz .lp2 ;compare was a success, key found
; dec A
; jc .non_modifier ;index < 0, non-power key
; jmp .lp1
;
;.lp2:
; index power_bit_table ;now index into bit to set/clear
; push A ; clear or set bit
; mov A, [ksc_down_up] ; depending on if key went
; cmp A, 00h ; up or down
; pop A ; restore bit pattern
; jz .mod0_up ; key went down
; or [X + 0], A ; set bit
; jmp .done_putkey
;.mod0_up: ; else, key went up
; cpl ; so clear bit
; and [X + 0], A
;.done_putkey: ;set carry indicating key found
; mov A,0ffh
; mov [usb_power_flag],A
; SETC
;.exit:
; pop A ;restore A,X
; pop X
; ret
;
;.non_modifier: ;clear carry indicating no key found
; CLEARC
; jmp .exit
;
;usb_init_keyscan:
;; CLEARRAM usbkey_ram_base,USBKEY_RAM_SIZE
; mov A,POWER_REPORT_ID
; mov [usb_power_id],A
; ret
XPAGEOFF
usb_usage_table:
db 000h,035h,01eh,01fh,020h,021h,022h,023h ;0-7
db 024h,025h,026h,027h,02dh,02eh,000h,02ah ;8-15
db 02bh,014h,01ah,008h,015h,017h,01ch,018h ;16-23
db 00ch,012h,013h,2fh,030h,031h,039h,004h ;24-31
db 016h,007h,009h,00ah,00bh,00dh,00eh,00fh ;32-39
db 033h,034h,032h,028h,0e1h,064h,01dh,01bh ;40-47
db 006h,019h,005h,011h,010h,036h,037h,038h ;48-55
db 000h,0e5h,0e0h,000h,0e2h,02ch,0e6h,000h ;56-63
db 0e4h,000h,000h,000h,000h,000h,000h,000h ;64-71
db 000h,000h,000h,049h,04ch,000h,000h,050h ;72-79
db 04ah,04dh,000h,052h,051h,04bh,04eh,000h ;80-87
db 000h,04fh,053h,05fh,05ch,059h,000h,054h ;88-95
db 060h,05dh,05ah,062h,055h,061h,05eh,05bh ;96-103
db 063h,056h,057h,000h,058h,000h,029h,000h ;104-111
db 03ah,03bh,03ch,03dh,03eh,03fh,040h,041h ;112-119
db 042h,043h,044h,045h,046h,047h,048h,0e3h ;120-127
db 0e7h,065h,066h,067h,068h,000h,000h,000h ;128-235
XPAGEON
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -