📄 usbkey.asm
字号:
;========================================================================
; FILE: usbkey.asm
;
; This file contains the code that implements the usb-specific
; routines to handle key scans.
;
; REVISIONS:
;
; 02/2/99
; rewrote usb_scan_keys, moved idle function into usbmain instead
; 12/28/98
; removed RAM allocation for error code buffer to save space.
; The error codes are now sent from a ROM table (see changes
; to usbmain.asm)
; 11/9/98 modified to send bit-field for power, sleep, and wake
; in accordance with latest PC98 specifications. This change
; accompanies changes to the endpoint 2 descriptor and code
; in usbmain to send the new usage.
;
; modified scan codes for power, sleep, and wake keys to be old
; style 0x66,0x67, and 0x68, respectively. This passes the current
; (August 98) Keyboard WHQL tests.
;
;========================================================================
;========================================================================
; Global Variables
;========================================================================
USB_KEY_BUFFER_SIZE: EQU 8
; keyboard duplicate input report buffer (8 bytes)
; This buffer is sent to the host as a USB keyboard packet
usb_current_state: equ (usbkey_ram_base + 0);storage for type of last report
;(error report or key report)
usb_key_count: equ (usbkey_ram_base + 1) ; indicates number of keys pressed
usb_tx_required: equ (usbkey_ram_base + 2) ; indicates a key(s) changed state
usb_power_id: equ (usbkey_ram_base + 3)
usb_power_keys: equ (usbkey_ram_base + 4)
usb_power_flag: equ (usbkey_ram_base + 5)
usb_consumer_id: equ (usbkey_ram_base + 6)
usb_consumer_keys: equ (usbkey_ram_base + 7)
usb_consumer_flag: equ (usbkey_ram_base + 8)
usb_report_buffer: equ (usbkey_ram_base + 9)
usb_last_mod: equ usb_report_buffer ; last modifier
USBKEY_RAM_SIZE: equ 9 + USB_KEY_BUFFER_SIZE
USB_NO_REPORT: equ 0
USB_REPORT_ERROR: equ 1
USB_REPORT_KEY: equ 2
;========================================================================
; 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 usb_consumer_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
consumer_key_table:
db AT101KB_VOL_INC, AT101KB_VOL_DEC, AT101KB_MUTE
consumer_bit_table:
db 1,2,4
XPAGEON
NUM_POWER_KEYS: equ 3
NUM_CONSUMER_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
mov A,CONSUMER_REPORT_ID
mov [usb_consumer_id], A
ret
;========================================================================
; FUNCTION:usb_consumer_key
;
;handles volume inc, volume dec, and mute key presses in usb environment.
;
; This function was invented to trap the consumer key presses
; and maintain a single byte whose format is as follows:
;
; bit 1: 1 = volume inc key pressed
; bit 2: 1 = volume dec key pressed
; bit 3: 1 = mute key pressed
;
; if any of these three keys changes state, the corresponding bit in the
; bit field is modified and the usb_consumer_flag is set to indicate that the
; state of the consumer keys has changed.
;========================================================================
usb_consumer_key:
push X
push A
mov X,usb_consumer_keys
.lp0:
mov [ksc_work],A ;store key in work byte
mov A,(NUM_CONSUMER_KEYS - 1) ;initialize A to number of consumer keys
.lp1:
push A ;save index
index consumer_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 consumer_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_consumer_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_keyscan2:
CLEARRAM usbkey_ram_base,USBKEY_RAM_SIZE
mov A,CONSUMER_REPORT_ID
mov [usb_consumer_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 + -