📄 usb.asm
字号:
;---------------------------------------;--------------------------------------;
; This function checks an interface descriptor of a device to see if it ;
; describes a HID/Boot/Mouse device. If the device is a mouse, then ;
; it is configured and initialized. ;
; ;
; Input: DL = USB Device address of new device ;
; ES:DI+BX = Pointer to an interface descriptor supported by device ;
; ES:DI+BP = Limit of the data returned by device during the last ;
; Get Configuration Descriptor command ;
; DS:SI = Pointer to DeviceTableEntry for the device ;
; ;
; Output: CF = Set if mouse was not found ;
; Clear if mouse was found and initialized ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
CheckForAndConfigureMouse proc near
pusha
; ES:DI+BX points to an InterfaceDescriptor. Check its BaseClass, SubClass,
; and Protocol fields for a HID/Boot/Mouse device.
cmp es:(InterfaceDescriptor ptr [di+bx]).BaseClass, BASS_CLASS_HID
stc
jne CheckMouseDone ;Br if this interface is not a HID device
cmp es:(InterfaceDescriptor ptr [di+bx]).SubClass, SUB_CLASS_BOOT_DEVICE
stc
jne CheckMouseDone ;Br if this interface is not a boot device
cmp es:(InterfaceDescriptor ptr [di+bx]).Protocol, PROTOCOL_MOUSE
stc
jne CheckMouseDone ;Br if this interface is not a mouse
; Set the BiosDeviceType field in DeviceTableEntry[0]. This serves as a flag
; that indicates a usable interface has been found in the current configuration.
; This is needed so we can check for other usable interfaces in the current
; configuration (i.e. composite device), but not try to search in other
; configurations.
mov (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_MOUSE
mov (DeviceTableEntry ptr [si]).pDeviceCallback, offset cgroup:ProcessMouseData
add (DeviceTableEntry ptr [si]).pDeviceCallback, orgbase
; Call a common routine to handle the remaining initialization that is done
; for all devices.
call ConfigureNewDevice ;Finish init for new device
; Returns CF set/clear appropriately
CheckMouseDone:
popa
ret
CheckForAndConfigureMouse endp
;---------------------------------------;
; CheckForAndConfigureHub ;
;---------------------------------------;--------------------------------------;
; This function checks an interface descriptor of a device to see if it ;
; describes a USB hub. If the device is a hub, then it is configured and ;
; initialized. ;
; ;
; Input: ES:DI+BX = Pointer to an interface descriptor supported by device ;
; ES:DI+BP = Limit of the data returned by device during the last ;
; Get Configuration Descriptor command ;
; DS:SI = Pointer to DeviceTableEntry[0] which contains some info ;
; from the device, config, and interface descriptors ;
; ;
; Output: CF = Set if hub was not found ;
; Clear if hub was found and initialized ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
CheckForAndConfigureHub proc near
pusha
; ES:DI+BX points to an InterfaceDescriptor. Check its BaseClass, SubClass,
; and Protocol fields for a hub device.
; Samsung & Acer hub have class info in device desc (and 00s here)..........................
cmp es:(InterfaceDescriptor ptr [di+bx]).BaseClass, BASE_CLASS_HUB
stc
jne CheckHubDone ;Br if this interface is not a hub device
; Many hubs don't have subclass
; cmp es:(InterfaceDescriptor ptr [di+bx]).SubClass, SUB_CLASS_HUB
; stc
; jne CheckHubDone ;Br if this interface is not a hub device
; Set the BiosDeviceType field in DeviceTableEntry[0]. This serves as a flag
; that indicates a usable interface has been found in the current configuration.
; This is needed so we can check for other usable interfaces in the current
; configuration (i.e. composite device), but not try to search in other
; configurations.
mov (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_HUB
mov (DeviceTableEntry ptr [si]).pDeviceCallback, offset cgroup:ProcessHubData
add (DeviceTableEntry ptr [si]).pDeviceCallback, orgbase
; Call a common routine to handle the remaining initialization that is done
; for all devices.
call ConfigureNewDevice ;Finish init for new device
; Returns CF set/clear appropriately
CheckHubDone:
popa
ret
CheckForAndConfigureHub endp
;---------------------------------------;
; ConfigureNewDevice ;
;---------------------------------------;--------------------------------------;
; This device completes the initialization of USB devices once they have been ;
; identified. ;
; ;
; Input: ES:DI+BX = Pointer to an interface descriptor supported by device ;
; ES:DI+BP = Limit of the data returned by device during the last ;
; Get Configuration Descriptor command ;
; DS:SI = Pointer to DeviceTableEntry[0] which contains some info ;
; from the device, config, and interface descriptors ;
; ;
; Output: CF = Set if device was not initialized successfully ;
; Clear if device was initialized successfully ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
ConfigureNewDevice proc near
pusha
push es
; First find a free entry in the DeviceTable. Select a entry number in the range
; MIN_xxx_DEVICE_INDEX - MAX_xxx_DEVICE_INDEX. The index into the DeviceTableEntry
; array no longer corresponds to the address assigned to the new device.
mov dx, di ;Save DI+BX = ptr to Interface desc
mov di, offset DeviceTable ;DI = ptr to DeviceTable[0]
add di, MIN_HID_DEVICE_INDEX * size DeviceTableEntry
mov cl, MIN_HID_DEVICE_INDEX ;CL will count device addresses
mov ch, MAX_HID_DEVICE_INDEX ;CH is is max device address
cmp (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_HUB
jne ConfigNewNextEntry ;Br if new device is not a hub
mov di, offset DeviceTable ;DI = ptr to DeviceTable[0]
add di, MIN_HUB_DEVICE_INDEX * size DeviceTableEntry
mov cl, MIN_HUB_DEVICE_INDEX ;CL will count device addresses
mov ch, MAX_HUB_DEVICE_INDEX ;CH is is max device address
ConfigNewNextEntry:
cmp (DeviceTableEntry ptr [di]).Present, TRUE
jne ConfigNewFoundEntry ;Br if found unused entry
inc cl ;Inc device address
add di, size DeviceTableEntry
cmp cl, ch
jbe ConfigNewNextEntry ;Br if not to end of DeviceTable
jmp ConfigNewSkipInterface ;No free entry was found so abort
; DI now points to a free DeviceTable entry. Since DeviceTableEntry[0] (at SI)
; already has many fields filled in, the new entry should be initialized with a
; copy of DeviceTableEntry[0]. But, the new DeviceTableEntry should not be
; marked as "present" until the device is successfully initialized.
ConfigNewFoundEntry:
mov ax, (DeviceTableEntry ptr [di]).TdPoolPtr ;Save TdPoolPtr
shl eax,16
mov ax, (DeviceTableEntry ptr [di]).EdPoolPtr ;Save EdPoolPtr
push es ;Save ES
push ds ;Set ES = DS
pop es
push di ;Save ptr to new DeviceTableEntry
mov cx, size DeviceTableEntry
rep movsb
pop si ;SI = ptr to new DeviceTableEntry
pop es ;Restore ES
mov di, dx ;Restore DI+BX = ptr to Interface desc
mov (DeviceTableEntry ptr [si]).Present, FALSE
mov (DeviceTableEntry ptr [si]).EdPoolPtr, ax ;Restore EdPoolPtr
shr eax,16
mov (DeviceTableEntry ptr [si]).TdPoolPtr, ax ;Restore TdPoolPtr
; Adjust BX so that ES:DI+BX points to the next descriptor, abort if we're past
; the end of the data.
movzx ax, es:(InterfaceDescriptor ptr [di+bx]).DescLength
add bx, ax ;BX = ptr to next desc
cmp bx, bp
jae ConfigNewSkipInterface ;Br if past end of data
; ES:DI+BX should now point to an EndpointDescriptor. If it does not, search
; down until we either find an EndpointDescriptor or go past the limit in BP.
ConfigNewNextDesc :
cmp es:(EndpointDescriptor ptr [di+bx]).DescType, DESC_TYPE_ENDPOINT
je ConfigNewFoundEndpoint ;Br if on an endpoint desc
movzx ax, es:(EndpointDescriptor ptr [di+bx]).DescLength
or ax, ax
jz ConfigNewSkipInterface ;Br if 0 length desc (should never happen, but...)
add bx, ax ;BX = ptr to next desc
cmp bx, bp
jb ConfigNewNextDesc ;Br if not past end of data
jmp ConfigNewSkipInterface ;Br if endpoint desc was not found
; Save some of the fields from the EndpointDescriptor into the DeviceTable
; entry for this device.
ConfigNewFoundEndpoint:
mov al, es:(EndpointDescriptor ptr [di+bx]).EndpointAddr
and al, EP_DESC_ADDR_EP_NUM
mov (DeviceTableEntry ptr [si]).EndpointNum, al
; Do a SetConfiguration command to the device to set it to its
; HID/Boot configuration.
mov al, (DeviceTableEntry ptr [si]).DeviceAddress ;AL = device address
mov ah, 0 ;Send command to endpoint 0 on device
movzx cx, (DeviceTableEntry ptr [si]).ConfigNum
call _UsbSetConfiguration ;Set config of device/endp AL/AH to CX
jc ConfigNewSkipInterface ;Br if error during command
; If the new device is a hub, then do some hub specific initialization.
mov ah, (DeviceTableEntry ptr [si]).BiosDeviceType
cmp ah, BIOS_DEV_TYPE_HUB
jne ConfigNewNotHub ;Br if new device is not a hub
; Do a GetDescriptor call to get the hub's HubDescriptor and save some
; fields from this descriptor in the DeviceTableEntry.
push si ;Save ptr to device table entry
mov al, (DeviceTableEntry ptr [si]).DeviceAddress ;AL = device address
mov ah, 0 ;Send command to endpoint 0 on device
mov bx, USB_RQ_GET_CLASS_DESCRIPTOR ;Request type is "Get Class Descriptor"
mov ch, DESC_TYPE_CLASS_HUB ;CH = Descriptor type
mov cl, 0
xor dx, dx ;DX = wIndex parameter = 0
mov si, MAX_CONTROL_DATA_SIZE - 1 ;SI = Max size of descriptor
mov di, offset DeviceRequestDataBuf ;ES:DI = ptr DeviceRequestDataBuff
call UsbDeviceRequest ;Execute the device request, returns CF
pop si ;Restore ptr to device table entry
jc ConfigNewSkipInterface ;Br if error during command
mov al, es:(HubDescriptor ptr [di]).NumPorts ;AL = # of ports on hub
mov (DeviceTableEntry ptr [si]).HubNumPorts, al
mov al, es:(HubDescriptor ptr [di]).PowerOnDelay ;AL = Port power on delay
mov (DeviceTableEntry ptr [si]).HubPowerOnDelay, al
mov (DeviceTableEntry ptr [si]).HubEnumFlag, FALSE ;Hub's ports have not been enumerated
; Turn on power to all of the hub's ports by setting its port power features.
; This is needed because hubs cannot detect a device attach until port power
; is turned on.
mov dx, 1 ;DL will count hub ports and
; DX will be used as wIndex parameter
InitHubNextPort:
mov al, (DeviceTableEntry ptr [si]).DeviceAddress ;AL = device address
mov ah, 0 ;Send command to endpoint 0 on device
mov bx, HUB_RQ_SET_PORT_FEATURE ;BX = Request type
mov cx, HUB_FEATURE_PORT_POWER ;CX = wValue parameter = Feature selector
push si ;Save ptr to device table entry
xor si, si ;SI = wLength parameter = 0
call UsbDeviceRequest ;Execute the device request, returns CF
pop si ;Restore ptr to device table entry
jc ConfigNewSkipInterface ;Br if error during command
inc dx ;Next port number
cmp dl, (DeviceTableEntry ptr [si]).HubNumPorts
jbe InitHubNextPort ;Br if still more ports to power on
;;;;; Delay the amount of time specified in the PowerOnDelay field of
;;;;; the hub descriptor.
;;;;
;;;; push ax
;;;; mov al, (DeviceTableEntry ptr [di]).HubPowerOnDelay ;In 2ms units
;;;; cmp al, 5
;;;; jae EnablePortDelayNext ;Br if hub's delay is >= 10ms
;;;; mov al, 5 ;Force delay to at least 10ms
;;;;
;;;;EnablePortDelayNext:
;;;; mov cx, 134d ;2ms / 15us
;;;; call pm_fixed_delay ;Delay 2ms
;;;;
;;;; dec al ;Dec 2ms delay counter
;;;; jnz EnablePortDelayNext ;Br if not done with hub's delay
;;;; pop ax
ConfigNewNotHub:
; If new device is a keyboard or mouse, notify keyboard/mouse cod
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -