forked from KolibriOS/kolibrios
convert usbhid and usbstor to PE
git-svn-id: svn://kolibrios.org@5051 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
962d0858c7
commit
7dce54fc55
@ -134,8 +134,6 @@ FASM_PROGRAMS:=\
|
|||||||
drivers/sb16.obj:DRIVERS/SB16.OBJ:$(KERNEL)/drivers/sb16/sb16.asm \
|
drivers/sb16.obj:DRIVERS/SB16.OBJ:$(KERNEL)/drivers/sb16/sb16.asm \
|
||||||
drivers/sound.obj:DRIVERS/SOUND.OBJ:$(KERNEL)/drivers/sound.asm \
|
drivers/sound.obj:DRIVERS/SOUND.OBJ:$(KERNEL)/drivers/sound.asm \
|
||||||
drivers/intelac97.obj:DRIVERS/INTELAC97.OBJ:$(KERNEL)/drivers/intelac97.asm \
|
drivers/intelac97.obj:DRIVERS/INTELAC97.OBJ:$(KERNEL)/drivers/intelac97.asm \
|
||||||
drivers/usbhid.obj:DRIVERS/USBHID.OBJ:$(KERNEL)/drivers/usbhid/usbhid.asm \
|
|
||||||
drivers/usbstor.obj:DRIVERS/USBSTOR.OBJ:$(KERNEL)/drivers/usbstor.asm \
|
|
||||||
drivers/vt823x.obj:DRIVERS/VT823X.OBJ:$(KERNEL)/drivers/vt823x.asm \
|
drivers/vt823x.obj:DRIVERS/VT823X.OBJ:$(KERNEL)/drivers/vt823x.asm \
|
||||||
drivers/3c59x.obj:DRIVERS/3C59X.OBJ:$(REPOSITORY)/drivers/ethernet/3c59x.asm \
|
drivers/3c59x.obj:DRIVERS/3C59X.OBJ:$(REPOSITORY)/drivers/ethernet/3c59x.asm \
|
||||||
File|Managers/kfar:File|Managers/KFAR:$(PROGS)/fs/kfar/trunk/kfar.asm \
|
File|Managers/kfar:File|Managers/KFAR:$(PROGS)/fs/kfar/trunk/kfar.asm \
|
||||||
@ -226,6 +224,8 @@ FASM_PROGRAMS_PESTRIP:=\
|
|||||||
drivers/uhci.sys:DRIVERS/UHCI.SYS:$(REPOSITORY)/drivers/usb/uhci.asm \
|
drivers/uhci.sys:DRIVERS/UHCI.SYS:$(REPOSITORY)/drivers/usb/uhci.asm \
|
||||||
drivers/ohci.sys:DRIVERS/OHCI.SYS:$(REPOSITORY)/drivers/usb/ohci.asm \
|
drivers/ohci.sys:DRIVERS/OHCI.SYS:$(REPOSITORY)/drivers/usb/ohci.asm \
|
||||||
drivers/ehci.sys:DRIVERS/EHCI.SYS:$(REPOSITORY)/drivers/usb/ehci.asm \
|
drivers/ehci.sys:DRIVERS/EHCI.SYS:$(REPOSITORY)/drivers/usb/ehci.asm \
|
||||||
|
drivers/usbhid.sys:DRIVERS/USBHID.SYS:$(REPOSITORY)/drivers/usb/usbhid/usbhid.asm \
|
||||||
|
drivers/usbstor.sys:DRIVERS/USBSTOR.SYS:$(REPOSITORY)/drivers/usb/usbstor.asm \
|
||||||
drivers/rdc.sys:DRIVERS/RDC.SYS:$(REPOSITORY)/drivers/video/rdc.asm \
|
drivers/rdc.sys:DRIVERS/RDC.SYS:$(REPOSITORY)/drivers/video/rdc.asm \
|
||||||
drivers/ps2mouse.sys:DRIVERS/PS2MOUSE.SYS:$(REPOSITORY)/drivers/mouse/ps2mouse4d/trunk/ps2mouse.asm \
|
drivers/ps2mouse.sys:DRIVERS/PS2MOUSE.SYS:$(REPOSITORY)/drivers/mouse/ps2mouse4d/trunk/ps2mouse.asm \
|
||||||
drivers/tmpdisk.sys:DRIVERS/TMPDISK.SYS:$(REPOSITORY)/drivers/disk/tmpdisk.asm \
|
drivers/tmpdisk.sys:DRIVERS/TMPDISK.SYS:$(REPOSITORY)/drivers/disk/tmpdisk.asm \
|
||||||
|
@ -60,7 +60,7 @@ ends
|
|||||||
proc keyboard_driver_add_device
|
proc keyboard_driver_add_device
|
||||||
; 1. Allocate memory for keyboard_device_data. If failed, return NULL.
|
; 1. Allocate memory for keyboard_device_data. If failed, return NULL.
|
||||||
movi eax, sizeof.keyboard_device_data
|
movi eax, sizeof.keyboard_device_data
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .nothing
|
jz .nothing
|
||||||
; 2. Initialize keyboard_device_data: store pointer to USB layer data,
|
; 2. Initialize keyboard_device_data: store pointer to USB layer data,
|
||||||
@ -154,7 +154,7 @@ proc keyboard_driver_add_device
|
|||||||
; store pointer to keyboard_device_data in the stack
|
; store pointer to keyboard_device_data in the stack
|
||||||
push eax
|
push eax
|
||||||
; call kernel API
|
; call kernel API
|
||||||
stdcall RegKeyboard, kbd_functions, eax
|
invoke RegKeyboard, kbd_functions, eax
|
||||||
; restore pointer to keyboard_device_data from the stack,
|
; restore pointer to keyboard_device_data from the stack,
|
||||||
; putting keyboard handle from API to the stack
|
; putting keyboard handle from API to the stack
|
||||||
xchg eax, [esp]
|
xchg eax, [esp]
|
||||||
@ -167,7 +167,7 @@ proc keyboard_driver_add_device
|
|||||||
.nothing:
|
.nothing:
|
||||||
ret
|
ret
|
||||||
.fail_free:
|
.fail_free:
|
||||||
call Kfree
|
invoke Kfree
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -179,10 +179,10 @@ proc keyboard_driver_disconnect
|
|||||||
; 1. If an autorepeat timer is active, stop it.
|
; 1. If an autorepeat timer is active, stop it.
|
||||||
cmp [edi+keyboard_device_data.timer], 0
|
cmp [edi+keyboard_device_data.timer], 0
|
||||||
jz @f
|
jz @f
|
||||||
stdcall CancelTimerHS, [edi+keyboard_device_data.timer]
|
invoke CancelTimerHS, [edi+keyboard_device_data.timer]
|
||||||
@@:
|
@@:
|
||||||
; 2. Unregister keyboard in the kernel.
|
; 2. Unregister keyboard in the kernel.
|
||||||
stdcall DelKeyboard, [edi+keyboard_device_data.handle]
|
invoke DelKeyboard, [edi+keyboard_device_data.handle]
|
||||||
; We should free data in CloseKeyboard, not here.
|
; We should free data in CloseKeyboard, not here.
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -245,11 +245,11 @@ end if
|
|||||||
mov eax, [edi+keyboard_device_data.timer]
|
mov eax, [edi+keyboard_device_data.timer]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
stdcall CancelTimerHS, eax
|
invoke CancelTimerHS, eax
|
||||||
@@:
|
@@:
|
||||||
; 1h. Start the new autorepeat timer with 250 ms initial delay
|
; 1h. Start the new autorepeat timer with 250 ms initial delay
|
||||||
; and 50 ms subsequent delays.
|
; and 50 ms subsequent delays.
|
||||||
stdcall TimerHS, 25, 5, autorepeat_timer, edi
|
invoke TimerHS, 25, 5, autorepeat_timer, edi
|
||||||
mov [edi+keyboard_device_data.timer], eax
|
mov [edi+keyboard_device_data.timer], eax
|
||||||
if ~HID_DUMP_UNCLAIMED
|
if ~HID_DUMP_UNCLAIMED
|
||||||
.unclaimed:
|
.unclaimed:
|
||||||
@ -265,7 +265,7 @@ end if
|
|||||||
mov eax, [edi+keyboard_device_data.timer]
|
mov eax, [edi+keyboard_device_data.timer]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
stdcall CancelTimerHS, eax
|
invoke CancelTimerHS, eax
|
||||||
mov [edi+keyboard_device_data.timer], 0
|
mov [edi+keyboard_device_data.timer], 0
|
||||||
@@:
|
@@:
|
||||||
pop ecx
|
pop ecx
|
||||||
@ -321,10 +321,10 @@ end if
|
|||||||
jnc @f
|
jnc @f
|
||||||
push ecx
|
push ecx
|
||||||
mov ecx, 0xE0
|
mov ecx, 0xE0
|
||||||
call SetKeyboardData
|
invoke SetKeyboardData
|
||||||
pop ecx
|
pop ecx
|
||||||
@@:
|
@@:
|
||||||
call SetKeyboardData
|
invoke SetKeyboardData
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -359,7 +359,7 @@ virtual at esp
|
|||||||
.device_data dd ?
|
.device_data dd ?
|
||||||
end virtual
|
end virtual
|
||||||
mov eax, [.device_data]
|
mov eax, [.device_data]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
ret 4
|
ret 4
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -392,7 +392,7 @@ endl
|
|||||||
add eax, 8 + 3
|
add eax, 8 + 3
|
||||||
and eax, not 3
|
and eax, not 3
|
||||||
push eax
|
push eax
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
pop ecx
|
pop ecx
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .nothing
|
jz .nothing
|
||||||
@ -444,14 +444,14 @@ endl
|
|||||||
or edx, [ebx+usb_device_data.interface_number]
|
or edx, [ebx+usb_device_data.interface_number]
|
||||||
mov [eax+4], edx
|
mov [eax+4], edx
|
||||||
; 8. Submit output control request.
|
; 8. Submit output control request.
|
||||||
stdcall USBControlTransferAsync, [ebx+usb_device_data.configpipe], \
|
invoke USBControlTransferAsync, [ebx+usb_device_data.configpipe], \
|
||||||
eax, edi, [size], after_set_keyboard_lights, ebx, 0
|
eax, edi, [size], after_set_keyboard_lights, ebx, 0
|
||||||
; If failed, free the buffer now.
|
; If failed, free the buffer now.
|
||||||
; If succeeded, the callback will free the buffer.
|
; If succeeded, the callback will free the buffer.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .nothing
|
jnz .nothing
|
||||||
lea eax, [edi-8]
|
lea eax, [edi-8]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
.nothing:
|
.nothing:
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -470,6 +470,6 @@ end virtual
|
|||||||
; Ignore status, just free the buffer allocated by SetKeyboardLights.
|
; Ignore status, just free the buffer allocated by SetKeyboardLights.
|
||||||
mov eax, [.buffer]
|
mov eax, [.buffer]
|
||||||
sub eax, 8
|
sub eax, 8
|
||||||
call Kfree
|
invoke Kfree
|
||||||
ret 20
|
ret 20
|
||||||
endp
|
endp
|
@ -34,7 +34,7 @@ ends
|
|||||||
proc mouse_driver_add_device
|
proc mouse_driver_add_device
|
||||||
; Just allocate memory; no initialization needed.
|
; Just allocate memory; no initialization needed.
|
||||||
movi eax, sizeof.mouse_device_data
|
movi eax, sizeof.mouse_device_data
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ endp
|
|||||||
proc mouse_driver_disconnect
|
proc mouse_driver_disconnect
|
||||||
; Free the allocated memory.
|
; Free the allocated memory.
|
||||||
mov eax, edi
|
mov eax, edi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ endp
|
|||||||
; in: edi -> mouse_device_data (pointer returned from mouse_driver_add_device)
|
; in: edi -> mouse_device_data (pointer returned from mouse_driver_add_device)
|
||||||
proc mouse_driver_end_packet
|
proc mouse_driver_end_packet
|
||||||
; Call the kernel, passing collected state.
|
; Call the kernel, passing collected state.
|
||||||
stdcall SetMouseData, \
|
invoke SetMouseData, \
|
||||||
[edi+mouse_device_data.buttons], \
|
[edi+mouse_device_data.buttons], \
|
||||||
[edi+mouse_device_data.dx], \
|
[edi+mouse_device_data.dx], \
|
||||||
[edi+mouse_device_data.dy], \
|
[edi+mouse_device_data.dy], \
|
@ -353,7 +353,7 @@ parse_descr_label:
|
|||||||
mov [last_collection], eax
|
mov [last_collection], eax
|
||||||
; 1b. Allocate state of global items.
|
; 1b. Allocate state of global items.
|
||||||
movi eax, sizeof.global_items
|
movi eax, sizeof.global_items
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .memory_error
|
jz .memory_error
|
||||||
; 1c. Zero-initialize it and move pointer to edi.
|
; 1c. Zero-initialize it and move pointer to edi.
|
||||||
@ -373,7 +373,7 @@ parse_descr_label:
|
|||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
push [eax+usage_list_item.next]
|
push [eax+usage_list_item.next]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
pop eax
|
pop eax
|
||||||
jmp @b
|
jmp @b
|
||||||
@@:
|
@@:
|
||||||
@ -496,7 +496,7 @@ end if
|
|||||||
cmp [ebx+report_set.data], 0
|
cmp [ebx+report_set.data], 0
|
||||||
jnz .invalid_report
|
jnz .invalid_report
|
||||||
mov eax, 256*4
|
mov eax, 256*4
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .memory_error
|
jz .memory_error
|
||||||
mov [ebx+report_set.data], eax
|
mov [ebx+report_set.data], eax
|
||||||
@ -521,7 +521,7 @@ end if
|
|||||||
jnz .report_allocated
|
jnz .report_allocated
|
||||||
; 7b. Allocate.
|
; 7b. Allocate.
|
||||||
movi eax, sizeof.report
|
movi eax, sizeof.report
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .memory_error
|
jz .memory_error
|
||||||
; 7c. Initialize.
|
; 7c. Initialize.
|
||||||
@ -568,7 +568,7 @@ end if
|
|||||||
mov edx, [num_usage_ranges]
|
mov edx, [num_usage_ranges]
|
||||||
lea eax, [eax+edx*sizeof.usage_range+4]
|
lea eax, [eax+edx*sizeof.usage_range+4]
|
||||||
@@:
|
@@:
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
pop edx
|
pop edx
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .memory_error
|
jz .memory_error
|
||||||
@ -688,7 +688,7 @@ end if
|
|||||||
; allocate, zero-initialize, update parent, if there is one,
|
; allocate, zero-initialize, update parent, if there is one,
|
||||||
; make it current.
|
; make it current.
|
||||||
movi eax, sizeof.collection
|
movi eax, sizeof.collection
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .memory_error
|
jz .memory_error
|
||||||
push eax edi
|
push eax edi
|
||||||
@ -817,7 +817,7 @@ end if
|
|||||||
; For Push, allocate new global_items structure,
|
; For Push, allocate new global_items structure,
|
||||||
; initialize from the current one and make it current.
|
; initialize from the current one and make it current.
|
||||||
movi eax, sizeof.global_items
|
movi eax, sizeof.global_items
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .memory_error
|
jz .memory_error
|
||||||
push esi eax
|
push esi eax
|
||||||
@ -835,7 +835,7 @@ end if
|
|||||||
jz .invalid_report
|
jz .invalid_report
|
||||||
push eax
|
push eax
|
||||||
xchg eax, edi
|
xchg eax, edi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
pop edi
|
pop edi
|
||||||
jmp .item_parsed
|
jmp .item_parsed
|
||||||
; -------------------------------- Local items --------------------------------
|
; -------------------------------- Local items --------------------------------
|
||||||
@ -862,7 +862,7 @@ end if
|
|||||||
push 1
|
push 1
|
||||||
.new_usage:
|
.new_usage:
|
||||||
movi eax, sizeof.usage_list_item
|
movi eax, sizeof.usage_list_item
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
pop edx
|
pop edx
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .memory_error
|
jz .memory_error
|
||||||
@ -912,7 +912,7 @@ end if
|
|||||||
inc [delimiter_depth]
|
inc [delimiter_depth]
|
||||||
push esi
|
push esi
|
||||||
mov esi, delimiter_note
|
mov esi, delimiter_note
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi
|
pop esi
|
||||||
jmp .item_parsed
|
jmp .item_parsed
|
||||||
.delimiter.close:
|
.delimiter.close:
|
||||||
@ -954,14 +954,14 @@ end if
|
|||||||
.memory_error:
|
.memory_error:
|
||||||
mov esi, nomemory_msg
|
mov esi, nomemory_msg
|
||||||
.end_str:
|
.end_str:
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
.end:
|
.end:
|
||||||
; Free all global_items structures.
|
; Free all global_items structures.
|
||||||
test edi, edi
|
test edi, edi
|
||||||
jz @f
|
jz @f
|
||||||
push [edi+global_items.next]
|
push [edi+global_items.next]
|
||||||
xchg eax, edi
|
xchg eax, edi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
pop edi
|
pop edi
|
||||||
jmp .end
|
jmp .end
|
||||||
@@:
|
@@:
|
||||||
@ -971,7 +971,7 @@ end if
|
|||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
push [eax+usage_list_item.next]
|
push [eax+usage_list_item.next]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
pop eax
|
pop eax
|
||||||
jmp @b
|
jmp @b
|
||||||
@@:
|
@@:
|
||||||
@ -1116,7 +1116,7 @@ macro hid_cleanup
|
|||||||
mov eax, [esi+collection.parent]
|
mov eax, [esi+collection.parent]
|
||||||
@@:
|
@@:
|
||||||
xchg eax, esi
|
xchg eax, esi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
jmp .free_collections
|
jmp .free_collections
|
||||||
.collections_done:
|
.collections_done:
|
||||||
; 3. Free all three report sets.
|
; 3. Free all three report sets.
|
||||||
@ -1136,19 +1136,19 @@ macro hid_cleanup
|
|||||||
test eax, eax
|
test eax, eax
|
||||||
jz .field_done
|
jz .field_done
|
||||||
push [eax+report_field_group.next]
|
push [eax+report_field_group.next]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
pop eax
|
pop eax
|
||||||
jmp .field_loop
|
jmp .field_loop
|
||||||
.field_done:
|
.field_done:
|
||||||
mov eax, [edi+report.next]
|
mov eax, [edi+report.next]
|
||||||
xchg eax, edi
|
xchg eax, edi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
jmp .report_loop
|
jmp .report_loop
|
||||||
.report_done:
|
.report_done:
|
||||||
cmp [esi+report_set.numbered], 0
|
cmp [esi+report_set.numbered], 0
|
||||||
jz @f
|
jz @f
|
||||||
mov eax, [esi+report_set.data]
|
mov eax, [esi+report_set.data]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
@@:
|
@@:
|
||||||
add esi, sizeof.report_set
|
add esi, sizeof.report_set
|
||||||
dec dword [esp]
|
dec dword [esp]
|
@ -1,5 +1,6 @@
|
|||||||
; standard driver stuff
|
; standard driver stuff; version of driver model = 5
|
||||||
format MS COFF
|
format PE DLL native 0.05
|
||||||
|
entry START
|
||||||
|
|
||||||
DEBUG = 1
|
DEBUG = 1
|
||||||
|
|
||||||
@ -7,14 +8,8 @@ DEBUG = 1
|
|||||||
__DEBUG__ = 1
|
__DEBUG__ = 1
|
||||||
__DEBUG_LEVEL__ = 1
|
__DEBUG_LEVEL__ = 1
|
||||||
|
|
||||||
include '../proc32.inc'
|
|
||||||
include '../imports.inc'
|
|
||||||
include '../fdo.inc'
|
|
||||||
include '../../struct.inc'
|
include '../../struct.inc'
|
||||||
|
|
||||||
public START
|
|
||||||
public version
|
|
||||||
|
|
||||||
; Compile-time settings.
|
; Compile-time settings.
|
||||||
; If set, the code will dump all descriptors as they are read to the debug board.
|
; If set, the code will dump all descriptors as they are read to the debug board.
|
||||||
USB_DUMP_DESCRIPTORS = 1
|
USB_DUMP_DESCRIPTORS = 1
|
||||||
@ -103,12 +98,17 @@ 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 writable executable
|
||||||
|
include '../../macros.inc'
|
||||||
|
include '../../proc32.inc'
|
||||||
|
include '../../peimport.inc'
|
||||||
|
include '../../fdo.inc'
|
||||||
; 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 ?
|
||||||
|
.cmdline 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.
|
||||||
@ -118,10 +118,10 @@ end virtual
|
|||||||
; 2. Register self as a USB driver.
|
; 2. Register self as a USB driver.
|
||||||
; The name is my_driver = 'usbhid'; IOCTL interface is not supported;
|
; The name is my_driver = 'usbhid'; IOCTL interface is not supported;
|
||||||
; usb_functions is an offset of a structure with callback functions.
|
; usb_functions is an offset of a structure with callback functions.
|
||||||
stdcall RegUSBDriver, my_driver, eax, usb_functions
|
invoke RegUSBDriver, my_driver, eax, usb_functions
|
||||||
; 3. Return the returned value of RegUSBDriver.
|
; 3. Return the returned value of RegUSBDriver.
|
||||||
.nothing:
|
.nothing:
|
||||||
ret 4
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; This procedure is called when new HID device is detected.
|
; This procedure is called when new HID device is detected.
|
||||||
@ -138,11 +138,11 @@ 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
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
mov esi, nomemory_msg
|
mov esi, nomemory_msg
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
jmp .return0
|
jmp .return0
|
||||||
@@:
|
@@:
|
||||||
; zero-initialize it
|
; zero-initialize it
|
||||||
@ -215,11 +215,11 @@ end virtual
|
|||||||
.cfgerror:
|
.cfgerror:
|
||||||
; 6a. Print a message.
|
; 6a. Print a message.
|
||||||
mov esi, invalid_config_descr_msg
|
mov esi, invalid_config_descr_msg
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
; 6b. Free memory allocated for device data.
|
; 6b. Free memory allocated for device data.
|
||||||
.free:
|
.free:
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
call Kfree
|
invoke Kfree
|
||||||
.return0:
|
.return0:
|
||||||
; 6c. Return an error.
|
; 6c. Return an error.
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -255,7 +255,7 @@ end virtual
|
|||||||
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
|
invoke 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
|
||||||
@ -295,7 +295,7 @@ end virtual
|
|||||||
.cfgerror:
|
.cfgerror:
|
||||||
mov esi, invalid_config_descr_msg
|
mov esi, invalid_config_descr_msg
|
||||||
.abort_with_msg:
|
.abort_with_msg:
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
.found_report:
|
.found_report:
|
||||||
; 2. Send request for the Report descriptor.
|
; 2. Send request for the Report descriptor.
|
||||||
@ -304,7 +304,7 @@ end virtual
|
|||||||
test eax, eax
|
test eax, eax
|
||||||
jz .cfgerror
|
jz .cfgerror
|
||||||
push eax
|
push eax
|
||||||
call Kmalloc
|
invoke 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
|
||||||
@ -320,13 +320,13 @@ end virtual
|
|||||||
(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], \
|
invoke 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
|
invoke 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
|
||||||
@ -353,7 +353,7 @@ endl
|
|||||||
.generic_fail:
|
.generic_fail:
|
||||||
push esi
|
push esi
|
||||||
mov esi, reportfail
|
mov esi, reportfail
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi
|
pop esi
|
||||||
jmp .exit
|
jmp .exit
|
||||||
.has_something:
|
.has_something:
|
||||||
@ -386,7 +386,7 @@ end if
|
|||||||
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
|
invoke 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
|
||||||
@ -418,11 +418,11 @@ end if
|
|||||||
; 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
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
mov esi, nomemory_msg
|
mov esi, nomemory_msg
|
||||||
call SysMsgBoardStr
|
invoke 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
|
||||||
@ -430,7 +430,7 @@ end if
|
|||||||
call ask_for_input
|
call ask_for_input
|
||||||
got_report.exit:
|
got_report.exit:
|
||||||
mov eax, [buffer]
|
mov eax, [buffer]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ 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, \
|
invoke 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], \
|
||||||
@ -492,7 +492,7 @@ endl
|
|||||||
ret
|
ret
|
||||||
.fail:
|
.fail:
|
||||||
mov esi, transfer_error_msg
|
mov esi, transfer_error_msg
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -507,12 +507,12 @@ 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
|
invoke 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
|
invoke 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
|
||||||
@ -534,9 +534,7 @@ 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.
|
|
||||||
align 4
|
align 4
|
||||||
version dd 50005h
|
|
||||||
; Structure with callback functions.
|
; Structure with callback functions.
|
||||||
usb_functions:
|
usb_functions:
|
||||||
dd 12
|
dd 12
|
||||||
@ -549,5 +547,6 @@ include_debug_strings
|
|||||||
; Workers data
|
; Workers data
|
||||||
workers_globals
|
workers_globals
|
||||||
|
|
||||||
; for uninitialized data
|
align 4
|
||||||
;section '.data' data readable writable align 16
|
data fixups
|
||||||
|
end data
|
@ -1,5 +1,6 @@
|
|||||||
; standard driver stuff
|
; standard driver stuff; version of driver model = 5
|
||||||
format MS COFF
|
format PE DLL native 0.05
|
||||||
|
entry START
|
||||||
|
|
||||||
DEBUG = 1
|
DEBUG = 1
|
||||||
DUMP_PACKETS = 0
|
DUMP_PACKETS = 0
|
||||||
@ -8,12 +9,7 @@ DUMP_PACKETS = 0
|
|||||||
__DEBUG__ = 1
|
__DEBUG__ = 1
|
||||||
__DEBUG_LEVEL__ = 1
|
__DEBUG_LEVEL__ = 1
|
||||||
|
|
||||||
include 'proc32.inc'
|
include '../struct.inc'
|
||||||
include 'imports.inc'
|
|
||||||
include 'fdo.inc'
|
|
||||||
|
|
||||||
public START
|
|
||||||
public version
|
|
||||||
|
|
||||||
; USB constants
|
; USB constants
|
||||||
DEVICE_DESCR_TYPE = 1
|
DEVICE_DESCR_TYPE = 1
|
||||||
@ -29,43 +25,37 @@ BULK_PIPE = 2
|
|||||||
INTERRUPT_PIPE = 3
|
INTERRUPT_PIPE = 3
|
||||||
|
|
||||||
; USB structures
|
; USB structures
|
||||||
virtual at 0
|
struct config_descr
|
||||||
config_descr:
|
bLength db ?
|
||||||
.bLength db ?
|
bDescriptorType db ?
|
||||||
.bDescriptorType db ?
|
wTotalLength dw ?
|
||||||
.wTotalLength dw ?
|
bNumInterfaces db ?
|
||||||
.bNumInterfaces db ?
|
bConfigurationValue db ?
|
||||||
.bConfigurationValue db ?
|
iConfiguration db ?
|
||||||
.iConfiguration db ?
|
bmAttributes db ?
|
||||||
.bmAttributes db ?
|
bMaxPower db ?
|
||||||
.bMaxPower db ?
|
ends
|
||||||
.sizeof:
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
virtual at 0
|
struct interface_descr
|
||||||
interface_descr:
|
bLength db ?
|
||||||
.bLength db ?
|
bDescriptorType db ?
|
||||||
.bDescriptorType db ?
|
bInterfaceNumber db ?
|
||||||
.bInterfaceNumber db ?
|
bAlternateSetting db ?
|
||||||
.bAlternateSetting db ?
|
bNumEndpoints db ?
|
||||||
.bNumEndpoints db ?
|
bInterfaceClass db ?
|
||||||
.bInterfaceClass db ?
|
bInterfaceSubClass db ?
|
||||||
.bInterfaceSubClass db ?
|
bInterfaceProtocol db ?
|
||||||
.bInterfaceProtocol db ?
|
iInterface db ?
|
||||||
.iInterface db ?
|
ends
|
||||||
.sizeof:
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
virtual at 0
|
struct endpoint_descr
|
||||||
endpoint_descr:
|
bLength db ?
|
||||||
.bLength db ?
|
bDescriptorType db ?
|
||||||
.bDescriptorType db ?
|
bEndpointAddress db ?
|
||||||
.bEndpointAddress db ?
|
bmAttributes db ?
|
||||||
.bmAttributes db ?
|
wMaxPacketSize dw ?
|
||||||
.wMaxPacketSize dw ?
|
bInterval db ?
|
||||||
.bInterval db ?
|
ends
|
||||||
.sizeof:
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
; Mass storage protocol constants, USB layer
|
; Mass storage protocol constants, USB layer
|
||||||
REQUEST_GETMAXLUN = 0xFE ; get max lun
|
REQUEST_GETMAXLUN = 0xFE ; get max lun
|
||||||
@ -73,38 +63,28 @@ REQUEST_BORESET = 0xFF ; bulk-only reset
|
|||||||
|
|
||||||
; Mass storage protocol structures, USB layer
|
; Mass storage protocol structures, USB layer
|
||||||
; Sent from host to device in the first stage of an operation.
|
; Sent from host to device in the first stage of an operation.
|
||||||
struc command_block_wrapper
|
struct command_block_wrapper
|
||||||
{
|
Signature dd ? ; the constant 'USBC'
|
||||||
.Signature dd ? ; the constant 'USBC'
|
Tag dd ? ; identifies response with request
|
||||||
.Tag dd ? ; identifies response with request
|
Length dd ? ; length of data-transport phase
|
||||||
.Length dd ? ; length of data-transport phase
|
Flags db ? ; one of CBW_FLAG_*
|
||||||
.Flags db ? ; one of CBW_FLAG_*
|
|
||||||
CBW_FLAG_OUT = 0
|
CBW_FLAG_OUT = 0
|
||||||
CBW_FLAG_IN = 80h
|
CBW_FLAG_IN = 80h
|
||||||
.LUN db ? ; addressed unit
|
LUN db ? ; addressed unit
|
||||||
.CommandLength db ? ; the length of the following field
|
CommandLength db ? ; the length of the following field
|
||||||
.Command rb 16
|
Command rb 16
|
||||||
.sizeof:
|
ends
|
||||||
}
|
|
||||||
virtual at 0
|
|
||||||
command_block_wrapper command_block_wrapper
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
; Sent from device to host in the last stage of an operation.
|
; Sent from device to host in the last stage of an operation.
|
||||||
struc command_status_wrapper
|
struct command_status_wrapper
|
||||||
{
|
Signature dd ? ; the constant 'USBS'
|
||||||
.Signature dd ? ; the constant 'USBS'
|
Tag dd ? ; identifies response with request
|
||||||
.Tag dd ? ; identifies response with request
|
LengthRest dd ? ; .Length - (size of data which were transferred)
|
||||||
.LengthRest dd ? ; .Length - (size of data which were transferred)
|
Status db ? ; one of CSW_STATUS_*
|
||||||
.Status db ? ; one of CSW_STATUS_*
|
|
||||||
CSW_STATUS_OK = 0
|
CSW_STATUS_OK = 0
|
||||||
CSW_STATUS_FAIL = 1
|
CSW_STATUS_FAIL = 1
|
||||||
CSW_STATUS_FATAL = 2
|
CSW_STATUS_FATAL = 2
|
||||||
.sizeof:
|
ends
|
||||||
}
|
|
||||||
virtual at 0
|
|
||||||
command_status_wrapper command_status_wrapper
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
; Constants of SCSI layer
|
; Constants of SCSI layer
|
||||||
SCSI_REQUEST_SENSE = 3
|
SCSI_REQUEST_SENSE = 3
|
||||||
@ -133,73 +113,62 @@ SENSE_MISCOMPARE = 14
|
|||||||
|
|
||||||
; Structures of SCSI layer
|
; Structures of SCSI layer
|
||||||
; Result of SCSI INQUIRY request.
|
; Result of SCSI INQUIRY request.
|
||||||
struc inquiry_data
|
struct inquiry_data
|
||||||
{
|
PeripheralDevice db ? ; lower 5 bits are PeripheralDeviceType
|
||||||
.PeripheralDevice db ? ; lower 5 bits are PeripheralDeviceType
|
|
||||||
; upper 3 bits are PeripheralQualifier
|
; upper 3 bits are PeripheralQualifier
|
||||||
.RemovableMedium db ? ; upper bit is RemovableMedium
|
RemovableMedium db ? ; upper bit is RemovableMedium
|
||||||
; other bits are for compatibility
|
; other bits are for compatibility
|
||||||
.Version db ? ; lower 3 bits are ANSI-Approved version
|
Version db ? ; lower 3 bits are ANSI-Approved version
|
||||||
; next 3 bits are ECMA version
|
; next 3 bits are ECMA version
|
||||||
; upper 2 bits are ISO version
|
; upper 2 bits are ISO version
|
||||||
.ResponseDataFormat db ? ; lower 4 bits are ResponseDataFormat
|
ResponseDataFormat db ? ; lower 4 bits are ResponseDataFormat
|
||||||
; bit 6 is TrmIOP
|
; bit 6 is TrmIOP
|
||||||
; bit 7 is AENC
|
; bit 7 is AENC
|
||||||
.AdditionalLength db ?
|
AdditionalLength db ?
|
||||||
dw ? ; reserved
|
dw ? ; reserved
|
||||||
.Flags db ?
|
Flags db ?
|
||||||
.VendorID rb 8 ; vendor ID, big-endian
|
VendorID rb 8 ; vendor ID, big-endian
|
||||||
.ProductID rb 16 ; product ID, big-endian
|
ProductID rb 16 ; product ID, big-endian
|
||||||
.ProductRevBE dd ? ; product revision, big-endian
|
ProductRevBE dd ? ; product revision, big-endian
|
||||||
.sizeof:
|
ends
|
||||||
}
|
|
||||||
virtual at 0
|
|
||||||
inquiry_data inquiry_data
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
struc sense_data
|
struct sense_data
|
||||||
{
|
ErrorCode db ? ; lower 7 bits are error code:
|
||||||
.ErrorCode db ? ; lower 7 bits are error code:
|
|
||||||
; 70h = current error,
|
; 70h = current error,
|
||||||
; 71h = deferred error
|
; 71h = deferred error
|
||||||
; upper bit is InformationValid
|
; upper bit is InformationValid
|
||||||
.SegmentNumber db ? ; number of segment descriptor
|
SegmentNumber db ? ; number of segment descriptor
|
||||||
; for commands COPY [+VERIFY], COMPARE
|
; for commands COPY [+VERIFY], COMPARE
|
||||||
.SenseKey db ? ; bits 0-3 are one of SENSE_*
|
SenseKey db ? ; bits 0-3 are one of SENSE_*
|
||||||
; bit 4 is reserved
|
; bit 4 is reserved
|
||||||
; bit 5 is IncorrectLengthIndicator
|
; bit 5 is IncorrectLengthIndicator
|
||||||
; bits 6 and 7 are used by
|
; bits 6 and 7 are used by
|
||||||
; sequential-access devices
|
; sequential-access devices
|
||||||
.Information dd ? ; command-specific
|
Information dd ? ; command-specific
|
||||||
.AdditionalLength db ? ; length of data starting here
|
AdditionalLength db ? ; length of data starting here
|
||||||
.CommandInformation dd ? ; command-specific
|
CommandInformation dd ? ; command-specific
|
||||||
.AdditionalSenseCode db ? ; \ more detailed error code
|
AdditionalSenseCode db ? ; \ more detailed error code
|
||||||
.AdditionalSenseQual db ? ; / standard has a large table of them
|
AdditionalSenseQual db ? ; / standard has a large table of them
|
||||||
.FRUCode db ? ; which part of device has failed
|
FRUCode db ? ; which part of device has failed
|
||||||
; (device-specific, not regulated)
|
; (device-specific, not regulated)
|
||||||
.SenseKeySpecific rb 3 ; depends on SenseKey
|
SenseKeySpecific rb 3 ; depends on SenseKey
|
||||||
.sizeof:
|
ends
|
||||||
}
|
|
||||||
virtual at 0
|
|
||||||
sense_data sense_data
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
; Device data
|
; Device data
|
||||||
; USB Mass storage device has one or more logical units, identified by LUN,
|
; USB Mass storage device has one or more logical units, identified by LUN,
|
||||||
; logical unit number. The highest value of LUN, that is, number of units
|
; logical unit number. The highest value of LUN, that is, number of units
|
||||||
; minus 1, can be obtained via control request Get Max LUN.
|
; minus 1, can be obtained via control request Get Max LUN.
|
||||||
virtual at 0
|
struct usb_device_data
|
||||||
usb_device_data:
|
ConfigPipe dd ? ; configuration pipe
|
||||||
.ConfigPipe dd ? ; configuration pipe
|
OutPipe dd ? ; pipe for OUT bulk endpoint
|
||||||
.OutPipe dd ? ; pipe for OUT bulk endpoint
|
InPipe dd ? ; pipe for IN bulk endpoint
|
||||||
.InPipe dd ? ; pipe for IN bulk endpoint
|
MaxLUN dd ? ; maximum Logical Unit Number
|
||||||
.MaxLUN dd ? ; maximum Logical Unit Number
|
LogicalDevices dd ? ; pointer to array of usb_unit_data
|
||||||
.LogicalDevices dd ? ; pointer to array of usb_unit_data
|
|
||||||
; 1 for a connected USB device, 1 for each disk device
|
; 1 for a connected USB device, 1 for each disk device
|
||||||
; the structure can be freed when .NumReferences decreases to zero
|
; the structure can be freed when .NumReferences decreases to zero
|
||||||
.NumReferences dd ? ; number of references
|
NumReferences dd ? ; number of references
|
||||||
.ConfigRequest rb 8 ; buffer for configuration requests
|
ConfigRequest rb 8 ; buffer for configuration requests
|
||||||
.LengthRest dd ? ; Length - (size of data which were transferred)
|
LengthRest dd ? ; Length - (size of data which were transferred)
|
||||||
; All requests to a given device are serialized,
|
; All requests to a given device are serialized,
|
||||||
; only one request to a given device can be processed at a time.
|
; only one request to a given device can be processed at a time.
|
||||||
; The current request and all pending requests are organized in the following
|
; The current request and all pending requests are organized in the following
|
||||||
@ -208,46 +177,42 @@ usb_device_data:
|
|||||||
; data stage is not tagged (unlike command_*_wrapper), so the only way to know
|
; data stage is not tagged (unlike command_*_wrapper), so the only way to know
|
||||||
; what request the data are associated with is to guarantee that only one
|
; what request the data are associated with is to guarantee that only one
|
||||||
; request is processing at the time.
|
; request is processing at the time.
|
||||||
.RequestsQueue rd 2
|
RequestsQueue rd 2
|
||||||
.QueueLock rd 3 ; protects .RequestsQueue
|
QueueLock rd 3 ; protects .RequestsQueue
|
||||||
.InquiryData inquiry_data ; information about device
|
InquiryData inquiry_data ; information about device
|
||||||
; data for the current request
|
; data for the current request
|
||||||
.Command command_block_wrapper
|
Command command_block_wrapper
|
||||||
.DeviceDisconnected db ?
|
DeviceDisconnected db ?
|
||||||
.Status command_status_wrapper
|
Status command_status_wrapper
|
||||||
.Sense sense_data
|
Sense sense_data
|
||||||
.sizeof:
|
ends
|
||||||
end virtual
|
|
||||||
|
|
||||||
; Information about one logical device.
|
; Information about one logical device.
|
||||||
virtual at 0
|
struct usb_unit_data
|
||||||
usb_unit_data:
|
Parent dd ? ; pointer to parent usb_device_data
|
||||||
.Parent dd ? ; pointer to parent usb_device_data
|
LUN db ? ; index in usb_device_data.LogicalDevices array
|
||||||
.LUN db ? ; index in usb_device_data.LogicalDevices array
|
DiskIndex db ? ; for name "usbhd<index>"
|
||||||
.DiskIndex db ? ; for name "usbhd<index>"
|
MediaPresent db ?
|
||||||
.MediaPresent db ?
|
|
||||||
db ? ; alignment
|
db ? ; alignment
|
||||||
.DiskDevice dd ? ; handle of disk device or NULL
|
DiskDevice dd ? ; handle of disk device or NULL
|
||||||
.SectorSize dd ? ; sector size
|
SectorSize dd ? ; sector size
|
||||||
; For some devices, the first request to the medium fails with 'unit not ready'.
|
; For some devices, the first request to the medium fails with 'unit not ready'.
|
||||||
; When the code sees this status, it retries the command several times.
|
; When the code sees this status, it retries the command several times.
|
||||||
; Two following variables track the retry count and total time for those;
|
; Two following variables track the retry count and total time for those;
|
||||||
; total time is currently used only for debug output.
|
; total time is currently used only for debug output.
|
||||||
.UnitReadyAttempts dd ?
|
UnitReadyAttempts dd ?
|
||||||
.TimerTicks dd ?
|
TimerTicks dd ?
|
||||||
.sizeof:
|
ends
|
||||||
end virtual
|
|
||||||
|
|
||||||
; This is the structure for items in the queue usb_device_data.RequestsQueue.
|
; This is the structure for items in the queue usb_device_data.RequestsQueue.
|
||||||
virtual at 0
|
struct request_queue_item
|
||||||
request_queue_item:
|
Next dd ? ; next item in the queue
|
||||||
.Next dd ? ; next item in the queue
|
Prev dd ? ; prev item in the queue
|
||||||
.Prev dd ? ; prev item in the queue
|
ReqBuilder dd ? ; procedure to fill command_block_wrapper
|
||||||
.ReqBuilder dd ? ; procedure to fill command_block_wrapper
|
Buffer dd ? ; input or output data
|
||||||
.Buffer dd ? ; input or output data
|
|
||||||
; (length is command_block_wrapper.Length)
|
; (length is command_block_wrapper.Length)
|
||||||
.Callback dd ? ; procedure to call in the end of transfer
|
Callback dd ? ; procedure to call in the end of transfer
|
||||||
.UserData dd ? ; passed as-is to .Callback
|
UserData dd ? ; passed as-is to .Callback
|
||||||
; There are 3 possible stages of any request, one of them optional:
|
; There are 3 possible stages of any request, one of them optional:
|
||||||
; command stage (host sends command_block_wrapper to device),
|
; command stage (host sends command_block_wrapper to device),
|
||||||
; optional data stage,
|
; optional data stage,
|
||||||
@ -255,16 +220,21 @@ request_queue_item:
|
|||||||
; Also, if a request fails, the code queues additional request
|
; Also, if a request fails, the code queues additional request
|
||||||
; SCSI_REQUEST_SENSE; sense_data from SCSI_REQUEST_SENSE
|
; SCSI_REQUEST_SENSE; sense_data from SCSI_REQUEST_SENSE
|
||||||
; contains some information about the error.
|
; contains some information about the error.
|
||||||
.Stage db ?
|
Stage db ?
|
||||||
.sizeof:
|
ends
|
||||||
end virtual
|
|
||||||
|
section '.flat' code readable writable executable
|
||||||
|
include '../proc32.inc'
|
||||||
|
include '../peimport.inc'
|
||||||
|
include '../fdo.inc'
|
||||||
|
include '../macros.inc'
|
||||||
|
|
||||||
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 ? ; DRV_ENTRY or DRV_EXIT
|
.reason dd ? ; DRV_ENTRY or DRV_EXIT
|
||||||
|
.cmdline 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.
|
||||||
@ -273,14 +243,14 @@ end virtual
|
|||||||
jnz .nothing
|
jnz .nothing
|
||||||
; 2. Initialize: we have one global mutex.
|
; 2. Initialize: we have one global mutex.
|
||||||
mov ecx, free_numbers_lock
|
mov ecx, free_numbers_lock
|
||||||
call MutexInit
|
invoke MutexInit
|
||||||
; 3. Register self as a USB driver.
|
; 3. Register self as a USB driver.
|
||||||
; The name is my_driver = 'usbstor'; IOCTL interface is not supported;
|
; The name is my_driver = 'usbstor'; IOCTL interface is not supported;
|
||||||
; usb_functions is an offset of a structure with callback functions.
|
; usb_functions is an offset of a structure with callback functions.
|
||||||
stdcall RegUSBDriver, my_driver, 0, usb_functions
|
invoke RegUSBDriver, my_driver, 0, usb_functions
|
||||||
; 4. Return the returned value of RegUSBDriver.
|
; 4. Return the returned value of RegUSBDriver.
|
||||||
.nothing:
|
.nothing:
|
||||||
ret 4
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; Helper procedures to work with requests queue.
|
; Helper procedures to work with requests queue.
|
||||||
@ -298,12 +268,12 @@ virtual at esp
|
|||||||
.UserData dd ? ; request_queue_item.UserData
|
.UserData dd ? ; request_queue_item.UserData
|
||||||
end virtual
|
end virtual
|
||||||
; 1. Allocate the memory for the request description.
|
; 1. Allocate the memory for the request description.
|
||||||
movi eax, request_queue_item.sizeof
|
movi eax, sizeof.request_queue_item
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
mov esi, nomemory
|
mov esi, nomemory
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi ebx
|
pop esi ebx
|
||||||
ret 20
|
ret 20
|
||||||
@@:
|
@@:
|
||||||
@ -322,7 +292,7 @@ end virtual
|
|||||||
; 4. Lock the queue.
|
; 4. Lock the queue.
|
||||||
mov esi, [.device]
|
mov esi, [.device]
|
||||||
lea ecx, [esi+usb_device_data.QueueLock]
|
lea ecx, [esi+usb_device_data.QueueLock]
|
||||||
call MutexLock
|
invoke MutexLock
|
||||||
; 5. Insert the request to the tail of the queue.
|
; 5. Insert the request to the tail of the queue.
|
||||||
add esi, usb_device_data.RequestsQueue
|
add esi, usb_device_data.RequestsQueue
|
||||||
mov edx, [esi+request_queue_item.Prev]
|
mov edx, [esi+request_queue_item.Prev]
|
||||||
@ -340,7 +310,7 @@ end virtual
|
|||||||
call setup_request
|
call setup_request
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
.unlock:
|
.unlock:
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
; 9. Return.
|
; 9. Return.
|
||||||
.nothing:
|
.nothing:
|
||||||
pop esi ebx
|
pop esi ebx
|
||||||
@ -369,7 +339,7 @@ end if
|
|||||||
stdcall [ebx+request_queue_item.Callback], esi, [ebx+request_queue_item.UserData]
|
stdcall [ebx+request_queue_item.Callback], esi, [ebx+request_queue_item.UserData]
|
||||||
; 4. Lock the queue.
|
; 4. Lock the queue.
|
||||||
lea ecx, [esi+usb_device_data.QueueLock]
|
lea ecx, [esi+usb_device_data.QueueLock]
|
||||||
call MutexLock
|
invoke MutexLock
|
||||||
; 5. Remove the request.
|
; 5. Remove the request.
|
||||||
lea edx, [esi+usb_device_data.RequestsQueue]
|
lea edx, [esi+usb_device_data.RequestsQueue]
|
||||||
mov eax, [ebx+request_queue_item.Next]
|
mov eax, [ebx+request_queue_item.Next]
|
||||||
@ -378,14 +348,14 @@ end if
|
|||||||
; 6. Free the request memory.
|
; 6. Free the request memory.
|
||||||
push eax edx
|
push eax edx
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
call Kfree
|
invoke Kfree
|
||||||
pop edx ebx
|
pop edx ebx
|
||||||
; 7. If there is a next request, start processing.
|
; 7. If there is a next request, start processing.
|
||||||
cmp ebx, edx
|
cmp ebx, edx
|
||||||
jnz setup_request
|
jnz setup_request
|
||||||
; 8. Unlock the queue and return.
|
; 8. Unlock the queue and return.
|
||||||
lea ecx, [esi+usb_device_data.QueueLock]
|
lea ecx, [esi+usb_device_data.QueueLock]
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -410,14 +380,14 @@ proc setup_request
|
|||||||
lea edx, [esi+usb_device_data.ConfigRequest]
|
lea edx, [esi+usb_device_data.ConfigRequest]
|
||||||
mov word [edx], (REQUEST_BORESET shl 8) + 21h ; class request
|
mov word [edx], (REQUEST_BORESET shl 8) + 21h ; class request
|
||||||
mov word [edx+6], ax ; length = 0
|
mov word [edx+6], ax ; length = 0
|
||||||
stdcall USBControlTransferAsync, [esi+usb_device_data.ConfigPipe], edx, eax, eax, recovery_callback1, esi, eax
|
invoke USBControlTransferAsync, [esi+usb_device_data.ConfigPipe], edx, eax, eax, recovery_callback1, esi, eax
|
||||||
; 2b. Fail here = fatal error.
|
; 2b. Fail here = fatal error.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .fatal
|
jz .fatal
|
||||||
; 2c. Otherwise, unlock the queue and return. recovery_callback1 will continue processing.
|
; 2c. Otherwise, unlock the queue and return. recovery_callback1 will continue processing.
|
||||||
.unlock_return:
|
.unlock_return:
|
||||||
lea ecx, [esi+usb_device_data.QueueLock]
|
lea ecx, [esi+usb_device_data.QueueLock]
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
ret
|
ret
|
||||||
.norecovery:
|
.norecovery:
|
||||||
; 3. Send the command. Fail (no memory or device disconnected) = fatal error.
|
; 3. Send the command. Fail (no memory or device disconnected) = fatal error.
|
||||||
@ -429,7 +399,7 @@ proc setup_request
|
|||||||
; 4. Fatal error. Set status = FATAL, unlock the queue, complete the request.
|
; 4. Fatal error. Set status = FATAL, unlock the queue, complete the request.
|
||||||
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
|
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
|
||||||
lea ecx, [esi+usb_device_data.QueueLock]
|
lea ecx, [esi+usb_device_data.QueueLock]
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
jmp complete_request
|
jmp complete_request
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -453,11 +423,11 @@ proc request_stage1
|
|||||||
if DUMP_PACKETS
|
if DUMP_PACKETS
|
||||||
DEBUGF 1,'K : USBSTOR out:'
|
DEBUGF 1,'K : USBSTOR out:'
|
||||||
mov eax, edx
|
mov eax, edx
|
||||||
mov ecx, command_block_wrapper.sizeof
|
mov ecx, sizeof.command_block_wrapper
|
||||||
call debug_dump
|
call debug_dump
|
||||||
DEBUGF 1,'\n'
|
DEBUGF 1,'\n'
|
||||||
end if
|
end if
|
||||||
stdcall USBNormalTransferAsync, [esi+usb_device_data.OutPipe], edx, command_block_wrapper.sizeof, request_callback1, esi, 0
|
invoke USBNormalTransferAsync, [esi+usb_device_data.OutPipe], edx, sizeof.command_block_wrapper, request_callback1, esi, 0
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .nothing
|
jz .nothing
|
||||||
; 5. If the next stage is data stage in the same direction, enqueue it here.
|
; 5. If the next stage is data stage in the same direction, enqueue it here.
|
||||||
@ -473,7 +443,7 @@ if DUMP_PACKETS
|
|||||||
call debug_dump
|
call debug_dump
|
||||||
DEBUGF 1,'\n'
|
DEBUGF 1,'\n'
|
||||||
end if
|
end if
|
||||||
stdcall USBNormalTransferAsync, [esi+usb_device_data.OutPipe], [edx+request_queue_item.Buffer], [esi+usb_device_data.Command.Length], request_callback2, esi, 0
|
invoke USBNormalTransferAsync, [esi+usb_device_data.OutPipe], [edx+request_queue_item.Buffer], [esi+usb_device_data.Command.Length], request_callback2, esi, 0
|
||||||
.nothing:
|
.nothing:
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -551,7 +521,7 @@ end virtual
|
|||||||
cmp [ecx+usb_device_data.Command.Flags], 0
|
cmp [ecx+usb_device_data.Command.Flags], 0
|
||||||
jns .nothing
|
jns .nothing
|
||||||
; 5. Initiate USB transfer. If this fails, go to the error handler.
|
; 5. Initiate USB transfer. If this fails, go to the error handler.
|
||||||
stdcall USBNormalTransferAsync, [ecx+usb_device_data.InPipe], [edx+request_queue_item.Buffer], [ecx+usb_device_data.Command.Length], request_callback2, ecx, 0
|
invoke USBNormalTransferAsync, [ecx+usb_device_data.InPipe], [edx+request_queue_item.Buffer], [ecx+usb_device_data.Command.Length], request_callback2, ecx, 0
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .error
|
jz .error
|
||||||
; 6. The status stage goes to the same direction, enqueue it now.
|
; 6. The status stage goes to the same direction, enqueue it now.
|
||||||
@ -625,7 +595,7 @@ end if
|
|||||||
; 4. Initiate USB transfer. If this fails, go to the error handler.
|
; 4. Initiate USB transfer. If this fails, go to the error handler.
|
||||||
..enqueue_status:
|
..enqueue_status:
|
||||||
lea edx, [ecx+usb_device_data.Status]
|
lea edx, [ecx+usb_device_data.Status]
|
||||||
stdcall USBNormalTransferAsync, [ecx+usb_device_data.InPipe], edx, command_status_wrapper.sizeof, request_callback3, ecx, 0
|
invoke USBNormalTransferAsync, [ecx+usb_device_data.InPipe], edx, sizeof.command_status_wrapper, request_callback3, ecx, 0
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .error
|
jz .error
|
||||||
.nothing:
|
.nothing:
|
||||||
@ -698,7 +668,7 @@ end if
|
|||||||
; 6. Invalid status block. Say error, set status to fatal and complete request.
|
; 6. Invalid status block. Say error, set status to fatal and complete request.
|
||||||
push esi
|
push esi
|
||||||
mov esi, invresponse
|
mov esi, invresponse
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi
|
pop esi
|
||||||
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
|
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
|
||||||
jmp .complete
|
jmp .complete
|
||||||
@ -728,10 +698,10 @@ endp
|
|||||||
; edx = first argument = pointer to usb_device_data.Command,
|
; edx = first argument = pointer to usb_device_data.Command,
|
||||||
; second argument = custom data given to queue_request (ignored).
|
; second argument = custom data given to queue_request (ignored).
|
||||||
proc request_sense_req
|
proc request_sense_req
|
||||||
mov [edx+command_block_wrapper.Length], sense_data.sizeof
|
mov [edx+command_block_wrapper.Length], sizeof.sense_data
|
||||||
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
|
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
|
||||||
mov byte [edx+command_block_wrapper.Command+0], SCSI_REQUEST_SENSE
|
mov byte [edx+command_block_wrapper.Command+0], SCSI_REQUEST_SENSE
|
||||||
mov byte [edx+command_block_wrapper.Command+4], sense_data.sizeof
|
mov byte [edx+command_block_wrapper.Command+4], sizeof.sense_data
|
||||||
ret 8
|
ret 8
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -780,25 +750,25 @@ end virtual
|
|||||||
jz .known
|
jz .known
|
||||||
; 1c. If the device is unknown, print a message and go to 11c.
|
; 1c. If the device is unknown, print a message and go to 11c.
|
||||||
mov esi, unkdevice
|
mov esi, unkdevice
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
; 1d. If the device uses known command set, print a message and continue
|
; 1d. If the device uses known command set, print a message and continue
|
||||||
; configuring.
|
; configuring.
|
||||||
.known:
|
.known:
|
||||||
push esi
|
push esi
|
||||||
mov esi, okdevice
|
mov esi, okdevice
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi
|
pop esi
|
||||||
; 2. Allocate memory for internal device data.
|
; 2. Allocate memory for internal device data.
|
||||||
; 2a. Call the kernel.
|
; 2a. Call the kernel.
|
||||||
mov eax, usb_device_data.sizeof
|
mov eax, sizeof.usb_device_data
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
; 2b. Check return value.
|
; 2b. Check return value.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
; 2c. If failed, say a message and go to 11c.
|
; 2c. If failed, say a message and go to 11c.
|
||||||
mov esi, nomemory
|
mov esi, nomemory
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
@@:
|
@@:
|
||||||
; 2d. If succeeded, zero the contents and continue configuring.
|
; 2d. If succeeded, zero the contents and continue configuring.
|
||||||
@ -829,7 +799,7 @@ end virtual
|
|||||||
mov [eax+request_queue_item.Next], eax
|
mov [eax+request_queue_item.Next], eax
|
||||||
mov [eax+request_queue_item.Prev], eax
|
mov [eax+request_queue_item.Prev], eax
|
||||||
lea ecx, [ebx+usb_device_data.QueueLock]
|
lea ecx, [ebx+usb_device_data.QueueLock]
|
||||||
call MutexInit
|
invoke MutexInit
|
||||||
; Bulk-only mass storage devices use one OUT bulk endpoint for sending
|
; Bulk-only mass storage devices use one OUT bulk endpoint for sending
|
||||||
; command/data and one IN bulk endpoint for receiving data/status.
|
; command/data and one IN bulk endpoint for receiving data/status.
|
||||||
; Look for those endpoints.
|
; Look for those endpoints.
|
||||||
@ -862,9 +832,9 @@ end virtual
|
|||||||
jnz .lookep
|
jnz .lookep
|
||||||
; 5. Check that the descriptor contains all required data and all data are
|
; 5. 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 [esi+endpoint_descr.bLength], endpoint_descr.sizeof
|
cmp byte [esi+endpoint_descr.bLength], sizeof.endpoint_descr
|
||||||
jb .errorep
|
jb .errorep
|
||||||
lea ecx, [esi+endpoint_descr.sizeof]
|
lea ecx, [esi+sizeof.endpoint_descr]
|
||||||
cmp ecx, edx
|
cmp ecx, edx
|
||||||
ja .errorep
|
ja .errorep
|
||||||
; 6. Check that the endpoint is bulk endpoint. The opposite is an error.
|
; 6. Check that the endpoint is bulk endpoint. The opposite is an error.
|
||||||
@ -887,7 +857,7 @@ end virtual
|
|||||||
movzx edx, [esi+endpoint_descr.wMaxPacketSize]
|
movzx edx, [esi+endpoint_descr.wMaxPacketSize]
|
||||||
movzx eax, [esi+endpoint_descr.bInterval] ; not used for USB1, may be important for USB2
|
movzx eax, [esi+endpoint_descr.bInterval] ; not used for USB1, may be important for USB2
|
||||||
; 9c. Call the kernel.
|
; 9c. Call the kernel.
|
||||||
stdcall USBOpenPipe, [ebx+usb_device_data.ConfigPipe], ecx, edx, BULK_PIPE, eax
|
invoke USBOpenPipe, [ebx+usb_device_data.ConfigPipe], ecx, edx, BULK_PIPE, eax
|
||||||
; 9d. Restore registers.
|
; 9d. Restore registers.
|
||||||
pop edx ecx
|
pop edx ecx
|
||||||
; 9e. Check result. If failed, go to 11b.
|
; 9e. Check result. If failed, go to 11b.
|
||||||
@ -907,7 +877,7 @@ end virtual
|
|||||||
.free:
|
.free:
|
||||||
; 11b. Free the allocated usb_device_data.
|
; 11b. Free the allocated usb_device_data.
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
call Kfree
|
invoke Kfree
|
||||||
.nothing:
|
.nothing:
|
||||||
; 11c. Return an error.
|
; 11c. Return an error.
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -922,7 +892,7 @@ end virtual
|
|||||||
if DUMP_PACKETS
|
if DUMP_PACKETS
|
||||||
DEBUGF 1,'K : GETMAXLUN: %x %x %x %x %x %x %x %x\n',[eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2
|
DEBUGF 1,'K : GETMAXLUN: %x %x %x %x %x %x %x %x\n',[eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2
|
||||||
end if
|
end if
|
||||||
stdcall USBControlTransferAsync, [ebx+usb_device_data.ConfigPipe], eax, ecx, 1, known_lun_callback, ebx, 0
|
invoke USBControlTransferAsync, [ebx+usb_device_data.ConfigPipe], eax, ecx, 1, known_lun_callback, ebx, 0
|
||||||
; 13. Return with pointer to device data as returned value.
|
; 13. Return with pointer to device data as returned value.
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
.return:
|
.return:
|
||||||
@ -955,15 +925,15 @@ end virtual
|
|||||||
mov eax, [ebx+usb_device_data.MaxLUN]
|
mov eax, [ebx+usb_device_data.MaxLUN]
|
||||||
inc eax
|
inc eax
|
||||||
DEBUGF 1,'K : %d logical unit(s)\n',eax
|
DEBUGF 1,'K : %d logical unit(s)\n',eax
|
||||||
imul eax, usb_unit_data.sizeof
|
imul eax, sizeof.usb_unit_data
|
||||||
push ebx
|
push ebx
|
||||||
call Kmalloc
|
invoke Kmalloc
|
||||||
pop ebx
|
pop ebx
|
||||||
; If failed, print a message and do nothing.
|
; If failed, print a message and do nothing.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
mov esi, nomemory
|
mov esi, nomemory
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi ebx
|
pop esi ebx
|
||||||
ret 20
|
ret 20
|
||||||
@@:
|
@@:
|
||||||
@ -980,12 +950,12 @@ end virtual
|
|||||||
mov [esi+usb_unit_data.SectorSize], eax
|
mov [esi+usb_unit_data.SectorSize], eax
|
||||||
mov [esi+usb_unit_data.UnitReadyAttempts], eax
|
mov [esi+usb_unit_data.UnitReadyAttempts], eax
|
||||||
push ecx
|
push ecx
|
||||||
call GetTimerTicks
|
invoke GetTimerTicks
|
||||||
mov [esi+usb_unit_data.TimerTicks], eax
|
mov [esi+usb_unit_data.TimerTicks], eax
|
||||||
stdcall queue_request, ebx, test_unit_ready_req, 0, test_unit_ready_callback, esi
|
stdcall queue_request, ebx, test_unit_ready_req, 0, test_unit_ready_callback, esi
|
||||||
pop ecx
|
pop ecx
|
||||||
inc ecx
|
inc ecx
|
||||||
add esi, usb_unit_data.sizeof
|
add esi, sizeof.usb_unit_data
|
||||||
cmp ecx, [ebx+usb_device_data.MaxLUN]
|
cmp ecx, [ebx+usb_device_data.MaxLUN]
|
||||||
jbe .looplun
|
jbe .looplun
|
||||||
; 4. Return.
|
; 4. Return.
|
||||||
@ -999,11 +969,11 @@ endp
|
|||||||
proc inquiry_req
|
proc inquiry_req
|
||||||
mov eax, [esp+8]
|
mov eax, [esp+8]
|
||||||
mov al, [eax+usb_unit_data.LUN]
|
mov al, [eax+usb_unit_data.LUN]
|
||||||
mov [edx+command_block_wrapper.Length], inquiry_data.sizeof
|
mov [edx+command_block_wrapper.Length], sizeof.inquiry_data
|
||||||
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
|
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
|
||||||
mov [edx+command_block_wrapper.LUN], al
|
mov [edx+command_block_wrapper.LUN], al
|
||||||
mov byte [edx+command_block_wrapper.Command+0], SCSI_INQUIRY
|
mov byte [edx+command_block_wrapper.Command+0], SCSI_INQUIRY
|
||||||
mov byte [edx+command_block_wrapper.Command+4], inquiry_data.sizeof
|
mov byte [edx+command_block_wrapper.Command+4], sizeof.inquiry_data
|
||||||
ret 8
|
ret 8
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -1034,7 +1004,7 @@ proc inquiry_callback
|
|||||||
movi ebx, 1
|
movi ebx, 1
|
||||||
mov ecx, new_disk_thread
|
mov ecx, new_disk_thread
|
||||||
; edx = parameter
|
; edx = parameter
|
||||||
call CreateThread
|
invoke CreateThread
|
||||||
pop edi esi ecx ebx
|
pop edi esi ecx ebx
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
jnz .nothing
|
jnz .nothing
|
||||||
@ -1046,7 +1016,7 @@ proc inquiry_callback
|
|||||||
; 4. The command has failed. Print a message and do nothing.
|
; 4. The command has failed. Print a message and do nothing.
|
||||||
push esi
|
push esi
|
||||||
mov esi, inquiry_fail
|
mov esi, inquiry_fail
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi
|
pop esi
|
||||||
ret 8
|
ret 8
|
||||||
endp
|
endp
|
||||||
@ -1079,7 +1049,7 @@ end virtual
|
|||||||
; possibly after some repetitions. Print a debug message showing
|
; possibly after some repetitions. Print a debug message showing
|
||||||
; number and time of those. Remember that media is ready and go to 4.
|
; number and time of those. Remember that media is ready and go to 4.
|
||||||
DEBUGF 1,'K : media is ready\n'
|
DEBUGF 1,'K : media is ready\n'
|
||||||
call GetTimerTicks
|
invoke GetTimerTicks
|
||||||
sub eax, [edx+usb_unit_data.TimerTicks]
|
sub eax, [edx+usb_unit_data.TimerTicks]
|
||||||
DEBUGF 1,'K : %d attempts, %d ticks\n',[edx+usb_unit_data.UnitReadyAttempts],eax
|
DEBUGF 1,'K : %d attempts, %d ticks\n',[edx+usb_unit_data.UnitReadyAttempts],eax
|
||||||
inc [edx+usb_unit_data.MediaPresent]
|
inc [edx+usb_unit_data.MediaPresent]
|
||||||
@ -1094,7 +1064,7 @@ end virtual
|
|||||||
jz @f
|
jz @f
|
||||||
push ecx edx esi
|
push ecx edx esi
|
||||||
movi esi, 10
|
movi esi, 10
|
||||||
call Sleep
|
invoke Sleep
|
||||||
pop esi edx ecx
|
pop esi edx ecx
|
||||||
stdcall queue_request, ecx, test_unit_ready_req, 0, test_unit_ready_callback, edx
|
stdcall queue_request, ecx, test_unit_ready_req, 0, test_unit_ready_callback, edx
|
||||||
ret 8
|
ret 8
|
||||||
@ -1120,7 +1090,7 @@ end virtual
|
|||||||
; 1. Generate name.
|
; 1. Generate name.
|
||||||
; 1a. Find a free index.
|
; 1a. Find a free index.
|
||||||
mov ecx, free_numbers_lock
|
mov ecx, free_numbers_lock
|
||||||
call MutexLock
|
invoke MutexLock
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@@:
|
@@:
|
||||||
bsf edx, [free_numbers+eax]
|
bsf edx, [free_numbers+eax]
|
||||||
@ -1128,10 +1098,10 @@ end virtual
|
|||||||
add eax, 4
|
add eax, 4
|
||||||
cmp eax, 4*4
|
cmp eax, 4*4
|
||||||
jnz @b
|
jnz @b
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
push esi
|
push esi
|
||||||
mov esi, noindex
|
mov esi, noindex
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
pop esi
|
pop esi
|
||||||
jmp .drop_reference
|
jmp .drop_reference
|
||||||
@@:
|
@@:
|
||||||
@ -1139,7 +1109,7 @@ end virtual
|
|||||||
btr [free_numbers+eax], edx
|
btr [free_numbers+eax], edx
|
||||||
lea eax, [eax*8+edx]
|
lea eax, [eax*8+edx]
|
||||||
push eax
|
push eax
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
pop eax
|
pop eax
|
||||||
; 1c. Generate a name of the form "usbhd<index>" in the stack.
|
; 1c. Generate a name of the form "usbhd<index>" in the stack.
|
||||||
mov dword [esp], 'usbh'
|
mov dword [esp], 'usbh'
|
||||||
@ -1166,41 +1136,41 @@ end virtual
|
|||||||
; 4. Notify the kernel about a new disk.
|
; 4. Notify the kernel about a new disk.
|
||||||
; 4a. Add a disk.
|
; 4a. Add a disk.
|
||||||
; stdcall queue_request, ecx, read_capacity_req, eax, read_capacity_callback, eax
|
; stdcall queue_request, ecx, read_capacity_req, eax, read_capacity_callback, eax
|
||||||
stdcall DiskAdd, disk_functions, edx, esi, 0
|
invoke DiskAdd, disk_functions, edx, esi, 0
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
; 4b. If it failed, release the index and do nothing.
|
; 4b. If it failed, release the index and do nothing.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .free_index
|
jz .free_index
|
||||||
; 4c. Notify the kernel that a media is present.
|
; 4c. Notify the kernel that a media is present.
|
||||||
stdcall DiskMediaChanged, eax, 1
|
invoke DiskMediaChanged, eax, 1
|
||||||
; 5. Lock the requests queue, check that device is not disconnected,
|
; 5. Lock the requests queue, check that device is not disconnected,
|
||||||
; store the disk handle, unlock the requests queue.
|
; store the disk handle, unlock the requests queue.
|
||||||
mov ecx, [esi+usb_unit_data.Parent]
|
mov ecx, [esi+usb_unit_data.Parent]
|
||||||
add ecx, usb_device_data.QueueLock
|
add ecx, usb_device_data.QueueLock
|
||||||
call MutexLock
|
invoke MutexLock
|
||||||
cmp byte [ecx+usb_device_data.DeviceDisconnected-usb_device_data.QueueLock], 0
|
cmp byte [ecx+usb_device_data.DeviceDisconnected-usb_device_data.QueueLock], 0
|
||||||
jnz .disconnected
|
jnz .disconnected
|
||||||
mov [esi+usb_unit_data.DiskDevice], ebx
|
mov [esi+usb_unit_data.DiskDevice], ebx
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
jmp .exit
|
jmp .exit
|
||||||
.disconnected:
|
.disconnected:
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
stdcall disk_close, ebx
|
stdcall disk_close, ebx
|
||||||
jmp .exit
|
jmp .exit
|
||||||
.free_index:
|
.free_index:
|
||||||
mov ecx, free_numbers_lock
|
mov ecx, free_numbers_lock
|
||||||
call MutexLock
|
invoke MutexLock
|
||||||
movzx eax, [esi+usb_unit_data.DiskIndex]
|
movzx eax, [esi+usb_unit_data.DiskIndex]
|
||||||
bts [free_numbers], eax
|
bts [free_numbers], eax
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
.drop_reference:
|
.drop_reference:
|
||||||
mov esi, [esi+usb_unit_data.Parent]
|
mov esi, [esi+usb_unit_data.Parent]
|
||||||
lock dec [esi+usb_device_data.NumReferences]
|
lock dec [esi+usb_device_data.NumReferences]
|
||||||
jnz .exit
|
jnz .exit
|
||||||
mov eax, [esi+usb_device_data.LogicalDevices]
|
mov eax, [esi+usb_device_data.LogicalDevices]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
xchg eax, esi
|
xchg eax, esi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
.exit:
|
.exit:
|
||||||
or eax, -1
|
or eax, -1
|
||||||
int 0x40
|
int 0x40
|
||||||
@ -1216,7 +1186,7 @@ virtual at esp
|
|||||||
end virtual
|
end virtual
|
||||||
; 1. Say a message.
|
; 1. Say a message.
|
||||||
mov esi, disconnectmsg
|
mov esi, disconnectmsg
|
||||||
call SysMsgBoardStr
|
invoke SysMsgBoardStr
|
||||||
; 2. Lock the requests queue, set .DeviceDisconnected to 1,
|
; 2. Lock the requests queue, set .DeviceDisconnected to 1,
|
||||||
; unlock the requests queue.
|
; unlock the requests queue.
|
||||||
; Locking is required for synchronization with queue_request:
|
; Locking is required for synchronization with queue_request:
|
||||||
@ -1229,9 +1199,9 @@ end virtual
|
|||||||
; then queue_request tries to use them.
|
; then queue_request tries to use them.
|
||||||
mov esi, [.device]
|
mov esi, [.device]
|
||||||
lea ecx, [esi+usb_device_data.QueueLock]
|
lea ecx, [esi+usb_device_data.QueueLock]
|
||||||
call MutexLock
|
invoke MutexLock
|
||||||
mov [esi+usb_device_data.DeviceDisconnected], 1
|
mov [esi+usb_device_data.DeviceDisconnected], 1
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
; 3. Drop one reference to the structure and check whether
|
; 3. Drop one reference to the structure and check whether
|
||||||
; that was the last reference.
|
; that was the last reference.
|
||||||
lock dec [esi+usb_device_data.NumReferences]
|
lock dec [esi+usb_device_data.NumReferences]
|
||||||
@ -1247,9 +1217,9 @@ end virtual
|
|||||||
mov eax, [esi+usb_unit_data.DiskDevice]
|
mov eax, [esi+usb_unit_data.DiskDevice]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
stdcall DiskDel, eax
|
invoke DiskDel, eax
|
||||||
@@:
|
@@:
|
||||||
add esi, usb_unit_data.sizeof
|
add esi, sizeof.usb_unit_data
|
||||||
dec ebx
|
dec ebx
|
||||||
jnz .diskdel
|
jnz .diskdel
|
||||||
; In this case, some operations with those disks are still possible,
|
; In this case, some operations with those disks are still possible,
|
||||||
@ -1262,10 +1232,10 @@ end virtual
|
|||||||
mov eax, [esi+usb_device_data.LogicalDevices]
|
mov eax, [esi+usb_device_data.LogicalDevices]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @f
|
jz @f
|
||||||
call Kfree
|
invoke Kfree
|
||||||
@@:
|
@@:
|
||||||
xchg eax, esi
|
xchg eax, esi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
jmp .return
|
jmp .return
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -1286,17 +1256,17 @@ virtual at esp
|
|||||||
end virtual
|
end virtual
|
||||||
mov esi, [.userdata]
|
mov esi, [.userdata]
|
||||||
mov ecx, free_numbers_lock
|
mov ecx, free_numbers_lock
|
||||||
call MutexLock
|
invoke MutexLock
|
||||||
movzx eax, [esi+usb_unit_data.DiskIndex]
|
movzx eax, [esi+usb_unit_data.DiskIndex]
|
||||||
bts [free_numbers], eax
|
bts [free_numbers], eax
|
||||||
call MutexUnlock
|
invoke MutexUnlock
|
||||||
mov esi, [esi+usb_unit_data.Parent]
|
mov esi, [esi+usb_unit_data.Parent]
|
||||||
lock dec [esi+usb_device_data.NumReferences]
|
lock dec [esi+usb_device_data.NumReferences]
|
||||||
jnz .nothing
|
jnz .nothing
|
||||||
mov eax, [esi+usb_device_data.LogicalDevices]
|
mov eax, [esi+usb_device_data.LogicalDevices]
|
||||||
call Kfree
|
invoke Kfree
|
||||||
xchg eax, esi
|
xchg eax, esi
|
||||||
call Kfree
|
invoke Kfree
|
||||||
.nothing:
|
.nothing:
|
||||||
pop esi ebx
|
pop esi ebx
|
||||||
ret 4
|
ret 4
|
||||||
@ -1308,7 +1278,7 @@ proc disk_querymedia stdcall uses ebx esi edi, \
|
|||||||
; 1. Create event for waiting.
|
; 1. Create event for waiting.
|
||||||
xor esi, esi
|
xor esi, esi
|
||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
call CreateEvent
|
invoke CreateEvent
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .generic_fail
|
jz .generic_fail
|
||||||
push eax
|
push eax
|
||||||
@ -1340,7 +1310,7 @@ end virtual
|
|||||||
; 3. Wait for event. This destroys it.
|
; 3. Wait for event. This destroys it.
|
||||||
mov eax, [.event]
|
mov eax, [.event]
|
||||||
mov ebx, [.event_code]
|
mov ebx, [.event_code]
|
||||||
call WaitEvent
|
invoke WaitEvent
|
||||||
; 4. Get the status and results.
|
; 4. Get the status and results.
|
||||||
pop ecx
|
pop ecx
|
||||||
bswap ecx ; .LastLBA
|
bswap ecx ; .LastLBA
|
||||||
@ -1403,7 +1373,7 @@ proc read_capacity_callback
|
|||||||
mov ebx, [ecx+disk_querymedia.event_code-disk_querymedia.locals]
|
mov ebx, [ecx+disk_querymedia.event_code-disk_querymedia.locals]
|
||||||
xor edx, edx
|
xor edx, edx
|
||||||
xor esi, esi
|
xor esi, esi
|
||||||
call RaiseEvent
|
invoke RaiseEvent
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret 8
|
ret 8
|
||||||
endp
|
endp
|
||||||
@ -1443,7 +1413,7 @@ max_sectors_at_time = 0xFFFF
|
|||||||
; 4. Create event for waiting.
|
; 4. Create event for waiting.
|
||||||
xor esi, esi
|
xor esi, esi
|
||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
call CreateEvent
|
invoke CreateEvent
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .generic_fail
|
jz .generic_fail
|
||||||
push eax ; .event
|
push eax ; .event
|
||||||
@ -1476,7 +1446,7 @@ end virtual
|
|||||||
; 6. Wait for event. This destroys it.
|
; 6. Wait for event. This destroys it.
|
||||||
mov eax, [.event]
|
mov eax, [.event]
|
||||||
mov ebx, [.event_code]
|
mov ebx, [.event_code]
|
||||||
call WaitEvent
|
invoke WaitEvent
|
||||||
; 7. Get the status. If the operation has failed, abort.
|
; 7. Get the status. If the operation has failed, abort.
|
||||||
pop eax ; .status
|
pop eax ; .status
|
||||||
pop ecx ecx ; cleanup .event_code, .event
|
pop ecx ecx ; cleanup .event_code, .event
|
||||||
@ -1579,7 +1549,7 @@ end virtual
|
|||||||
mov ebx, [esi+disk_read_write.event_code-disk_read_write.locals]
|
mov ebx, [esi+disk_read_write.event_code-disk_read_write.locals]
|
||||||
xor edx, edx
|
xor edx, edx
|
||||||
xor esi, esi
|
xor esi, esi
|
||||||
call RaiseEvent
|
invoke RaiseEvent
|
||||||
; 6. Return.
|
; 6. Return.
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret 8
|
ret 8
|
||||||
@ -1599,9 +1569,7 @@ inquiry_fail db 'K : INQUIRY command failed',13,10,0
|
|||||||
;read_fail db 'K : READ command failed',13,10,0
|
;read_fail db 'K : READ command failed',13,10,0
|
||||||
noindex db 'K : failed to generate disk name',13,10,0
|
noindex db 'K : failed to generate disk name',13,10,0
|
||||||
|
|
||||||
; Exported variable: kernel API version.
|
|
||||||
align 4
|
align 4
|
||||||
version dd 50005h
|
|
||||||
; Structure with callback functions.
|
; Structure with callback functions.
|
||||||
usb_functions:
|
usb_functions:
|
||||||
dd usb_functions_end - usb_functions
|
dd usb_functions_end - usb_functions
|
||||||
@ -1620,12 +1588,12 @@ disk_functions:
|
|||||||
dd 0 ; adjust_cache_size: use default cache
|
dd 0 ; adjust_cache_size: use default cache
|
||||||
disk_functions_end:
|
disk_functions_end:
|
||||||
|
|
||||||
|
data fixups
|
||||||
|
end data
|
||||||
|
|
||||||
free_numbers_lock rd 3
|
free_numbers_lock rd 3
|
||||||
; 128 devices should be enough for everybody
|
; 128 devices should be enough for everybody
|
||||||
free_numbers dd -1, -1, -1, -1
|
free_numbers dd -1, -1, -1, -1
|
||||||
|
|
||||||
; for DEBUGF macro
|
; for DEBUGF macro
|
||||||
include_debug_strings
|
include_debug_strings
|
||||||
|
|
||||||
; for uninitialized data
|
|
||||||
section '.data' data readable writable align 16
|
|
Loading…
Reference in New Issue
Block a user