1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; Includes source code by Kulakov Vladimir Gennadievich. ;; |
8,375 → 8,320 |
;; 02.12.2009 <Lrz> ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
;driver sceletone |
format PE DLL native |
entry START |
|
format MS COFF |
CURRENT_API = 0x0200 |
COMPATIBLE_API = 0x0100 |
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
|
DEBUG equ 0 |
__DEBUG__ = 1 |
__DEBUG_LEVEL__ = 2 |
|
include 'proc32.inc' |
include 'imports.inc' |
section '.flat' readable writable executable |
|
API_VERSION equ 5 ;debug |
include '../proc32.inc' |
include '../struct.inc' |
include '../macros.inc' |
include '../fdo.inc' |
|
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
; Serial data packet format: |
; D6 D5 D4 D3 D2 D1 D0 |
; 1st byte 1 LB RB Y7 Y6 X7 X6 |
; 2nd byte 0 X5 X4 X3 X2 X1 X0 |
; 3rd byte 0 Y5 Y4 Y3 Y2 Y1 Y0 |
|
virtual at 0 |
IOCTL IOCTL |
end virtual |
struct com_mouse_data |
|
public START |
public version |
port dw ? |
offset db ? |
data rb 3 |
|
ends |
|
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
STRIDE equ 4 ;size of row in devices table |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; proc START ;; |
;; ;; |
;; (standard driver proc) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
SRV_GETVERSION equ 0 |
proc START c, reason:dword, cmdline:dword |
|
section '.flat' code readable align 16 |
cmp [reason], DRV_ENTRY |
jne .fail |
|
proc START stdcall, state:dword |
DEBUGF 2,"Loading serial mouse driver\n" |
|
cmp [state], 1 |
jne .exit |
.entry: |
;Detect_COM_Mouse: |
if DEBUG |
mov esi, msgInit |
call Boot_Log |
end if |
mov bx, 0x3f8 |
call MSMouseSearch |
cmp AL, 'M' |
jne @f |
;mov [com1_mouse_detected],1 |
;mov [irq_owner+4*4], 1 ; IRQ4 owner is System |
stdcall init_mouse, 0x3f8, 4 |
stdcall init_mouse, 0x2f8, 3 |
stdcall init_mouse, 0x3e8, 4 |
stdcall init_mouse, 0x2e8, 3 |
|
mov dx, bx |
inc dx ; 0x3f8 + 1 |
mov al, 1 |
out dx, al |
invoke RegService, my_service, service_proc |
ret |
|
stdcall AttachIntHandler, 4, irq4_handler, dword 0 |
if DEBUG |
test eax, eax |
jne .label1 |
|
mov esi, msg_error_attach_int_handler |
call Boot_Log |
end if |
.label1: |
; mov eax, 0 |
; mov ebx, 0x3F8 |
; mov ecx, 0x3FF |
xor ebx, ebx |
mov ecx, 0x3F8 |
mov edx, 0x3FF |
call ReservePortArea |
|
if DEBUG |
cmp eax, 1 |
jne .go |
|
mov esi, msg_error_reserve_ports |
call Boot_Log |
|
.go: |
mov esi, boot_setmouse_type |
call Boot_Log |
end if |
@@: |
mov bx, 0x2f8 |
call MSMouseSearch |
cmp AL, 'M' |
jne .resume |
;mov [com2_mouse_detected],1 |
;mov [irq_owner+3*4], 1 ; IRQ3 owner is System |
|
stdcall AttachIntHandler, 3, irq3_handler, dword 0 |
|
; mov eax, 0 |
; mov ebx, 0x2F8 |
; mov ecx, 0x3F8 |
xor ebx, ebx |
mov ecx, 0x2F8 |
mov edx, 0x3F8 |
|
call ReservePortArea |
if DEBUG |
cmp eax, 1 |
jne @f |
|
mov esi, msg_error_reserve_ports |
call Boot_Log |
@@: |
|
mov esi, boot_setmouse_type + 22 |
call Boot_Log |
end if |
.resume: |
|
stdcall RegService, my_service, service_proc |
if DEBUG |
test eax, eax |
jne @f |
|
mov esi, msg_exit |
call Boot_Log |
end if |
@@: |
ret |
.fail: |
.exit: |
if DEBUG |
mov esi, msg_exit |
call Boot_Log |
end if |
xor eax, eax |
ret |
|
endp |
|
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
|
align 4 |
proc service_proc stdcall, ioctl:dword |
|
mov ebx, [ioctl] |
mov eax, [ebx+io_code] |
cmp eax, SRV_GETVERSION |
jne @F |
mov eax, [ebx + IOCTL.io_code] |
cmp eax, 0 ;SRV_GETVERSION |
jne .fail |
|
mov eax, [ebx+output] |
cmp [ebx+out_size], 4 |
mov eax, [ebx + IOCTL.output] |
cmp [ebx + IOCTL.out_size], 4 |
jne .fail |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
|
.fail: |
or eax, -1 |
ret |
endp |
|
align 4 |
MSMouseSearch: |
; ПОИСК МЫШИ ЧЕРЕЗ COM-ПОРТЫ |
MouseSearch: |
; Устанавливаем скорость |
; приема/передачи 1200 бод |
; in bx COM Port Base Address |
mov DX, bx |
add DX, 3 |
in AL, DX |
or AL, 80h ;установить бит DLAB |
out DX, AL |
mov DX, bx |
mov AL, 60h ;1200 бод |
out DX, AL |
inc DX |
mov AL, 0 |
out DX, AL |
; Установить длину слова 7 бит, 1 стоповый бит, |
; четность не контролировать |
mov DX, bx |
add DX, 3 |
mov AL, 00000010b |
out DX, AL |
; Запретить все прерывани |
|
proc init_mouse stdcall port, irq |
|
DEBUGF 1, "Trying to init serial mouse on port 0x%x\n", [port] |
|
xor ebx, ebx ; reserve port area |
mov ecx, [port] |
lea edx, [ecx + 7] |
push ebp |
invoke ReservePortArea |
pop ebp |
test eax, eax |
jnz .fail |
|
DEBUGF 1, "Reserved port area\n" |
|
mov bx, word[port] |
|
; Set the speed to 1200 baud |
mov dx, bx |
add dx, 3 |
in al, dx |
or al, 80h ; set DLAB bit |
out dx, al |
|
mov dx, bx |
mov al, 60h ; 1200 baud |
out dx, al |
inc dx |
mov AL, 0 |
out DX, AL |
; Проверить, что устройство подключено и являетс |
; мышью типа MSMouse |
; Отключить питание мыши и прерывани |
mov DX, bx |
add EDX, 4 ;регистр управления модемом |
mov AL, 0 ;сбросить DTR, RTS и OUT2 |
out DX, AL |
; Ожидать 5 "тиков" (0,2 с) |
mov ecx, 0xFFFF |
loop $ |
; Включить питание мыши |
mov al, 0 |
out dx, al |
|
; Use 7 bit words, 1 stop bit, no parity control, reset DLAB bit |
mov dx, bx |
add dx, 3 |
mov al, 00000010b |
out dx, al |
|
; Disable interrupts |
mov dx, bx |
inc dx |
mov al, 0 |
out dx, al |
|
; Check if a MS type serial mouse is connected |
|
; Disable power and mouse interrupts |
mov dx, bx |
add dx, 4 ; modem control register |
mov al, 0 ; reset DTR, RTS, and OUT2 |
out dx, al |
|
; Wait 5 ticks (0.2s) |
mov esi, 200 |
invoke Sleep |
|
; Power on the mouse |
mov al, 1 |
out dx, al |
mov ecx, 0xFFFF |
loop $ |
; Очистить регистр данных |
|
; Wait 5 ticks (0.2s) |
mov esi, 200 |
invoke Sleep |
|
; Clear data register |
mov dx, bx |
in AL, DX |
add edx, 4 |
mov AL, 1011b ;установить DTR и RTS и OUT2 |
out DX, AL |
in al, dx |
|
; set DTR, DTS and OUT2 |
add dx, 4 |
mov al, 1011b |
out dx, al |
|
mov ecx, 0x1FFFF |
; Цикл опроса порта |
WaitData: |
; Ожидать еще 10 "тиков" |
; Poll port |
.loop: |
dec ecx |
; cmp ecx,0 |
jz NoMouse |
; Проверить наличие идентификационного байта |
mov DX, bx |
add DX, 5 |
in AL, DX |
test AL, 1 ;Данные готовы? |
jz WaitData |
; Ввести данные |
mov DX, bx |
in AL, DX |
NoMouse: |
jz .fail |
|
; Check if identification byte is available |
mov dx, bx |
add dx, 5 |
in al, dx |
test al, 1 ; data ready? |
jz .loop |
|
; Read data byte |
mov dx, bx |
in al, dx |
cmp al, 'M' |
jne .free |
|
DEBUGF 2, "Serial mouse detected on port 0x%x\n", [port] |
|
; Create data struct |
|
invoke Kmalloc, sizeof.com_mouse_data |
test eax, eax |
jz .fail |
|
DEBUGF 1, "Structure 0x%x allocated\n", eax |
|
mov bx, word[port] |
mov [eax + com_mouse_data.port], bx |
mov [eax + com_mouse_data.offset], 0 |
|
; Attach int handler |
|
invoke AttachIntHandler, [irq], irq_handler, eax |
test eax, eax |
jz .fail |
|
DEBUGF 1, "Attached int handler\n" |
|
; Enable interrupts |
mov dx, word[port] |
inc dx |
mov al, 1 |
out dx, al |
|
xor eax, eax |
ret |
|
align 4 |
irq3_handler: |
mov dx, 0x2f8 |
mov esi, com2_mouse |
jmp irq_handler |
.free: |
DEBUGF 1, "Freeing port area\n" |
xor ebx, ebx |
inc ebx ; free port area |
mov ecx, [port] |
lea edx, [ecx + 7] |
push ebp |
invoke ReservePortArea |
pop ebp |
|
align 4 |
irq4_handler: |
mov dx, 0x3f8 |
mov esi, com1_mouse |
.fail: |
DEBUGF 1, "Failed\n" |
or eax, -1 |
ret |
|
endp |
|
|
|
irq_handler: |
|
; in: esi -> COM_MOUSE_DATA struc, dx = base port (xF8h) |
add edx, 5 ; xFDh |
push esi |
mov esi, [esp+2*4] |
|
.read_loop: |
mov dx, [esi + com_mouse_data.port] |
add dx, 5 |
in al, dx |
test al, 1 ; Данные готовы? |
jz .Error |
; Ввести данные |
sub edx, 5 |
test al, 1 ; data ready? |
jz .end |
; read data |
sub dx, 5 |
in al, dx |
; Сбросить старший незначащий бит |
and al, 01111111b |
and al, 01111111b ; clear MSB (use 7 bit words) |
|
; Определить порядковый номер принимаемого байта |
cmp [esi+COM_MOUSE_DATA.MouseByteNumber], 2 |
ja .Error |
jz .ThirdByte |
; Check which data byte we are reading |
cmp [esi + com_mouse_data.offset], 2 |
ja .reset |
je .ThirdByte |
jp .SecondByte |
; Сохранить первый байт данных |
.FirstByte: |
test al, 1000000b ; Первый байт посылки? |
jz .Error |
mov [esi+COM_MOUSE_DATA.FirstByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Сохранить второй байт данных |
|
; read first data byte |
test al, 01000000b ; First byte indicator set? |
jz .reset |
mov [esi + com_mouse_data.data+0], al |
inc [esi + com_mouse_data.offset] |
jmp .read_loop |
|
; read second data byte |
.SecondByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.SecondByte], al |
inc [esi+COM_MOUSE_DATA.MouseByteNumber] |
jmp .EndMouseInterrupt |
; Сохранить третий байт данных |
test al, 01000000b ; First byte indicator set? |
jnz .reset |
mov [esi + com_mouse_data.data+1], al |
inc [esi + com_mouse_data.offset] |
jmp .read_loop |
|
; read third data byte |
.ThirdByte: |
test al, 1000000b |
jnz .Error |
mov [esi+COM_MOUSE_DATA.ThirdByte], al |
mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 |
; (Пакет данных от мыши принят полностью). |
; Записать новое значение состояния кнопок мыши |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
test al, 01000000b ; First byte indicator set? |
jnz .reset |
mov [esi + com_mouse_data.data+2], al |
|
; Data packet is complete, parse it and set mouse data |
|
; Buttons |
mov al, [esi + com_mouse_data.data+0] |
mov ah, al |
shr al, 3 |
and al, 2 |
shr ah, 5 |
and ah, 1 |
shr al, 3 ; right mouse button |
and al, 2 ; |
shr ah, 5 ; left mouse button |
and ah, 1 ; |
add al, ah |
movzx eax, al |
mov [BTN_DOWN], eax |
|
; Прибавить перемещение по X к координате X |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
; X coordinate |
mov al, [esi + com_mouse_data.data+0] |
shl al, 6 |
or al, [esi+COM_MOUSE_DATA.SecondByte] |
|
cbw |
movzx eax, ax |
or al, [esi + com_mouse_data.data+1] |
movsx eax, al |
mov [MOUSE_X], eax |
|
; Прибавить перемещение по Y к координате Y |
mov al, [esi+COM_MOUSE_DATA.FirstByte] |
; Y coordinate |
mov al, [esi + com_mouse_data.data+0] |
and al, 00001100b |
shl al, 4 |
or al, [esi+COM_MOUSE_DATA.ThirdByte] |
|
cbw |
movzx eax, ax |
or al, [esi + com_mouse_data.data+2] |
movsx eax, al |
neg eax |
mov [MOUSE_Y], eax |
|
stdcall SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0 |
invoke SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0 |
|
jmp .EndMouseInterrupt |
|
.Error: |
; Произошел сбой в порядке передачи информации от |
; мыши, обнулить счетчик байтов пакета данных |
|
mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 |
.EndMouseInterrupt: |
.reset: |
mov [esi + com_mouse_data.offset], 0 |
.end: |
pop esi |
mov al, 1 |
ret |
|
;all initialized data place here |
|
align 4 |
; End of code |
|
struc COM_MOUSE_DATA { |
; Номер принимаемого от мыши байта |
.MouseByteNumber db ? |
; Трехбайтовая структура данных, передаваемая мышью |
.FirstByte db ? |
.SecondByte db ? |
.ThirdByte db ? |
;.timer_ticks_com dd ? |
} |
virtual at 0 |
COM_MOUSE_DATA COM_MOUSE_DATA |
end virtual |
data fixups |
end data |
|
com1_mouse COM_MOUSE_DATA |
com2_mouse COM_MOUSE_DATA |
include '../peimport.inc' |
|
MOUSE_X dd 0 |
MOUSE_Y dd 0 |
BTN_DOWN dd 0 |
my_service db 'commouse',0 ; max 16 chars include zero |
|
COMPortBaseAddr dw 3F8h |
include_debug_strings |
|
|
|
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
|
my_service db 'COM_Mouse',0 ;max 16 chars include zero |
|
if DEBUG |
msgInit db 'Preved bugoga!',13,10,0 |
boot_setmouse_type db 'Detected - COM1 mouse',13,10,0 |
db 'Detected - COM2 mouse',13,10,0 |
msg_error_reserve_ports db 'Error reserving ports!',13,10,0 |
msg_error_attach_int_handler db 'Error attach interrupt handler!',13,10,0 |
msg_exit db 'Exit!',13,10,0 |
end if |
|
section '.data' data readable writable align 16 |
|
;all uninitialized data place here |
|
MOUSE_X dd ? |
MOUSE_Y dd ? |
BTN_DOWN dd ? |