forked from KolibriOS/kolibrios
r3711 continued, no binary changes
git-svn-id: svn://kolibrios.org@3726 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
38f0b2a169
commit
436a7c0974
@ -74,15 +74,15 @@ ends
|
|||||||
|
|
||||||
; USB HID structures
|
; USB HID structures
|
||||||
struct hid_descr
|
struct hid_descr
|
||||||
bLength db ?
|
bLength db ?
|
||||||
bDescriptorType db ?
|
bDescriptorType db ?
|
||||||
bcdHID dw ?
|
bcdHID dw ?
|
||||||
bCountryCode db ?
|
bCountryCode db ?
|
||||||
bNumDescriptors db ?
|
bNumDescriptors db ?
|
||||||
base_sizeof rb 0
|
base_sizeof rb 0
|
||||||
; now two fields are repeated .bNumDescriptors times:
|
; now two fields are repeated .bNumDescriptors times:
|
||||||
subDescriptorType db ?
|
subDescriptorType db ?
|
||||||
subDescriptorLength dw ?
|
subDescriptorLength dw ?
|
||||||
ends
|
ends
|
||||||
|
|
||||||
; Include macro for parsing report descriptors/data.
|
; Include macro for parsing report descriptors/data.
|
||||||
@ -92,23 +92,23 @@ include 'report.inc'
|
|||||||
|
|
||||||
; Driver data for all devices
|
; Driver data for all devices
|
||||||
struct usb_device_data
|
struct usb_device_data
|
||||||
hid hid_data ; data of HID layer
|
hid hid_data ; data of HID layer
|
||||||
epdescr dd ? ; endpoint descriptor
|
epdescr dd ? ; endpoint descriptor
|
||||||
hiddescr dd ? ; HID descriptor
|
hiddescr dd ? ; HID descriptor
|
||||||
interface_number dd ? ; copy of interface_descr.bInterfaceNumber
|
interface_number dd ? ; copy of interface_descr.bInterfaceNumber
|
||||||
configpipe dd ? ; config pipe handle
|
configpipe dd ? ; config pipe handle
|
||||||
intpipe dd ? ; interrupt pipe handle
|
intpipe dd ? ; interrupt pipe handle
|
||||||
input_transfer_size dd ? ; input transfer size
|
input_transfer_size dd ? ; input transfer size
|
||||||
input_buffer dd ? ; buffer for input transfers
|
input_buffer dd ? ; buffer for input transfers
|
||||||
control rb 8 ; control packet to device
|
control rb 8 ; control packet to device
|
||||||
ends
|
ends
|
||||||
|
|
||||||
section '.flat' code readable align 16
|
section '.flat' code readable align 16
|
||||||
; The start procedure.
|
; The start procedure.
|
||||||
proc START
|
proc START
|
||||||
virtual at esp
|
virtual at esp
|
||||||
dd ? ; return address
|
dd ? ; return address
|
||||||
.reason dd ?
|
.reason dd ?
|
||||||
end virtual
|
end virtual
|
||||||
; 1. Test whether the procedure is called with the argument DRV_ENTRY.
|
; 1. Test whether the procedure is called with the argument DRV_ENTRY.
|
||||||
; If not, return 0.
|
; If not, return 0.
|
||||||
@ -127,30 +127,30 @@ endp
|
|||||||
; This procedure is called when new HID device is detected.
|
; This procedure is called when new HID device is detected.
|
||||||
; It initializes the device.
|
; It initializes the device.
|
||||||
proc AddDevice
|
proc AddDevice
|
||||||
push ebx esi edi ; save used registers to be stdcall
|
push ebx esi edi ; save used registers to be stdcall
|
||||||
virtual at esp
|
virtual at esp
|
||||||
rd 3 ; saved registers
|
rd 3 ; saved registers
|
||||||
dd ? ; return address
|
dd ? ; return address
|
||||||
.config_pipe dd ?
|
.config_pipe dd ?
|
||||||
.config_descr dd ?
|
.config_descr dd ?
|
||||||
.interface dd ?
|
.interface dd ?
|
||||||
end virtual
|
end virtual
|
||||||
DEBUGF 1,'K : USB HID device detected\n'
|
DEBUGF 1,'K : USB HID device detected\n'
|
||||||
; 1. Allocate memory for device data.
|
; 1. Allocate memory for device data.
|
||||||
movi eax, sizeof.usb_device_data
|
movi eax, sizeof.usb_device_data
|
||||||
call Kmalloc
|
call Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
mov esi, nomemory_msg
|
mov esi, nomemory_msg
|
||||||
call SysMsgBoardStr
|
call SysMsgBoardStr
|
||||||
jmp .return0
|
jmp .return0
|
||||||
@@:
|
@@:
|
||||||
; zero-initialize it
|
; zero-initialize it
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
movi ecx, sizeof.usb_device_data / 4
|
movi ecx, sizeof.usb_device_data / 4
|
||||||
rep stosd
|
rep stosd
|
||||||
mov edx, [.interface]
|
mov edx, [.interface]
|
||||||
; HID devices use one IN interrupt endpoint for polling the device
|
; HID devices use one IN interrupt endpoint for polling the device
|
||||||
; and an optional OUT interrupt endpoint. We do not use the later,
|
; and an optional OUT interrupt endpoint. We do not use the later,
|
||||||
@ -171,8 +171,8 @@ end virtual
|
|||||||
.lookep:
|
.lookep:
|
||||||
; 3b. Get next descriptor.
|
; 3b. Get next descriptor.
|
||||||
movzx ecx, byte [edx] ; the first byte of all descriptors is length
|
movzx ecx, byte [edx] ; the first byte of all descriptors is length
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
jz .cfgerror
|
jz .cfgerror
|
||||||
add edx, ecx
|
add edx, ecx
|
||||||
; 3c. Check that at least two bytes are readable. The opposite is an error.
|
; 3c. Check that at least two bytes are readable. The opposite is an error.
|
||||||
inc edx
|
inc edx
|
||||||
@ -188,34 +188,34 @@ end virtual
|
|||||||
; For other descriptors, continue the loop.
|
; For other descriptors, continue the loop.
|
||||||
; Note: bDescriptorType is in the same place in all descriptors.
|
; Note: bDescriptorType is in the same place in all descriptors.
|
||||||
cmp [edx+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE
|
cmp [edx+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE
|
||||||
jz .foundep
|
jz .foundep
|
||||||
cmp [edx+endpoint_descr.bDescriptorType], HID_DESCR_TYPE
|
cmp [edx+endpoint_descr.bDescriptorType], HID_DESCR_TYPE
|
||||||
jnz .lookep
|
jnz .lookep
|
||||||
; 4a. Check that the descriptor contains all required data and all data are
|
; 4a. Check that the descriptor contains all required data and all data are
|
||||||
; readable. The opposite is an error.
|
; readable. The opposite is an error.
|
||||||
movzx ecx, [edx+hid_descr.bLength]
|
movzx ecx, [edx+hid_descr.bLength]
|
||||||
cmp ecx, hid_descr.base_sizeof + 3
|
cmp ecx, hid_descr.base_sizeof + 3
|
||||||
jb .cfgerror
|
jb .cfgerror
|
||||||
add ecx, edx
|
add ecx, edx
|
||||||
cmp ecx, eax
|
cmp ecx, eax
|
||||||
ja .cfgerror
|
ja .cfgerror
|
||||||
; 4b. Store the pointer in usb_device_data structure for further references.
|
; 4b. Store the pointer in usb_device_data structure for further references.
|
||||||
mov [ebx+usb_device_data.hiddescr], edx
|
mov [ebx+usb_device_data.hiddescr], edx
|
||||||
; 4c. Continue the loop.
|
; 4c. Continue the loop.
|
||||||
jmp .lookep
|
jmp .lookep
|
||||||
.foundep:
|
.foundep:
|
||||||
; 5a. Check that the descriptor contains all required data and all data are
|
; 5a. Check that the descriptor contains all required data and all data are
|
||||||
; readable. The opposite is an error.
|
; readable. The opposite is an error.
|
||||||
cmp byte [edx+endpoint_descr.bLength], sizeof.endpoint_descr
|
cmp byte [edx+endpoint_descr.bLength], sizeof.endpoint_descr
|
||||||
jb .cfgerror
|
jb .cfgerror
|
||||||
lea ecx, [edx+sizeof.endpoint_descr]
|
lea ecx, [edx+sizeof.endpoint_descr]
|
||||||
cmp ecx, eax
|
cmp ecx, eax
|
||||||
jbe @f
|
jbe @f
|
||||||
; 6. An error occured during processing endpoint descriptor.
|
; 6. An error occured during processing endpoint descriptor.
|
||||||
.cfgerror:
|
.cfgerror:
|
||||||
; 6a. Print a message.
|
; 6a. Print a message.
|
||||||
mov esi, invalid_config_descr_msg
|
mov esi, invalid_config_descr_msg
|
||||||
call SysMsgBoardStr
|
call SysMsgBoardStr
|
||||||
; 6b. Free memory allocated for device data.
|
; 6b. Free memory allocated for device data.
|
||||||
.free:
|
.free:
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
@ -224,112 +224,112 @@ end virtual
|
|||||||
; 6c. Return an error.
|
; 6c. Return an error.
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
.nothing:
|
.nothing:
|
||||||
pop edi esi ebx ; restore used registers to be stdcall
|
pop edi esi ebx ; restore used registers to be stdcall
|
||||||
ret 12
|
ret 12
|
||||||
@@:
|
@@:
|
||||||
; 5b. If this is not IN interrupt endpoint, ignore it and continue the loop.
|
; 5b. If this is not IN interrupt endpoint, ignore it and continue the loop.
|
||||||
test [edx+endpoint_descr.bEndpointAddress], 80h
|
test [edx+endpoint_descr.bEndpointAddress], 80h
|
||||||
jz .lookep
|
jz .lookep
|
||||||
mov cl, [edx+endpoint_descr.bmAttributes]
|
mov cl, [edx+endpoint_descr.bmAttributes]
|
||||||
and cl, 3
|
and cl, 3
|
||||||
cmp cl, INTERRUPT_PIPE
|
cmp cl, INTERRUPT_PIPE
|
||||||
jnz .lookep
|
jnz .lookep
|
||||||
; 5c. Store the pointer in usb_device_data structure for futher references.
|
; 5c. Store the pointer in usb_device_data structure for futher references.
|
||||||
mov [ebx+usb_device_data.epdescr], edx
|
mov [ebx+usb_device_data.epdescr], edx
|
||||||
; 5d. Check that HID descriptor was found. If not, go to 6.
|
; 5d. Check that HID descriptor was found. If not, go to 6.
|
||||||
cmp [ebx+usb_device_data.hiddescr], 0
|
cmp [ebx+usb_device_data.hiddescr], 0
|
||||||
jz .cfgerror
|
jz .cfgerror
|
||||||
.descriptors_found:
|
.descriptors_found:
|
||||||
; 6. Configuration descriptor seems to be ok.
|
; 6. Configuration descriptor seems to be ok.
|
||||||
; Send SET_IDLE command disabling auto-repeat feature (it is quite useless)
|
; Send SET_IDLE command disabling auto-repeat feature (it is quite useless)
|
||||||
; and continue configuring in SET_IDLE callback.
|
; and continue configuring in SET_IDLE callback.
|
||||||
lea edx, [ebx+usb_device_data.control]
|
lea edx, [ebx+usb_device_data.control]
|
||||||
mov eax, [.interface]
|
mov eax, [.interface]
|
||||||
mov dword [edx], 21h + \ ; Class-specific request to Interface
|
mov dword [edx], 21h + \ ; Class-specific request to Interface
|
||||||
(0Ah shl 8) + \ ; SET_IDLE
|
(0Ah shl 8) + \ ; SET_IDLE
|
||||||
(0 shl 16) + \ ; apply to all input reports
|
(0 shl 16) + \ ; apply to all input reports
|
||||||
(0 shl 24) ; disable auto-repeat
|
(0 shl 24) ; disable auto-repeat
|
||||||
movzx eax, [eax+interface_descr.bInterfaceNumber]
|
movzx eax, [eax+interface_descr.bInterfaceNumber]
|
||||||
mov [ebx+usb_device_data.interface_number], eax
|
mov [ebx+usb_device_data.interface_number], eax
|
||||||
mov [edx+4], eax ; set interface number, zero length
|
mov [edx+4], eax ; set interface number, zero length
|
||||||
mov eax, [.config_pipe]
|
mov eax, [.config_pipe]
|
||||||
mov [ebx+usb_device_data.configpipe], eax
|
mov [ebx+usb_device_data.configpipe], eax
|
||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
stdcall USBControlTransferAsync, eax, edx, ecx, ecx, idle_set, ebx, ecx
|
stdcall USBControlTransferAsync, eax, edx, ecx, ecx, idle_set, ebx, ecx
|
||||||
; 7. Return pointer to usb_device_data.
|
; 7. Return pointer to usb_device_data.
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; This procedure is called by USB stack when SET_IDLE request initiated by
|
; This procedure is called by USB stack when SET_IDLE request initiated by
|
||||||
; AddDevice is completed, either successfully or unsuccessfully.
|
; AddDevice is completed, either successfully or unsuccessfully.
|
||||||
proc idle_set
|
proc idle_set
|
||||||
push ebx esi ; save used registers to be stdcall
|
push ebx esi ; save used registers to be stdcall
|
||||||
virtual at esp
|
virtual at esp
|
||||||
rd 2 ; saved registers
|
rd 2 ; saved registers
|
||||||
dd ? ; return address
|
dd ? ; return address
|
||||||
.pipe dd ?
|
.pipe dd ?
|
||||||
.status dd ?
|
.status dd ?
|
||||||
.buffer dd ?
|
.buffer dd ?
|
||||||
.length dd ?
|
.length dd ?
|
||||||
.calldata dd ?
|
.calldata dd ?
|
||||||
end virtual
|
end virtual
|
||||||
; Ignore status. Support for SET_IDLE is optional, so the device is free to
|
; Ignore status. Support for SET_IDLE is optional, so the device is free to
|
||||||
; STALL the request; config pipe should remain functional without explicit cleanup.
|
; STALL the request; config pipe should remain functional without explicit cleanup.
|
||||||
mov ebx, [.calldata]
|
mov ebx, [.calldata]
|
||||||
; 1. HID descriptor contains length of Report descriptor. Parse it.
|
; 1. HID descriptor contains length of Report descriptor. Parse it.
|
||||||
mov esi, [ebx+usb_device_data.hiddescr]
|
mov esi, [ebx+usb_device_data.hiddescr]
|
||||||
movzx ecx, [esi+hid_descr.bNumDescriptors]
|
movzx ecx, [esi+hid_descr.bNumDescriptors]
|
||||||
lea eax, [hid_descr.base_sizeof+ecx*3]
|
lea eax, [hid_descr.base_sizeof+ecx*3]
|
||||||
cmp eax, 100h
|
cmp eax, 100h
|
||||||
jae .cfgerror
|
jae .cfgerror
|
||||||
cmp al, [esi+hid_descr.bLength]
|
cmp al, [esi+hid_descr.bLength]
|
||||||
jb .cfgerror
|
jb .cfgerror
|
||||||
.look_report:
|
.look_report:
|
||||||
dec ecx
|
dec ecx
|
||||||
js .cfgerror
|
js .cfgerror
|
||||||
cmp [esi+hid_descr.subDescriptorType], REPORT_DESCR_TYPE
|
cmp [esi+hid_descr.subDescriptorType], REPORT_DESCR_TYPE
|
||||||
jz .found_report
|
jz .found_report
|
||||||
add esi, 3
|
add esi, 3
|
||||||
jmp .look_report
|
jmp .look_report
|
||||||
.cfgerror:
|
.cfgerror:
|
||||||
mov esi, invalid_config_descr_msg
|
mov esi, invalid_config_descr_msg
|
||||||
.abort_with_msg:
|
.abort_with_msg:
|
||||||
call SysMsgBoardStr
|
call SysMsgBoardStr
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
.found_report:
|
.found_report:
|
||||||
; 2. Send request for the Report descriptor.
|
; 2. Send request for the Report descriptor.
|
||||||
; 2a. Allocate memory.
|
; 2a. Allocate memory.
|
||||||
movzx eax, [esi+hid_descr.subDescriptorLength]
|
movzx eax, [esi+hid_descr.subDescriptorLength]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .cfgerror
|
jz .cfgerror
|
||||||
push eax
|
push eax
|
||||||
call Kmalloc
|
call Kmalloc
|
||||||
pop ecx
|
pop ecx
|
||||||
; If failed, say a message and stop initialization.
|
; If failed, say a message and stop initialization.
|
||||||
mov esi, nomemory_msg
|
mov esi, nomemory_msg
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .abort_with_msg
|
jz .abort_with_msg
|
||||||
; 2b. Submit the request.
|
; 2b. Submit the request.
|
||||||
xchg eax, esi
|
xchg eax, esi
|
||||||
lea edx, [ebx+usb_device_data.control]
|
lea edx, [ebx+usb_device_data.control]
|
||||||
mov eax, [ebx+usb_device_data.interface_number]
|
mov eax, [ebx+usb_device_data.interface_number]
|
||||||
mov dword [edx], 81h + \ ; Standard request to Interface
|
mov dword [edx], 81h + \ ; Standard request to Interface
|
||||||
(6 shl 8) + \ ; GET_DESCRIPTOR
|
(6 shl 8) + \ ; GET_DESCRIPTOR
|
||||||
(0 shl 16) + \ ; descriptor index: there is only one report descriptor
|
(0 shl 16) + \ ; descriptor index: there is only one report descriptor
|
||||||
(REPORT_DESCR_TYPE shl 24); descriptor type
|
(REPORT_DESCR_TYPE shl 24); descriptor type
|
||||||
mov [edx+4], ax ; Interface number
|
mov [edx+4], ax ; Interface number
|
||||||
mov [edx+6], cx ; descriptor length
|
mov [edx+6], cx ; descriptor length
|
||||||
stdcall USBControlTransferAsync, [ebx+usb_device_data.configpipe], \
|
stdcall USBControlTransferAsync, [ebx+usb_device_data.configpipe], \
|
||||||
edx, esi, ecx, got_report, ebx, 0
|
edx, esi, ecx, got_report, ebx, 0
|
||||||
; 2c. If failed, free the buffer and stop initialization.
|
; 2c. If failed, free the buffer and stop initialization.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .nothing
|
jnz .nothing
|
||||||
xchg eax, esi
|
xchg eax, esi
|
||||||
call Kfree
|
call Kfree
|
||||||
.nothing:
|
.nothing:
|
||||||
pop esi ebx ; restore used registers to be stdcall
|
pop esi ebx ; restore used registers to be stdcall
|
||||||
ret 20
|
ret 20
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; This procedure is called by USB stack when the report descriptor queried
|
; This procedure is called by USB stack when the report descriptor queried
|
||||||
@ -338,100 +338,100 @@ proc got_report stdcall uses ebx esi edi, pipe, status, buffer, length, calldata
|
|||||||
locals
|
locals
|
||||||
parse_descr_locals
|
parse_descr_locals
|
||||||
if ~HID_DUMP_UNCLAIMED
|
if ~HID_DUMP_UNCLAIMED
|
||||||
has_driver db ?
|
has_driver db ?
|
||||||
rb 3
|
rb 3
|
||||||
end if
|
end if
|
||||||
endl
|
endl
|
||||||
; 1. Check the status; if the request has failed, say something to the debug board
|
; 1. Check the status; if the request has failed, say something to the debug board
|
||||||
; and stop initialization.
|
; and stop initialization.
|
||||||
cmp [status], 0
|
cmp [status], 0
|
||||||
jnz .generic_fail
|
jnz .generic_fail
|
||||||
; 2. Subtract size of setup packet from the total length;
|
; 2. Subtract size of setup packet from the total length;
|
||||||
; the rest is length of the descriptor, and it must be nonzero.
|
; the rest is length of the descriptor, and it must be nonzero.
|
||||||
sub [length], 8
|
sub [length], 8
|
||||||
ja .has_something
|
ja .has_something
|
||||||
.generic_fail:
|
.generic_fail:
|
||||||
push esi
|
push esi
|
||||||
mov esi, reportfail
|
mov esi, reportfail
|
||||||
call SysMsgBoardStr
|
call SysMsgBoardStr
|
||||||
pop esi
|
pop esi
|
||||||
jmp .exit
|
jmp .exit
|
||||||
.has_something:
|
.has_something:
|
||||||
; 3. Process descriptor.
|
; 3. Process descriptor.
|
||||||
; 3a. Dump it to the debug board, if enabled in compile-time setting.
|
; 3a. Dump it to the debug board, if enabled in compile-time setting.
|
||||||
if USB_DUMP_DESCRIPTORS
|
if USB_DUMP_DESCRIPTORS
|
||||||
mov eax, [buffer]
|
mov eax, [buffer]
|
||||||
mov ecx, [length]
|
mov ecx, [length]
|
||||||
DEBUGF 1,'K : report descriptor:'
|
DEBUGF 1,'K : report descriptor:'
|
||||||
@@:
|
@@:
|
||||||
DEBUGF 1,' %x',[eax]:2
|
DEBUGF 1,' %x',[eax]:2
|
||||||
inc eax
|
inc eax
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz @b
|
jnz @b
|
||||||
DEBUGF 1,'\n'
|
DEBUGF 1,'\n'
|
||||||
end if
|
end if
|
||||||
; 3b. Call the HID layer.
|
; 3b. Call the HID layer.
|
||||||
parse_descr
|
parse_descr
|
||||||
cmp [report_ok], 0
|
cmp [report_ok], 0
|
||||||
jz got_report.exit
|
jz got_report.exit
|
||||||
mov ebx, [calldata]
|
mov ebx, [calldata]
|
||||||
postprocess_descr
|
postprocess_descr
|
||||||
; 4. Stop initialization if no driver is assigned.
|
; 4. Stop initialization if no driver is assigned.
|
||||||
if ~HID_DUMP_UNCLAIMED
|
if ~HID_DUMP_UNCLAIMED
|
||||||
cmp [has_driver], 0
|
cmp [has_driver], 0
|
||||||
jz got_report.exit
|
jz got_report.exit
|
||||||
end if
|
end if
|
||||||
; 5. Open interrupt IN pipe. If failed, stop initialization.
|
; 5. Open interrupt IN pipe. If failed, stop initialization.
|
||||||
mov edx, [ebx+usb_device_data.epdescr]
|
mov edx, [ebx+usb_device_data.epdescr]
|
||||||
movzx ecx, [edx+endpoint_descr.bEndpointAddress]
|
movzx ecx, [edx+endpoint_descr.bEndpointAddress]
|
||||||
movzx eax, [edx+endpoint_descr.bInterval]
|
movzx eax, [edx+endpoint_descr.bInterval]
|
||||||
movzx edx, [edx+endpoint_descr.wMaxPacketSize]
|
movzx edx, [edx+endpoint_descr.wMaxPacketSize]
|
||||||
stdcall USBOpenPipe, [ebx+usb_device_data.configpipe], ecx, edx, INTERRUPT_PIPE, eax
|
stdcall USBOpenPipe, [ebx+usb_device_data.configpipe], ecx, edx, INTERRUPT_PIPE, eax
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz got_report.exit
|
jz got_report.exit
|
||||||
mov [ebx+usb_device_data.intpipe], eax
|
mov [ebx+usb_device_data.intpipe], eax
|
||||||
; 6. Initialize buffer for input packet.
|
; 6. Initialize buffer for input packet.
|
||||||
; 6a. Find the length of input packet.
|
; 6a. Find the length of input packet.
|
||||||
; This is the maximal length of all input reports.
|
; This is the maximal length of all input reports.
|
||||||
mov edx, [ebx+usb_device_data.hid.input.first_report]
|
mov edx, [ebx+usb_device_data.hid.input.first_report]
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
.find_input_size:
|
.find_input_size:
|
||||||
test edx, edx
|
test edx, edx
|
||||||
jz .found_input_size
|
jz .found_input_size
|
||||||
cmp eax, [edx+report.size]
|
cmp eax, [edx+report.size]
|
||||||
jae @f
|
jae @f
|
||||||
mov eax, [edx+report.size]
|
mov eax, [edx+report.size]
|
||||||
@@:
|
@@:
|
||||||
mov edx, [edx+report.next]
|
mov edx, [edx+report.next]
|
||||||
jmp .find_input_size
|
jmp .find_input_size
|
||||||
.found_input_size:
|
.found_input_size:
|
||||||
; report.size is in bits, transform it to bytes
|
; report.size is in bits, transform it to bytes
|
||||||
add eax, 7
|
add eax, 7
|
||||||
shr eax, 3
|
shr eax, 3
|
||||||
; if reports are numbered, the first byte is report ID, include it
|
; if reports are numbered, the first byte is report ID, include it
|
||||||
cmp [ebx+usb_device_data.hid.input.numbered], 0
|
cmp [ebx+usb_device_data.hid.input.numbered], 0
|
||||||
jz @f
|
jz @f
|
||||||
inc eax
|
inc eax
|
||||||
@@:
|
@@:
|
||||||
mov [ebx+usb_device_data.input_transfer_size], eax
|
mov [ebx+usb_device_data.input_transfer_size], eax
|
||||||
; 6b. Allocate memory for input packet: dword-align and add additional dword
|
; 6b. Allocate memory for input packet: dword-align and add additional dword
|
||||||
; for extract_field_value.
|
; for extract_field_value.
|
||||||
add eax, 4+3
|
add eax, 4+3
|
||||||
and eax, not 3
|
and eax, not 3
|
||||||
call Kmalloc
|
call Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
mov esi, nomemory_msg
|
mov esi, nomemory_msg
|
||||||
call SysMsgBoardStr
|
call SysMsgBoardStr
|
||||||
jmp got_report.exit
|
jmp got_report.exit
|
||||||
@@:
|
@@:
|
||||||
mov [ebx+usb_device_data.input_buffer], eax
|
mov [ebx+usb_device_data.input_buffer], eax
|
||||||
; 7. Submit a request for input packet and wait for input.
|
; 7. Submit a request for input packet and wait for input.
|
||||||
call ask_for_input
|
call ask_for_input
|
||||||
got_report.exit:
|
got_report.exit:
|
||||||
mov eax, [buffer]
|
mov eax, [buffer]
|
||||||
call Kfree
|
call Kfree
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; Helper procedure for got_report and got_input.
|
; Helper procedure for got_report and got_input.
|
||||||
@ -439,13 +439,13 @@ endp
|
|||||||
proc ask_for_input
|
proc ask_for_input
|
||||||
; just call USBNormalTransferAsync with correct parameters,
|
; just call USBNormalTransferAsync with correct parameters,
|
||||||
; allow short packets
|
; allow short packets
|
||||||
stdcall USBNormalTransferAsync, \
|
stdcall USBNormalTransferAsync, \
|
||||||
[ebx+usb_device_data.intpipe], \
|
[ebx+usb_device_data.intpipe], \
|
||||||
[ebx+usb_device_data.input_buffer], \
|
[ebx+usb_device_data.input_buffer], \
|
||||||
[ebx+usb_device_data.input_transfer_size], \
|
[ebx+usb_device_data.input_transfer_size], \
|
||||||
got_input, ebx, \
|
got_input, ebx, \
|
||||||
1
|
1
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; This procedure is called by USB stack when a HID device responds with input
|
; This procedure is called by USB stack when a HID device responds with input
|
||||||
@ -455,67 +455,67 @@ locals
|
|||||||
parse_input_locals
|
parse_input_locals
|
||||||
endl
|
endl
|
||||||
; 1. Validate parameters: fail on error, ignore zero-length transfers.
|
; 1. Validate parameters: fail on error, ignore zero-length transfers.
|
||||||
mov ebx, [calldata]
|
mov ebx, [calldata]
|
||||||
cmp [status], 0
|
cmp [status], 0
|
||||||
jnz .fail
|
jnz .fail
|
||||||
cmp [length], 0
|
cmp [length], 0
|
||||||
jz .done
|
jz .done
|
||||||
; 2. Get pointer to report in esi.
|
; 2. Get pointer to report in esi.
|
||||||
; 2a. If there are no report IDs, use hid.input.data.
|
; 2a. If there are no report IDs, use hid.input.data.
|
||||||
mov eax, [buffer]
|
mov eax, [buffer]
|
||||||
mov esi, [ebx+usb_device_data.hid.input.data]
|
mov esi, [ebx+usb_device_data.hid.input.data]
|
||||||
cmp [ebx+usb_device_data.hid.input.numbered], 0
|
cmp [ebx+usb_device_data.hid.input.numbered], 0
|
||||||
jz .report_found
|
jz .report_found
|
||||||
; 2b. Otherwise, the first byte of report is report ID;
|
; 2b. Otherwise, the first byte of report is report ID;
|
||||||
; locate the report by its ID, advance buffer+length to one byte.
|
; locate the report by its ID, advance buffer+length to one byte.
|
||||||
movzx eax, byte [eax]
|
movzx eax, byte [eax]
|
||||||
mov esi, [esi+eax*4]
|
mov esi, [esi+eax*4]
|
||||||
inc [buffer]
|
inc [buffer]
|
||||||
dec [length]
|
dec [length]
|
||||||
.report_found:
|
.report_found:
|
||||||
; 3. Validate: ignore transfers with unregistered report IDs
|
; 3. Validate: ignore transfers with unregistered report IDs
|
||||||
; and transfers which are too short for the corresponding report.
|
; and transfers which are too short for the corresponding report.
|
||||||
test esi, esi
|
test esi, esi
|
||||||
jz .done
|
jz .done
|
||||||
mov eax, [esi+report.size]
|
mov eax, [esi+report.size]
|
||||||
add eax, 7
|
add eax, 7
|
||||||
shr eax, 3
|
shr eax, 3
|
||||||
cmp eax, [length]
|
cmp eax, [length]
|
||||||
ja .done
|
ja .done
|
||||||
; 4. Pass everything to HID layer.
|
; 4. Pass everything to HID layer.
|
||||||
parse_input
|
parse_input
|
||||||
.done:
|
.done:
|
||||||
; 5. Query the next input.
|
; 5. Query the next input.
|
||||||
mov ebx, [calldata]
|
mov ebx, [calldata]
|
||||||
call ask_for_input
|
call ask_for_input
|
||||||
.nothing:
|
.nothing:
|
||||||
ret
|
ret
|
||||||
.fail:
|
.fail:
|
||||||
mov esi, transfer_error_msg
|
mov esi, transfer_error_msg
|
||||||
call SysMsgBoardStr
|
call SysMsgBoardStr
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; This function is called by the USB subsystem when a device is disconnected.
|
; This function is called by the USB subsystem when a device is disconnected.
|
||||||
proc DeviceDisconnected
|
proc DeviceDisconnected
|
||||||
push ebx esi edi ; save used registers to be stdcall
|
push ebx esi edi ; save used registers to be stdcall
|
||||||
virtual at esp
|
virtual at esp
|
||||||
rd 3 ; saved registers
|
rd 3 ; saved registers
|
||||||
dd ? ; return address
|
dd ? ; return address
|
||||||
.device_data dd ?
|
.device_data dd ?
|
||||||
end virtual
|
end virtual
|
||||||
; 1. Say a message.
|
; 1. Say a message.
|
||||||
mov ebx, [.device_data]
|
mov ebx, [.device_data]
|
||||||
mov esi, disconnectmsg
|
mov esi, disconnectmsg
|
||||||
stdcall SysMsgBoardStr
|
stdcall SysMsgBoardStr
|
||||||
; 2. Ask HID layer to release all HID-related resources.
|
; 2. Ask HID layer to release all HID-related resources.
|
||||||
hid_cleanup
|
hid_cleanup
|
||||||
; 3. Free the device data.
|
; 3. Free the device data.
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
call Kfree
|
call Kfree
|
||||||
; 4. Return.
|
; 4. Return.
|
||||||
.nothing:
|
.nothing:
|
||||||
pop edi esi ebx ; restore used registers to be stdcall
|
pop edi esi ebx ; restore used registers to be stdcall
|
||||||
ret 4 ; purge one dword argument to be stdcall
|
ret 4 ; purge one dword argument to be stdcall
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -526,13 +526,13 @@ include 'keyboard.inc'
|
|||||||
|
|
||||||
; strings
|
; strings
|
||||||
my_driver db 'usbhid',0
|
my_driver db 'usbhid',0
|
||||||
nomemory_msg db 'K : no memory',13,10,0
|
nomemory_msg db 'K : no memory',13,10,0
|
||||||
invalid_config_descr_msg db 'K : invalid config descriptor',13,10,0
|
invalid_config_descr_msg db 'K : invalid config descriptor',13,10,0
|
||||||
reportfail db 'K : failed to read report descriptor',13,10,0
|
reportfail db 'K : failed to read report descriptor',13,10,0
|
||||||
transfer_error_msg db 'K : USB transfer error, disabling HID device',13,10,0
|
transfer_error_msg db 'K : USB transfer error, disabling HID device',13,10,0
|
||||||
disconnectmsg db 'K : USB HID device disconnected',13,10,0
|
disconnectmsg db 'K : USB HID device disconnected',13,10,0
|
||||||
invalid_report_msg db 'K : report descriptor is invalid',13,10,0
|
invalid_report_msg db 'K : report descriptor is invalid',13,10,0
|
||||||
delimiter_note db 'K : note: alternate usage ignored',13,10,0
|
delimiter_note db 'K : note: alternate usage ignored',13,10,0
|
||||||
|
|
||||||
; Exported variable: kernel API version.
|
; Exported variable: kernel API version.
|
||||||
align 4
|
align 4
|
||||||
|
@ -358,40 +358,40 @@ high_code:
|
|||||||
call mutex_init
|
call mutex_init
|
||||||
|
|
||||||
; SAVE REAL MODE VARIABLES
|
; SAVE REAL MODE VARIABLES
|
||||||
xor eax,eax
|
xor eax, eax
|
||||||
mov ax, [BOOT_VAR + BOOT_IDE_PI_16]
|
mov ax, [BOOT_VAR + BOOT_IDE_PI_16]
|
||||||
mov [IDEContrProgrammingInterface], ax
|
mov [IDEContrProgrammingInterface], ax
|
||||||
mov ax, [BOOT_VAR + BOOT_IDE_BASE_ADDR]
|
mov ax, [BOOT_VAR + BOOT_IDE_BASE_ADDR]
|
||||||
mov [IDEContrRegsBaseAddr], ax
|
mov [IDEContrRegsBaseAddr], ax
|
||||||
mov ax, [BOOT_VAR + BOOT_IDE_BAR0_16]
|
mov ax, [BOOT_VAR + BOOT_IDE_BAR0_16]
|
||||||
mov [IDE_BAR0_val], ax
|
mov [IDE_BAR0_val], ax
|
||||||
|
|
||||||
cmp ax,0
|
cmp ax, 0
|
||||||
je @f
|
je @f
|
||||||
cmp ax,1
|
cmp ax, 1
|
||||||
je @f
|
je @f
|
||||||
and ax,0xfff0
|
and ax, 0xfff0
|
||||||
mov [StandardATABases],ax
|
mov [StandardATABases], ax
|
||||||
mov [hd_address_table],eax
|
mov [hd_address_table], eax
|
||||||
mov [hd_address_table+8],eax
|
mov [hd_address_table+8], eax
|
||||||
@@:
|
@@:
|
||||||
mov ax, [BOOT_VAR + BOOT_IDE_BAR1_16]
|
mov ax, [BOOT_VAR + BOOT_IDE_BAR1_16]
|
||||||
mov [IDE_BAR1_val], ax
|
mov [IDE_BAR1_val], ax
|
||||||
mov ax, [BOOT_VAR + BOOT_IDE_BAR2_16]
|
mov ax, [BOOT_VAR + BOOT_IDE_BAR2_16]
|
||||||
mov [IDE_BAR2_val], ax
|
mov [IDE_BAR2_val], ax
|
||||||
|
|
||||||
cmp ax,0
|
cmp ax, 0
|
||||||
je @f
|
je @f
|
||||||
cmp ax,1
|
cmp ax, 1
|
||||||
je @f
|
je @f
|
||||||
and ax,0xfff0
|
and ax, 0xfff0
|
||||||
mov [StandardATABases+2],ax
|
mov [StandardATABases+2], ax
|
||||||
mov [hd_address_table+16],eax
|
mov [hd_address_table+16], eax
|
||||||
mov [hd_address_table+24],eax
|
mov [hd_address_table+24], eax
|
||||||
@@:
|
@@:
|
||||||
mov ax, [BOOT_VAR + BOOT_IDE_BAR3_16]
|
mov ax, [BOOT_VAR + BOOT_IDE_BAR3_16]
|
||||||
mov [IDE_BAR3_val], ax
|
mov [IDE_BAR3_val], ax
|
||||||
|
|
||||||
; --------------- APM ---------------------
|
; --------------- APM ---------------------
|
||||||
|
|
||||||
; init selectors
|
; init selectors
|
||||||
@ -1066,17 +1066,17 @@ end if
|
|||||||
|
|
||||||
cmp [IDEContrRegsBaseAddr], 0
|
cmp [IDEContrRegsBaseAddr], 0
|
||||||
setnz [dma_hdd]
|
setnz [dma_hdd]
|
||||||
|
|
||||||
cmp [dma_hdd],0
|
cmp [dma_hdd], 0
|
||||||
je .print_pio
|
je .print_pio
|
||||||
.print_dma:
|
.print_dma:
|
||||||
DEBUGF 1, "K : IDE DMA mode\n"
|
DEBUGF 1, "K : IDE DMA mode\n"
|
||||||
jmp .continue
|
jmp .continue
|
||||||
|
|
||||||
.print_pio:
|
.print_pio:
|
||||||
DEBUGF 1, "K : IDE PIO mode\n"
|
DEBUGF 1, "K : IDE PIO mode\n"
|
||||||
.continue:
|
.continue:
|
||||||
|
|
||||||
mov [timer_ticks_enable], 1 ; for cd driver
|
mov [timer_ticks_enable], 1 ; for cd driver
|
||||||
|
|
||||||
sti
|
sti
|
||||||
@ -1634,27 +1634,27 @@ endg
|
|||||||
|
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz noprma
|
jnz noprma
|
||||||
mov eax,[hd_address_table]
|
mov eax, [hd_address_table]
|
||||||
mov [cdbase], eax ;0x1f0
|
mov [cdbase], eax ;0x1f0
|
||||||
mov [cdid], 0xa0
|
mov [cdid], 0xa0
|
||||||
noprma:
|
noprma:
|
||||||
|
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz noprsl
|
jnz noprsl
|
||||||
mov eax,[hd_address_table]
|
mov eax, [hd_address_table]
|
||||||
mov [cdbase], eax ;0x1f0
|
mov [cdbase], eax ;0x1f0
|
||||||
mov [cdid], 0xb0
|
mov [cdid], 0xb0
|
||||||
noprsl:
|
noprsl:
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz nosema
|
jnz nosema
|
||||||
mov eax,[hd_address_table+16]
|
mov eax, [hd_address_table+16]
|
||||||
mov [cdbase], eax ;0x170
|
mov [cdbase], eax ;0x170
|
||||||
mov [cdid], 0xa0
|
mov [cdid], 0xa0
|
||||||
nosema:
|
nosema:
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz nosesl
|
jnz nosesl
|
||||||
mov eax,[hd_address_table+16]
|
mov eax, [hd_address_table+16]
|
||||||
mov [cdbase], eax ;0x170
|
mov [cdbase], eax ;0x170
|
||||||
mov [cdid], 0xb0
|
mov [cdid], 0xb0
|
||||||
nosesl:
|
nosesl:
|
||||||
ret
|
ret
|
||||||
@ -1683,8 +1683,8 @@ endg
|
|||||||
|
|
||||||
cmp ecx, 1
|
cmp ecx, 1
|
||||||
jnz noprmahd
|
jnz noprmahd
|
||||||
mov eax,[hd_address_table]
|
mov eax, [hd_address_table]
|
||||||
mov [hdbase], eax ;0x1f0
|
mov [hdbase], eax ;0x1f0
|
||||||
and dword [hdid], 0x0
|
and dword [hdid], 0x0
|
||||||
mov dword [hdpos], ecx
|
mov dword [hdpos], ecx
|
||||||
; call set_FAT32_variables
|
; call set_FAT32_variables
|
||||||
@ -1692,8 +1692,8 @@ endg
|
|||||||
|
|
||||||
cmp ecx, 2
|
cmp ecx, 2
|
||||||
jnz noprslhd
|
jnz noprslhd
|
||||||
mov eax,[hd_address_table]
|
mov eax, [hd_address_table]
|
||||||
mov [hdbase], eax ;0x1f0
|
mov [hdbase], eax ;0x1f0
|
||||||
mov [hdid], 0x10
|
mov [hdid], 0x10
|
||||||
mov dword [hdpos], ecx
|
mov dword [hdpos], ecx
|
||||||
; call set_FAT32_variables
|
; call set_FAT32_variables
|
||||||
@ -1701,8 +1701,8 @@ endg
|
|||||||
|
|
||||||
cmp ecx, 3
|
cmp ecx, 3
|
||||||
jnz nosemahd
|
jnz nosemahd
|
||||||
mov eax,[hd_address_table+16]
|
mov eax, [hd_address_table+16]
|
||||||
mov [hdbase], eax ;0x170
|
mov [hdbase], eax ;0x170
|
||||||
and dword [hdid], 0x0
|
and dword [hdid], 0x0
|
||||||
mov dword [hdpos], ecx
|
mov dword [hdpos], ecx
|
||||||
; call set_FAT32_variables
|
; call set_FAT32_variables
|
||||||
@ -1710,8 +1710,8 @@ endg
|
|||||||
|
|
||||||
cmp ecx, 4
|
cmp ecx, 4
|
||||||
jnz noseslhd
|
jnz noseslhd
|
||||||
mov eax,[hd_address_table+16]
|
mov eax, [hd_address_table+16]
|
||||||
mov [hdbase], eax ;0x170
|
mov [hdbase], eax ;0x170
|
||||||
mov [hdid], 0x10
|
mov [hdid], 0x10
|
||||||
mov dword [hdpos], ecx
|
mov dword [hdpos], ecx
|
||||||
; call set_FAT32_variables
|
; call set_FAT32_variables
|
||||||
|
Loading…
Reference in New Issue
Block a user