kolibrios/kernel/trunk/hid/keyboard.inc

834 lines
22 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
VKEY_LSHIFT = 00000000_00000001b
VKEY_RSHIFT = 00000000_00000010b
VKEY_LCONTROL = 00000000_00000100b
VKEY_RCONTROL = 00000000_00001000b
VKEY_LALT = 00000000_00010000b
VKEY_RALT = 00000000_00100000b
VKEY_CAPSLOCK = 00000000_01000000b
VKEY_NUMLOCK = 00000000_10000000b
VKEY_SCRLOCK = 00000001_00000000b
VKEY_LWIN = 00000010_00000000b
VKEY_RWIN = 00000100_00000000b
VKEY_SHIFT = VKEY_LSHIFT + VKEY_RSHIFT
VKEY_CONTROL = VKEY_LCONTROL + VKEY_RCONTROL
VKEY_ALT = VKEY_LALT + VKEY_RALT
uglobal
align 4
kb_state dd 0
ext_code db 0
keyboard_mode db 0
keyboard_data db 0
altmouseb db 0
ctrl_alt_del db 0
kb_lights db 0
old_kb_lights db 0
align 4
hotkey_scancodes rd 256 ; we have 256 scancodes
hotkey_list rd 256*4 ; max 256 defined hotkeys
hotkey_buffer rd 120*2 ; buffer for 120 hotkeys
endg
iglobal
hotkey_tests dd hotkey_test0
dd hotkey_test1
dd hotkey_test2
dd hotkey_test3
dd hotkey_test4
hotkey_tests_num = 5
endg
;---------------------------------------------------------------------
hotkey_test0:
test al, al
setz al
ret
;---------------------------------------------------------------------
hotkey_test1:
test al, al
setnp al
ret
;---------------------------------------------------------------------
hotkey_test2:
cmp al, 3
setz al
ret
;---------------------------------------------------------------------
hotkey_test3:
cmp al, 1
setz al
ret
;---------------------------------------------------------------------
hotkey_test4:
cmp al, 2
setz al
ret
;---------------------------------------------------------------------
hotkey_do_test:
push eax
mov edx, [kb_state]
shr edx, cl
add cl, cl
mov eax, [eax+4]
shr eax, cl
and eax, 15
cmp al, hotkey_tests_num
jae .fail
xchg eax, edx
and al, 3
call [hotkey_tests + edx*4]
cmp al, 1
pop eax
ret
;--------------------------------------
.fail:
stc
pop eax
ret
;---------------------------------------------------------------------
align 4
; @brief Export function - Add new scancode in buffer
; @param ecx - scancode
; @return not return
set_keyboard_data:
movzx eax, word[thread_count]; top window process
movzx eax, word[WIN_POS + eax*2]
shl eax, BSF sizeof.APPDATA
mov al, [SLOT_BASE + eax + APPDATA.keyboard_mode]
mov [keyboard_mode], al
mov eax, ecx
push ebx esi edi ebp
call send_scancode
pop ebp edi esi ebx
ret
;---------------------------------------------------------------------
struct KEYBOARD
next dd ?
prev dd ?
functions dd ?
userdata dd ?
ends
struct KBDFUNC
strucsize dd ?
close dd ?
setlights dd ?
ends
iglobal
keyboards:
dd keyboards
dd keyboards
endg
uglobal
keyboard_list_mutex MUTEX
endg
; @brief Export function - Registration new keyboard
; @param [esp + 4] - pointer on KBDFUNC this keyboard
; @param [esp + 8] - userdata for callback function
; @return eax = pointer on KEYBOARD structure or 0 on error
register_keyboard:
push ebx
movi eax, sizeof.KEYBOARD
call malloc
test eax, eax
jz .nothing
mov ecx, [esp+4+4]
mov [eax + KEYBOARD.functions], ecx
mov ecx, [esp+8+4]
mov [eax + KEYBOARD.userdata], ecx
xchg eax, ebx
mov ecx, keyboard_list_mutex
call mutex_lock
mov ecx, keyboards
mov edx, [ecx + KEYBOARD.prev]
mov [ebx + KEYBOARD.next], ecx
mov [ebx + KEYBOARD.prev], edx
mov [edx + KEYBOARD.next], ebx
mov [ecx + KEYBOARD.prev], ebx
mov ecx, [ebx + KEYBOARD.functions]
cmp [ecx + KBDFUNC.strucsize], KBDFUNC.setlights
jbe .unlock
mov ecx, [ecx + KBDFUNC.setlights]
test ecx, ecx
jz .unlock
stdcall ecx, [ebx + KEYBOARD.userdata], dword [kb_lights]
.unlock:
mov ecx, keyboard_list_mutex
call mutex_unlock
xchg eax, ebx
.nothing:
pop ebx
ret 8
; @brief Export function - Delete keyboard
; @param [esp + 4] - pointer on KEYBOARD structure
; @return not return
delete_keyboard:
push ebx
mov ebx, [esp+4+4]
mov ecx, keyboard_list_mutex
call mutex_lock
mov eax, [ebx + KEYBOARD.next]
mov edx, [ebx + KEYBOARD.prev]
mov [eax + KEYBOARD.prev], edx
mov [edx + KEYBOARD.next], eax
call mutex_unlock
mov ecx, [ebx + KEYBOARD.functions]
cmp [ecx + KBDFUNC.strucsize], KBDFUNC.close
jbe .nothing
mov ecx, [ecx + KBDFUNC.close]
test ecx, ecx
jz .nothing
stdcall ecx, [ebx + KEYBOARD.userdata]
.nothing:
pop ebx
ret 4
;---------------------------------------------------------------------
align 4
irq1:
movzx eax, word[thread_count]; top window process
movzx eax, word[WIN_POS + eax*2]
shl eax, BSF sizeof.APPDATA
mov al, [SLOT_BASE + eax + APPDATA.keyboard_mode]
mov [keyboard_mode], al
in al, 0x60
;--------------------------------------
send_scancode:
;DEBUGF 1, "K : Scan code: %x \n", al
mov [keyboard_data], al
; ch = scancode
; cl = ext_code
; bh = 0 - normal key
; bh = 1 - modifier (Shift/Ctrl/Alt)
; bh = 2 - extended code
mov ch, al
cmp al, 0xE0
je @f
cmp al, 0xE1
jne .normal_code
@@:
mov bh, 2
mov [ext_code], al
jmp .writekey
;--------------------------------------
.normal_code:
mov cl, 0
xchg cl, [ext_code]
and al, 0x7F
mov bh, 1
;--------------------------------------
@@:
cmp al, 0x5B
jne @f
cmp cl, 0xE0
jne @f
mov eax, VKEY_LWIN
mov bh, 0
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x5C
jne @f
cmp cl, 0xE0
jne @f
mov eax, VKEY_RWIN
mov bh, 0
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x2A
jne @f
cmp cl, 0xE0
je .writekey
mov eax, VKEY_LSHIFT
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x36
jne @f
cmp cl, 0xE0
je .writekey
mov eax, VKEY_RSHIFT
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x38
jne @f
mov eax, VKEY_LALT
test cl, cl
jz .modifier
mov al, VKEY_RALT
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x1D
jne @f
mov eax, VKEY_LCONTROL
test cl, cl
jz .modifier
mov al, VKEY_RCONTROL
cmp cl, 0xE0
jz .modifier
mov [ext_code], cl
jmp .writekey
;--------------------------------------
@@:
cmp al, 0x3A
jne @f
mov bl, 4
mov eax, VKEY_CAPSLOCK
jmp .no_key.xor
;--------------------------------------
@@:
cmp al, 0x45
jne @f
test cl, cl
jnz .writekey
mov bl, 2
mov eax, VKEY_NUMLOCK
jmp .no_key.xor
;--------------------------------------
@@:
cmp al, 0x46
jne @f
mov bl, 1
mov eax, VKEY_SCRLOCK
jmp .no_key.xor
;--------------------------------------
@@:
xor ebx, ebx
test ch, ch
js .writekey
movzx eax, ch ; plain key
mov bl, [keymap + eax]
mov edx, [kb_state]
test dl, VKEY_CONTROL ; ctrl alt del
jz .noctrlaltdel
test dl, VKEY_ALT
jz .noctrlaltdel
cmp ch, 53h
jne .noctrlaltdel
mov [ctrl_alt_del], 1
call wakeup_osloop
.noctrlaltdel:
test dl, VKEY_CONTROL ; ctrl on ?
jz @f
sub bl, 0x60
@@:
test dl, VKEY_CAPSLOCK ; caps lock on ?
jz .no_caps_lock
test dl, VKEY_SHIFT ; shift on ?
jz .keymap_shif
jmp @f
;--------------------------------------
.no_caps_lock:
test dl, VKEY_SHIFT ; shift on ?
jz @f
.keymap_shif:
mov bl, [keymap_shift + eax]
@@:
test dl, VKEY_ALT ; alt on ?
jz @f
mov bl, [keymap_alt + eax]
@@:
jmp .writekey
;--------------------------------------
.modifier:
test ch, ch
js .modifier.up
or [kb_state], eax
jmp .writekey
;--------------------------------------
.modifier.up:
not eax
and [kb_state], eax
jmp .writekey
;--------------------------------------
.no_key.xor:
mov bh, 0
test ch, ch
js .writekey
xor [kb_state], eax
xor [kb_lights], bl
.writekey:
pushad
; test for system hotkeys
movzx eax, ch
cmp bh, 1
ja .nohotkey
jb @f
xor eax, eax
@@:
mov eax, [hotkey_scancodes + eax*4]
.hotkey_loop:
test eax, eax
jz .nohotkey
mov cl, 0
call hotkey_do_test
jc .hotkey_cont
mov cl, 2
call hotkey_do_test
jc .hotkey_cont
mov cl, 4
call hotkey_do_test
jnc .hotkey_found
.hotkey_cont:
mov eax, [eax]
jmp .hotkey_loop
;--------------------------------------
.hotkey_found:
mov eax, [eax+8]
; put key in buffer for process in slot eax
mov edi, hotkey_buffer
@@:
cmp dword [edi], 0
jz .found_free
add edi, 8
cmp edi, hotkey_buffer+120*8
jb @b
; no free space - replace first entry
mov edi, hotkey_buffer
.found_free:
mov [edi], eax
movzx eax, ch
cmp bh, 1
jnz @f
xor eax, eax
@@:
mov [edi+4], ax
mov eax, [kb_state]
mov [edi+6], ax
cmp [PID_lock_input], dword 0
je .nohotkey
popad
jmp .exit.irq1
;--------------------------------------
.nohotkey:
popad
cmp [keyboard_mode], 0; return from keymap
jne .scancode
test bh, bh
jnz .exit.irq1
test bl, bl
jz .exit.irq1
cmp cl, 0xE0 ; extended keycode
jne @f
cmp ch, 53
jne .dowrite
mov bl, '/'
jmp .dowrite
@@:
cmp ch, 55
jne @f
mov bl, '*'
jmp .dowrite
@@:
cmp ch, 74
jne @f
mov bl, '-'
jmp .dowrite
@@:
cmp ch, 78
jne @f
mov bl, '+'
jmp .dowrite
@@:
test [kb_state], VKEY_NUMLOCK
jz .dowrite
cmp ch, 71
jb .dowrite
cmp ch, 83
ja .dowrite
movzx eax, ch
mov bl, [numlock_map + eax - 71]
jmp .dowrite
;--------------------------------------
.scancode:
mov bl, ch
.dowrite:
movzx eax, byte[KEY_COUNT]
cmp al, 120
jae .exit.irq1
inc eax
mov [KEY_COUNT], al
; store ascii or scancode
mov [KEY_BUFF + eax -1], bl
; store original scancode
add eax, 120+2
push ecx
cmp [keyboard_mode], 0; return from keymap
je @f
xor ch, ch
@@:
mov [KEY_BUFF + eax -1], ch
pop ecx
sub eax, 120+2
.exit.irq1:
ret
;---------------------------------------------------------------------
set_lights:
push ebx esi
mov ecx, keyboard_list_mutex
call mutex_lock
mov esi, keyboards
.loop:
mov esi, [esi + KEYBOARD.next]
cmp esi, keyboards
jz .done
mov eax, [esi + KEYBOARD.functions]
cmp dword [eax], KBDFUNC.setlights
jbe .loop
mov eax, [eax + KBDFUNC.setlights]
test eax, eax
jz .loop
stdcall eax, [esi + KEYBOARD.userdata], dword [kb_lights]
jmp .loop
.done:
mov ecx, keyboard_list_mutex
call mutex_unlock
pop esi ebx
ret
ps2_set_lights:
stdcall disable_irq, 1
mov al, 0xED
call kb_write_wait_ack
mov al, [esp+8]
call kb_write_wait_ack
stdcall enable_irq, 1
ret 8
;// mike.dld ]
proc check_lights_state_has_work?
mov al, [kb_lights]
cmp al, [old_kb_lights]
ret
endp
check_lights_state:
call check_lights_state_has_work?
jz .nothing
mov [old_kb_lights], al
call set_lights
.nothing:
ret
;---------------------------------------------------------------------
iglobal
numlock_map db '789-456+1230.'
endg
;---------------------------------------------------------------------
align 4
kb_write_wait_ack:
push ecx edx
mov dl, al
mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's
.wait_output_ready:
in al, 0x64
test al, 2
jz @f
loop .wait_output_ready
mov ah, 1
jmp .nothing
@@:
mov al, dl
out 0x60, al
mov ecx, 0xfffff; last 0xffff, new value in view of fast CPU's
.wait_ack:
in al, 0x64
test al, 1
jnz @f
loop .wait_ack
mov ah, 1
jmp .nothing
@@:
in al, 0x60
xor ah, ah
.nothing:
pop edx ecx
ret
;-----------------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 66 sys function. ;;
;; in eax=66,ebx in [0..5],ecx,edx ;;
;; out eax ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
iglobal
align 4
f66call:
dd sys_process_def.1 ; 1 = set keyboard mode
dd sys_process_def.2 ; 2 = get keyboard mode
dd sys_process_def.3 ; 3 = get keyboard ctrl, alt, shift
dd sys_process_def.4 ; 4 = set system-wide hotkey
dd sys_process_def.5 ; 5 = delete installed hotkey
dd sys_process_def.6 ; 6 = disable input, work only hotkeys
dd sys_process_def.7 ; 7 = enable input, opposition to f.66.6
endg
;-----------------------------------------------------------------------------
align 4
sys_process_def:
dec ebx
cmp ebx, 7
jae .not_support ;if >=8 then or eax,-1
mov edi, [current_slot]
jmp dword [f66call + ebx*4]
.not_support:
or [esp + SYSCALL_STACK.eax], -1
ret
;-----------------------------------------------------------------------------
align 4
.1:
mov [edi + APPDATA.keyboard_mode], cl
ret
;-----------------------------------------------------------------------------
align 4
.2: ; 2 = get keyboard mode
movzx eax, byte [edi + APPDATA.keyboard_mode]
mov [esp + SYSCALL_STACK.eax], eax
ret
;-----------------------------------------------------------------------------
align 4
.3: ;3 = get keyboard ctrl, alt, shift
mov eax, [kb_state]
mov [esp + SYSCALL_STACK.eax], eax
ret
;-----------------------------------------------------------------------------
align 4
.4:
mov edi, [current_slot_idx]
mov eax, hotkey_list
@@:
cmp dword [eax + 8], 0
jz .found_free
add eax, 16
cmp eax, hotkey_list+16*256
jb @b
mov dword [esp + SYSCALL_STACK.eax], 1
ret
.found_free:
mov [eax + 8], edi
mov [eax + 4], edx
movzx ecx, cl
lea ecx, [hotkey_scancodes+ecx*4]
mov edx, [ecx]
mov [eax], edx
mov [ecx], eax
mov [eax + 12], ecx
test edx, edx
jz @f
mov [edx + 12], eax
@@:
and dword [esp + SYSCALL_STACK.eax], 0
ret
;-----------------------------------------------------------------------------
align 4
.5:
mov edi, [current_slot_idx]
movzx ebx, cl
lea ebx, [hotkey_scancodes+ebx*4]
mov eax, [ebx]
.scan:
test eax, eax
jz .notfound
cmp [eax + 8], edi
jnz .next
cmp [eax + 4], edx
jz .found
.next:
mov eax, [eax]
jmp .scan
.notfound:
mov dword [esp + SYSCALL_STACK.eax], 1
ret
.found:
mov ecx, [eax]
jecxz @f
mov edx, [eax + 12]
mov [ecx + 12], edx
@@:
mov ecx, [eax + 12]
mov edx, [eax]
mov [ecx], edx
xor edx, edx
mov [eax + 4], edx
mov [eax + 8], edx
mov [eax + 12], edx
mov [eax], edx
mov [esp + SYSCALL_STACK.eax], edx
ret
;-----------------------------------------------------------------------------
align 4
.6:
pushfd
cli
mov eax, [PID_lock_input]
test eax, eax
jnz @f
; get current PID
mov eax, [current_slot]
mov eax, [eax + APPDATA.tid]
; set current PID for lock input
mov [PID_lock_input], eax
@@:
popfd
ret
;-----------------------------------------------------------------------------
align 4
.7:
mov eax, [PID_lock_input]
test eax, eax
jz @f
; get current PID
mov ebx, [current_slot]
mov ebx, [ebx + APPDATA.tid]
; compare current lock input with current PID
cmp ebx, eax
jne @f
xor eax, eax
mov [PID_lock_input], eax
@@:
ret
;-----------------------------------------------------------------------------
uglobal
PID_lock_input dd 0x0
endg
;-----------------------------------------------------------------------------
align 4
; @brief System function 2 - Get pressed key
; @param eax = 2- number function
; @return eax = 1 - buffer empty, else
; al = 0, ah = code pressed key,
; 16-23 bits - scancode pressed key(in ASCII mode)
; if al=2 ah=scancode pressed key, 16-31 bits - state control keys
sys_getkey:
mov [esp + SYSCALL_STACK.eax], dword 1
; test main buffer
mov ebx, [current_slot_idx] ; TOP OF WINDOW STACK
movzx ecx, word [WIN_STACK + ebx * 2]
mov edx, [thread_count]
cmp ecx, edx
jne .finish
cmp [KEY_COUNT], byte 0
je .finish
movzx ax, byte [KEY_BUFF + 120 + 2]
shl eax, 8
mov al, byte [KEY_BUFF]
shl eax, 8
push eax
dec byte [KEY_COUNT]
and byte [KEY_COUNT], 127
movzx ecx, byte [KEY_COUNT]
add ecx, 2
mov eax, KEY_BUFF + 1
mov ebx, KEY_BUFF
call memmove
add eax, 120 + 2
add ebx, 120 + 2
call memmove
pop eax
;--------------------------------------
align 4
.ret_eax:
mov [esp + SYSCALL_STACK.eax], eax
ret
;--------------------------------------
align 4
.finish:
; test hotkeys buffer
mov ecx, hotkey_buffer
;--------------------------------------
align 4
@@:
cmp [ecx], ebx
jz .found
add ecx, 8
cmp ecx, hotkey_buffer + 120 * 8
jb @b
ret
;--------------------------------------
align 4
.found:
mov ax, [ecx + 6]
shl eax, 16
mov ah, [ecx + 4]
mov al, 2
and dword [ecx + 4], 0
and dword [ecx], 0
jmp .ret_eax
;------------------------------------------------------------------------------