All pastes #126179 Raw Edit

PS/2 devices driver

public text v1 · immutable
#126179 ·published 2006-08-11 06:45 UTC
rendered paste body
; **********************************************************

;	Name: PS/2 Keyboard & Mouse driver
;       Type: Virtual Device Driver
;	Autor: Toaster Burger
;	Version: 1.00

; **********************************************************

[bits 32]
CPU 386

%define	Type_User
%include "interface.asm"

%define	Char(number2)	number2
%define	Param(number)	[ebp+16 + 4*(number-1)]
%define	Param1	[ebp+16 + 4*0]
%define	Param2	[ebp+16 + 4*1]
%define	Param3	[ebp+16 + 4*2]
%define	Param4	[ebp+16 + 4*3]


%macro	ack 0.nolist

ack_test:
in al,60h
cmp al,0FAh
jne ack_test

%endmacro



%macro	kb_comm 2.nolist

; %2 = command
; %1 = error label

mov ah,%2
call kbCommand
jc %1

%endmacro



%macro	kb_comm_low 2.nolist

; %2 = command
; %1 = error label

mov ah,%2
call kbCommand_low
jc %1

%endmacro



%macro	kb_read 1.nolist

; %1 = error label

call kbRead
jc %1

%endmacro



%macro	kb_write 2.nolist

; %1 = byte to write
; %2 = error label

mov ah,%2
call kbWrite
jc %1

%endmacro



%macro	key_press 1.nolist

; PressedKeys
;   bit 0: shift left
;   bit 1: ctrl left
;   bit 2: alt (unused)
;   bit 3: del (unused)
;   bit 4: caps lock
;   bit 5: ctrl right
;   bit 6: ctrl (unused)
;   bit 7: shift right
;   bit 8: shift (unused)
; for future: test with %if the code and set the unused (alt, ctrl, shift) values

  ; some definition... take care of it...
  %define KeyEvent		[ebp-8]

  
  ; if key_press(%1) (= key was down and key is now down) then exit
  ;   in order to do not handle typematic codes
  
  test [edx + PressedKeys],dword %1
  jz %%continue
  
  cmp KeyEvent,word WM_KEYDOWN
  je Keyboard_Handler_Exit
  
  ; if here key event is key up, so clear the bit
  clear_bit [edx + PressedKeys], %1
  jmp %%exit
  
  %%continue:
  or [edx + PressedKeys],dword %1
  
  %%exit:

%endmacro


jmp dword initialise

jmp dword Switch_Key_Table
jmp dword Set_Scroll_led






Switch_Key_Table:

; SPI Set_Keyboard_Layout, Table

; Table = "eu" for europe, "us" for american keyboard layout

Enter_System
call Get_address


cmp Param1,dword 'eu'
je Switch_Key_Table_eu

cmp Param1,dword 'us'
je Switch_Key_Table_us

jmp Switch_Key_Table_Exit


Switch_Key_Table_eu:
mov [edx + Take_Key_Table],dword 0
jmp Switch_Key_Table_Exit


Switch_Key_Table_us:
mov [edx + Take_Key_Table],dword 1


Switch_Key_Table_Exit:
Leave_System

ret









Set_Scroll_led:

; undocumented

Enter_System
call Get_address


; clear the led bit (default)
clear_bit [edx + Led_locks], 1

; only bit 0 is significant in the Param1
mov eax,Param1
or eax,1
or [edx + Led_locks],eax

; set the (maybe) new leds
call Set_leds


Leave_System

ret









Get_Key_states:

; SPI Get_Key_states

; return = record of
;   {
;      PressedKeys
;         bit 0: shift left
;         bit 1: ctrl left
;         bit 2: alt (unused)
;         bit 3: del (unused)
;         bit 4: caps lock
;         bit 5: ctrl right
;         bit 6: ctrl (unused)
;         bit 7: shift right
;         bit 8: shift (unused)
;         bit 9: rollen
;         bit 10: num lock
;      
;      CapsLock (key state)
;      NumLock (key state)
;      Rollen (key state)
;      Alt_Gr (key state)
;      
;      Led_locks
;      Typematic_rate
;   }

Enter_System
call Get_address


API New, 6
mov edi,eax

mov ax,[edx + PressedKeys]
stosw

mov al,[edx + CapsLock]
stosb

mov al,[edx + NumLock]
stosb

mov al,[edx + Rollen]
stosb

mov al,[edx + Alt_Gr]
stosb

mov al,[edx + Led_locks]
stosb

mov al,[edx + Typematic_rate]
stosb


mov eax,edi
sub eax,6
Leave_System

ret









Return_last_key:

; SPI Return_last_key

; return = record of
;   {
;      
;      LastKey
;      LastKeyExt
;      LastKeyEvent
;      
;   }

Enter_System
call Get_address


API New, 12
mov edi,eax

mov eax,[edx + LastKey]
stosd
mov eax,[edx + LastKeyExt]
stosd
mov eax,[edx + LastKeyEvent]
stosd


mov eax,edi
sub eax,12
Leave_System

ret









Resend_last_key:

; SPI Resend_last_key

; resends the last key to the user, as it was

Enter_System
call Get_address


; send the key to the top (active) window
mov esi,Top_Window
mov edi,TWC_link.Handle(esi)
API Send_Message, TWC_link.ProcessHandle(esi), edi, [edx + LastKeyEvent], [edx + LastKey], [edx + LastKeyExt]


Leave_System

ret









Retrieve_last_key:

; SPI Retrieve_last_key

; given direct to the keyboard, resend last scancode

Enter_System
call Get_address


; Keyboard command
;   FEh  sngl   resend last scancode

kb_comm_low  Public_Keyboard_Error, 0feh


xor eax,eax
Leave_System

ret





Public_Keyboard_Error:

mov eax,Keyboard_abort

Leave_System

ret










Get_address:

mov edx,dword 0FFFF00FFh

; other method:
;    set the start address
;    mov edx,[Global_Offset_Table + 1*16 + 7]

ret







initialise:

; Param1 = base of vxd

Enter_System
pushfd
cli

mov edx,Param1
mov [edx + Get_address + 1],edx



; ---- keyboard control ----
Keyboard_Control:

; link the IRQ 1 with the Keyboard Handler
mov ebx,Param1
add ebx,Keyboard_Handler
API Set_IRQ, 1, ebx


; set the Scancode Set
kb_comm  Keyboard_init_abort, 0f0h
kb_write Keyboard_init_abort, 1


; set the leds
call Set_leds
jc Keyboard_init_abort


; set the Typematic rate
kb_comm  Keyboard_init_abort, 0f3h
kb_write Keyboard_init_abort, [edx + Typematic_rate]


; enable the Keyboard and start scanning
kb_comm  Keyboard_init_abort, 0f4h


; set default key values
mov [edx + CapsLock],byte 0
mov [edx + NumLock],byte 0
mov [edx + Rollen],byte 0
mov [edx + PressedKeys],byte 0
mov [edx + Extended_key],byte 0
mov [edx + Keyboard],dword 1



; ---- mouse control ----
Mouse_Control:

; link the IRQ 12 with the Mouse Handler
mov ebx,Param1
add ebx,Mouse_Handler
API Set_IRQ, 12, ebx


; enable the mouse port
kb_comm  Mouse_abort, 0a8h


; reset the mouse (100 samples/sec, 4 counts/mm, 1:1)
kb_comm  Mouse_abort, 0d4h
kb_comm  Mouse_abort, 0f6h


; enable data reporting
kb_comm  Mouse_abort, 0d4h
kb_comm  Mouse_abort, 0f4h

%ifdef homix_os_use
kb_comm  Mouse_abort, 0a8h
kb_comm  Mouse_abort, 020h
kb_comm  Mouse_abort, 060h
kb_comm  Mouse_abort, 0d4h
kb_comm  Mouse_abort, 0f4h
%endif


; mark the Mouse as available
mov [edx+Mouse],dword 1



Connect_Exit:
popfd
Leave_System
clc

ret




Keyboard_init_abort:

; create a timer ???

; resume the mouse mounting
jmp Mouse_Control




Mouse_abort:

; create a timer ???

jmp Connect_Exit








Keyboard_Handler:

; define the variables
%define	ScanCode		[ebp-4]
%define	KeyEvent		[ebp-8]
%define	ExtCode			[ebp-12]
%define	System_Stack		12

Enter_driver
call Get_address


xor eax,eax
mov KeyEvent,dword 0
mov ScanCode,dword 0
mov ExtCode,dword 0


; check if there is a scancode
in al,64h
test al,00000001b
jz Keyboard_Handler_Exit

; input the scancode
in al,60h


; are one (E0h) or two (E1h) scancodes following ?
cmp al,0E0h
je Keyboard_Handler_E?h
cmp al,0E1h
je Keyboard_Handler_E?h
cmp al,0FAh
je Keyboard_Handler_Exit

; if extended jump
cmp [edx + Extended_key],byte 1
je Take_Extended_Key_Table



; set the KeyEvent
;    If EventCode = 0 then 
;      KeyEvent = KEY_DOWN
;    Else 
;      KeyEvent = KEY_UP;
Set_Key_Event:
test al,10000000b
jz Keyboard_Handler_down

Keyboard_Handler_up:
mov KeyEvent,dword WM_KEYUP
jmp Keyboard_Handler_ok

Keyboard_Handler_down:
mov KeyEvent,dword WM_KEYDOWN

Keyboard_Handler_ok:
; only the scancode is significant
and eax,01111111b




; take the correct Key Tables for ascii keys
cmp [edx + Take_Key_Table],byte 0
jne Take_Key_Table_american



Take_Key_Table_europe:

; sort out ascii keys
check_bounds 2, 13, 2, Take_Key_Table_europe_ascii
check_bounds 16, 27, 2+2, Take_Key_Table_europe_ascii
check_bounds 30, 41, 2+2+2, Take_Key_Table_europe_ascii
check_bounds 43, 53, 2+2+2+1, Take_Key_Table_europe_ascii
check_bounds 86, 86, 2+2+2+1+32, Take_Key_Table_europe_ascii

; sort out imm keys
check_bounds 0, 1, 0, Take_Key_Table_imm
check_bounds 14, 15, 12, Take_Key_Table_imm
check_bounds 28, 28, 12*2, Take_Key_Table_imm
check_bounds 57, 57, 12*2+28, Take_Key_Table_imm
check_bounds 59, 68, 12*2+28+1, Take_Key_Table_imm
check_bounds 87, 88, 12*2+28+1+18, Take_Key_Table_imm

; sort out numblock keys
check_bounds 69, 69, 0, Take_Key_Table_num_lock
check_bounds 71, 83, 71, Take_Key_Table_numblock
check_bounds 55, 55, 0, Take_Key_Table_numblock_mul

; sort out direct translation keys
check_bounds 58, 58, 0, Take_Key_Table_caps_lock
check_bounds 29, 29, 0, Take_Key_Table_ctrl_left
check_bounds 42, 42, 0, Take_Key_Table_shift_left
check_bounds 54, 54, 0, Take_Key_Table_shift_right
check_bounds 56, 56, 0, Take_Key_Table_alt_left
check_bounds 70, 70, 0, Take_Key_Table_rollen

; store the unknown key for intelli genuine ToasterOS use
mov [edx + UnknownKey],al
mov bl,KeyEvent
mov [edx + UnknownKey + 1],bl
jmp Keyboard_Handler_Exit




Take_Key_Table_american:

; sort out ascii keys
check_bounds 2, 13, 2, Take_Key_Table_american_ascii
check_bounds 16, 27, 2+2, Take_Key_Table_american_ascii
check_bounds 30, 41, 2+2+2, Take_Key_Table_american_ascii
check_bounds 43, 53, 2+2+2+1, Take_Key_Table_american_ascii
check_bounds 86, 86, 2+2+2+1+32, Take_Key_Table_american_ascii

; sort out imm keys
check_bounds 0, 1, 0, Take_Key_Table_imm
check_bounds 14, 15, 12, Take_Key_Table_imm
check_bounds 28, 28, 12*2, Take_Key_Table_imm
check_bounds 57, 57, 12*2+28, Take_Key_Table_imm
check_bounds 59, 68, 12*2+28+1, Take_Key_Table_imm
check_bounds 87, 88, 12*2+28+1+18, Take_Key_Table_imm

; sort out numblock keys
check_bounds 69, 69, 0, Take_Key_Table_num_lock
check_bounds 71, 83, 71, Take_Key_Table_numblock
check_bounds 55, 55, 0, Take_Key_Table_numblock_mul

; sort out direct translation keys
check_bounds 58, 58, 0, Take_Key_Table_caps_lock
check_bounds 29, 29, 0, Take_Key_Table_ctrl_left
check_bounds 42, 42, 0, Take_Key_Table_shift_left
check_bounds 54, 54, 0, Take_Key_Table_shift_right
check_bounds 56, 56, 0, Take_Key_Table_alt_left
check_bounds 70, 70, 0, Take_Key_Table_rollen

; store the unknown key for intelli genuine ToasterOS use
mov [edx + UnknownKey],al
mov bl,KeyEvent
mov [edx + UnknownKey + 1],bl
jmp Keyboard_Handler_Exit




Take_Extended_Key_Table:
mov [edx + Extended_key],byte 0

; sort out (extra) break codes, AAh and 2Ah are not significant
check_bounds 170, 170, 0, Keyboard_Handler_Exit
check_bounds 42, 42, 0, Keyboard_Handler_Exit


; suppose make code
mov KeyEvent,dword WM_KEYDOWN

; sort out middle block keys
check_bounds 71, 73, 71, Take_Key_Table_middle_block
check_bounds 75, 75, 71+1, Take_Key_Table_middle_block
check_bounds 77, 77, 71+1+1, Take_Key_Table_middle_block
check_bounds 79, 83, 71+1+1+1, Take_Key_Table_middle_block

; sort out direct translation keys
check_bounds 53, 53, 0, Take_Key_Table_numblock_div
check_bounds 55, 55, 0, Take_Key_Table_print_screen
check_bounds 56, 56, 0, Take_Key_Table_alt_gr
check_bounds 84, 84, 0, Take_Key_Table_print_screen
check_bounds 86, 86, 0, Set_Key_Event
check_bounds 91, 91, 0, Take_Key_Table_left_win
check_bounds 92, 92, 0, Take_Key_Table_right_win
check_bounds 93, 93, 0, Take_Key_Table_popup


; suppose break code
mov KeyEvent,dword WM_KEYUP

; sort out middle block keys
check_bounds 198, 198, 0, Take_Key_Table_pause
check_bounds 199, 201, 199, Take_Key_Table_middle_block
check_bounds 203, 203, 199+1, Take_Key_Table_middle_block
check_bounds 205, 205, 199+1+1, Take_Key_Table_middle_block
check_bounds 207, 211, 199+1+1+1, Take_Key_Table_middle_block

; sort out direct translation keys
check_bounds 181, 181, 0, Take_Key_Table_numblock_div
check_bounds 183, 183, 0, Take_Key_Table_print_screen
check_bounds 184, 184, 0, Take_Key_Table_alt_gr
check_bounds 212, 212, 0, Take_Key_Table_print_screen
check_bounds 214, 214, 0, Set_Key_Event
check_bounds 219, 219, 0, Take_Key_Table_left_win
check_bounds 220, 220, 0, Take_Key_Table_right_win
check_bounds 221, 221, 0, Take_Key_Table_popup


; the most special pause key
Test_Key_Pause_scan_code1:
cmp al,01Dh
jne Test_Key_Pause_scan_code3
mov [edx + Extended_key],byte 1
jmp Keyboard_Handler_Exit

; the 2nd code 45h won't be test, because if its one of the make code, the next e0h
; activates this handler by default

Test_Key_Pause_scan_code3:
cmp al,09Dh
jne Test_Key_Pause_scan_code4
mov [edx + Extended_key],byte 1
jmp Keyboard_Handler_Exit

Test_Key_Pause_scan_code4:
cmp al,197
je Take_Key_Table_pause


; store the unknown key for intelli genuine ToasterOS use
mov [edx + UnknownKey],al
mov bl,KeyEvent
mov [edx + UnknownKey + 1],bl
jmp Keyboard_Handler_Exit





Take_Key_Table_europe_ascii:
; ascii means keys which are visible

cmp [edx + Alt_Gr],byte 1
je Take_Key_Table_europe_ascii_alt_gr

cmp [edx + CapsLock],byte 1
je Take_Key_Table_europe_ascii_shift


Take_Key_Table_europe_ascii_normal:
movzx ebx,byte [edx + Key_Table_europe_ascii + eax]
jmp Send_Key


Take_Key_Table_europe_ascii_shift:
movzx ebx,byte [edx + Key_Table_europe_ascii_shift + eax]
jmp Send_Key


Take_Key_Table_europe_ascii_alt_gr:
check_bounds 3, 4, 3, Take_Key_Table_europe_ascii_alt_gr_set
check_bounds 8, 12, 3*2, Take_Key_Table_europe_ascii_alt_gr_set
check_bounds 16, 16, 3*3, Take_Key_Table_europe_ascii_alt_gr_set
check_bounds 18, 18, 3*3+1, Take_Key_Table_europe_ascii_alt_gr_set
check_bounds 27, 27, 3*3+1+8, Take_Key_Table_europe_ascii_alt_gr_set
check_bounds 50, 50, 3*3+1+8+22, Take_Key_Table_europe_ascii_alt_gr_set
check_bounds 86, 86, 3*3+1+8+22+35, Take_Key_Table_europe_ascii_alt_gr_set
jmp Keyboard_Handler_Exit


Take_Key_Table_europe_ascii_alt_gr_set:
movzx ebx,byte [edx + Key_Table_europe_ascii_alt_gr + eax]
jmp Send_Key




Take_Key_Table_american_ascii:
; ascii means keys which are visible

cmp [edx + CapsLock],byte 1
je Take_Key_Table_american_ascii_shift

Take_Key_Table_american_ascii_normal:
movzx ebx,byte [edx + Key_Table_american_ascii + eax]
jmp Send_Key

Take_Key_Table_american_ascii_shift:
movzx ebx,byte [edx + Key_Table_american_ascii_shift + eax]
jmp Send_Key




Take_Key_Table_imm:
; imm means keys which are immediately to translate and send

movzx ebx,byte [edx + Key_Table_imm + eax]
jmp Send_Key



Take_Key_Table_numblock:
; numblock means keys of the numblock

cmp [edx + NumLock],byte 1
je Take_Key_Table_numblock_num

cmp [edx + NumLock],byte 2
je Take_Key_Table_numblock_tec

movzx ecx,byte [edx + Key_Table_numblock_tec + eax]
mov ExtCode,ecx
movzx ebx,byte [edx + Key_Table_numblock + eax]
jmp Send_Key

Take_Key_Table_numblock_tec:
movzx ebx,byte [edx + Key_Table_numblock_tec + eax]
mov ExtCode,ebx
jmp Send_Key

Take_Key_Table_numblock_num:
movzx ecx,byte [edx + Key_Table_numblock_tec + eax]
mov ExtCode,ecx
movzx ebx,byte [edx + Key_Table_numblock_num + eax]
jmp Send_Key



Take_Key_Table_numblock_mul:
; key = mul (some part of the direct translation keys)

mov ebx,'*'
mov ExtCode,dword VK_MULTIPLY
jmp Send_Key



Take_Key_Table_numblock_div:
; key = div (part of the direct translation keys)

mov ebx,'/'
mov ExtCode,dword VK_DIVIDE
jmp Send_Key



Take_Key_Table_num_lock:
; key = num lock (some part of the direct translation keys)

; if key event != key first then exit
cmp KeyEvent,word WM_KEYDOWN
jne Take_Key_Table_num_lock_clearbit
key_press 10000000000b

invert_bool byte [edx + NumLock]
invert_bit [edx + Led_locks], 10b
call Set_leds
jmp Keyboard_Handler_Exit

Take_Key_Table_num_lock_clearbit:
clear_bit [edx + PressedKeys], 10000000000b
jmp Keyboard_Handler_Exit



Take_Key_Table_caps_lock:
; key = caps lock (part of the direct translation keys)

; if key event != key first then exit
cmp KeyEvent,word WM_KEYDOWN
jne Take_Key_Table_caps_lock_clearbit
key_press 10000b

invert_bool byte [edx + CapsLock]
invert_bit [edx + Led_locks], 100b
call Set_leds
jmp Keyboard_Handler_Exit


Take_Key_Table_caps_lock_clearbit:
clear_bit [edx + PressedKeys], 10000b
jmp Keyboard_Handler_Exit



Take_Key_Table_rollen:
; rollen = scroll lock

; if key event <> key first then exit
cmp KeyEvent,word WM_KEYDOWN
jne Take_Key_Table_rollen_clearbit
key_press 1000000000b

invert_bool byte [edx + Rollen]
invert_bit [edx + Led_locks], 1b
call Set_leds
jmp Keyboard_Handler_Exit

Take_Key_Table_rollen_clearbit:
clear_bit [edx + PressedKeys], 1000000000b
jmp Keyboard_Handler_Exit



Take_Key_Table_ctrl_left:
; key = ctrl left (part of the direct translation keys)
;   make and break code (bit 1: ctrl left)

key_press 10b
mov ExtCode,dword VK_LCONTROL
mov ebx,VK_CONTROL
jmp Send_Key



Take_Key_Table_shift_left:
; key = shift left (part of the direct translation keys)
;   make and break code (bit 0: shift left)

key_press 1b
invert_bool byte [edx + CapsLock]
mov ExtCode,dword VK_LSHIFT
mov ebx,VK_SHIFT
jmp Send_Key



Take_Key_Table_shift_right:
; key = shift right (part of the direct translation keys)
;   make and break code (bit 7: shift right)

key_press 10000000b
invert_bool byte [edx + CapsLock]
mov ExtCode,dword VK_RSHIFT
mov ebx,VK_SHIFT
jmp Send_Key



Take_Key_Table_alt_left:
; key = alt left (part of the direct translation keys)
;   make and break code (bit 2: alt left)

key_press 100b
mov ExtCode,dword VK_LMENU
mov ebx,VK_MENU
jmp Send_Key



Take_Key_Table_alt_gr:
;   only make code

; alt gr = alt (for american)
cmp [edx + Take_Key_Table],byte 0
jne Take_Key_Table_alt_left

invert_bool byte [edx + Alt_Gr]
jmp Keyboard_Handler_Exit



Take_Key_Table_print_screen:

; copy screen to clipboard
;   - ?

mov ebx,VK_SNAPSHOT
jmp Send_Key



Take_Key_Table_left_win:

; show the win 3.1 Toolbar/menu
;   - ?

mov ebx,VK_LWIN
jmp Send_Key



Take_Key_Table_right_win:

; show the win 3.1 Toolbar/menu
;   - ?

mov ebx,VK_RWIN
jmp Send_Key



Take_Key_Table_popup:

mov ebx,VK_APPS
jmp Send_Key



Take_Key_Table_pause:

; idle the system
;   - ?

mov ebx,VK_PAUSE
jmp Send_Key



Take_Key_Table_middle_block:
; middle block = keys of the middle block

movzx ebx,byte [edx + Key_Table_middle_block + eax]
jmp Send_Key





Send_Key:
mov ScanCode,ebx
mov [edx + LastKey],ebx
mov ecx,ExtCode
mov [edx + LastKeyExt],ecx
mov ecx,KeyEvent
mov [edx + LastKeyEvent],ecx

; if key <> 0 then send_key
or ebx,ebx
jz Keyboard_Handler_Exit

; send the key to the top (active) window
mov esi,Top_Window
mov edi,TWC_link.Handle(esi)
API Send_Message, TWC_link.ProcessHandle(esi), edi, KeyEvent, ScanCode, ExtCode
  
jmp Keyboard_Handler_Exit



Keyboard_Handler_E?h:
  mov [edx + Extended_key],byte 1
jmp Keyboard_Handler_Exit



Keyboard_Handler_Exit:
Leave_driver
EOI_Master

iret






Set_leds:


; sets the leds by means of the led locks
kb_comm_low Set_leds_Exit, 0edh
kb_write    Set_leds_Exit, [edx + Led_locks]


Set_leds_Exit:

ret








kbWrite:

; a public OS developer routine to write something to the Keyboard
; input(ah) = byte to send
; return = 0 if successful, otherwise error (abort)


; test for a transmit timeout
mov ecx,0FFFFh

Test_loop_1:
in al,64h
test al,00100000b
jz Test_loop_1_ok
loop Test_loop_1

stc
jmp kbWrite_Exit

Test_loop_1_ok:


; test if the input buffer is full
mov ecx,0FFFFh

Test_loop_2:
in al,64h
test al,00000010b
jz Test_loop_2_ok
loop Test_loop_2

stc
jmp kbWrite_Exit

Test_loop_2_ok:


; send the byte out to port 60h
mov al,ah
out 60h,al
clc


kbWrite_Exit:

ret







kbRead:

; a public OS developer routine to read something of the Keyboard
; return = read byte


; test if the output buffer is full
mov ecx,0FFFFh

Test_loop_3:
in al,64h
test al,00000001b
jz Test_loop_3_ok
loop Test_loop_3

stc
jmp kbWrite_Exit

Test_loop_3_ok:


; delay for a short time
delay 32


; input the byte
in al,60h


ret







kbCommand:

; a public OS developer routine to send a command to the Keyboard
; input(ah) = command to send


; test if the input buffer is full
mov ecx,0FFFFh

Test_loop_4:
in al,64h
test al,00000010b
jz Test_loop_4_ok
loop Test_loop_4

stc
jmp kbWrite_Exit

Test_loop_4_ok:


; send the command
mov al,ah
out 64h,al


; test if the command acception
mov ecx,0FFFFh

Test_loop_5:
in al,64h
test al,00000010b
jz Test_loop_5_ok
loop Test_loop_5

stc
jmp kbWrite_Exit

Test_loop_5_ok:
clc


ret







kbCommand_low:

; a public OS developer routine to send a command to the Keyboard
; input(ah) = command to send to port 60h instead of 64h


; test if the input buffer is full
mov ecx,0FFFFh

Test_loop_6:
in al,64h
test al,00000010b
jz Test_loop_6_ok
loop Test_loop_6

stc
jmp kbWrite_Exit

Test_loop_6_ok:


; send the command (at this time to port 60h)
mov al,ah
out 60h,al


; test if the command acception
mov ecx,0FFFFh

Test_loop_7:
in al,64h
test al,00000010b
jz Test_loop_7_ok
loop Test_loop_7

stc
jmp kbWrite_Exit

Test_loop_7_ok:
clc


ret








Mouse_Handler:

; define the variables
%define	Buttons			[ebp-1]
%define	Movement_X		[ebp-2]
%define	Movement_Y		[ebp-3]
%define	System_Stack		3

Enter_driver
call Get_address


; check if there are the 3 bytes
in al,64h
test al,00000001b
jz Mouse_Handler_Exit


; store the 3 bytes (Buttons, X Movement, Y Movement)
in al,60h
mov Buttons,al
in al,60h
mov Movement_X,al
in al,60h
mov Movement_Y,al


; update the position
API Update_Cursor_position, Buttons, Movement_X, Movement_Y


Mouse_Handler_Exit:
Leave_driver
EOI_Slave

iret







Mouse_Handler_intelli:

; currently not supported

iret







; Keyboard and Mouse are boolean values if they are available
Keyboard	dd	0
Mouse		dd	0

; Keyboard state
Typematic_rate	dd	00101000b
Led_locks	dd	000b

; key states
CapsLock	dd	0
NumLock		dd	0
Rollen		dd	0
Alt_Gr		dd	0

PressedKeys	dd	0
UnknownKey	dd	0
Extended_key	dd	0
LastKey		dd	0
LastKeyExt	dd	0
LastKeyEvent	dd	0

; 0 = europe, 1 = american
Take_Key_Table	dd	0


; the Key tables (for europe keyboards)
Key_Table_europe_ascii		db	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'ß', '´', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 'ü', '+', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä', '^', '#', 'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', '<'
Key_Table_europe_ascii_shift	db	'!', '"', '§', '$', '%', '&', '/', '(', ')', '=', '?', '`', 'Q', 'W', 'E', 'R', 'T', 'Z', 'I', 'I', 'O', 'P', 'Ü', '*', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä', '°', 27h, 'Y', 'X', 'C', 'V', 'B', 'N', 'M', ';', ':', '_', '>'
Key_Table_europe_ascii_alt_gr	db	'²', '³', '{', '[', ']', '}', '\', '@', '€', '~', 'µ', '|'

; the Key tables (for american keyboards)
Key_Table_american_ascii	db	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '-', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 27h, '`', '\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\'
Key_Table_american_ascii_shift	db	'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 'Q', 'W', 'E', 'R', 'T', 'Y', 'I', 'I', 'O', 'P', '{', '}', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '|'

; the Key tables (for europe & american keyboards)
Key_Table_imm			db	VK_NULL, VK_ESCAPE, VK_BACK, VK_TAB, VK_RETURN, VK_SPACE, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12
Key_Table_numblock		db	VK_HOME, VK_UP, VK_PRIOR, '-', VK_LEFT, VK_NUMPAD5, VK_RIGHT, '+', VK_END, VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE
Key_Table_numblock_num		db	'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', VK_DELETE
Key_Table_numblock_tec		db	VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_SUBTRACT, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_ADD, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_DELETE
Key_Table_middle_block		db	VK_HOME, VK_UP, VK_PRIOR, VK_LEFT, VK_RIGHT, VK_END, VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE




; bits of Led_locks (0=Off 1=On):
;   0 = Scroll Lock
;   1 = Num Lock
;   2 = Caps Lock
;   rest = 0


; bits of Typematic_rate
;   bit 0 -> 4: rate. Timings:
;     0: 30 keys/sec   10: 10
;     1: 26.7	       13: 9
;     2: 24	       16: 7.5
;     4: 20	       20: 5
;     8: 15	       31: 2
;     
;   bit 5 & 6: pause before repeat:
;     0: 250 ms
;     1: 500
;     2: 750
;     4: 1000
;     
;   bit 7: Always 0


; PressedKeys
;   bit 0: shift left
;   bit 1: ctrl left
;   bit 2: alt (unused)
;   bit 3: del (unused)
;   bit 4: caps lock
;   bit 5: ctrl right
;   bit 6: ctrl (unused)
;   bit 7: shift right
;   bit 8: shift (unused)
;   bit 9: rollen
;   bit 10: num lock