📄 usb.asm
字号:
pusha
push es
mov bx, USB_RQ_SET_CONFIGURATION ;Request type is "Set Address"
xor dx, dx ;DX = wIndex parameter = 0
xor si, si ;SI = wLength parameter = 0
xor di, di ;ES:DI = data buf ptr = NULL
mov es, di
call UsbDeviceRequest ;Execute the device request, returns CF
pop es
popa
ret
_UsbSetConfiguration endp
;---------------------------------------;
; _UsbHidSetProtocol ;
;---------------------------------------;--------------------------------------;
; This function executes a Set Protocol command to the given USB HID device ;
; and endpoint. ;
; ;
; Input: AL = USB device address of device to receive the command ;
; AH = Endpoint number within the USB device ;
; CL = New protocol for device ;
; 00h = HID boot protocol ;
; 01h = HID entity protocol ;
; 02h-FFh = Reserved ;
; CH = Endpoint number (from EndpointDescriptor.EndpointAddr) ;
; ;
; Output: CF = Clear if the command completed successfully ;
; Set if the command failed ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
;;;;_UsbHidSetProtocol proc near
;;;; pusha
;;;; push es
;;;;
;;;; mov bx, HID_RQ_SET_PROTOCOL ;Request type is "Set Protocol"
;;;; movzx dx, ch ;DX = wIndex = Interface number
;;;; xor ch, ch ;CX = wValue = Protocol code
;;;; xor si, si ;SI = wLength parameter = 0
;;;; xor di, di ;ES:DI = data buf ptr = NULL
;;;; mov es, di
;;;;
;;;; call UsbDeviceRequest ;Execute the device request, returns CF
;;;;
;;;; pop es
;;;; popa
;;;; ret
;;;;_UsbHidSetProtocol endp
;---------------------------------------;
; UsbHubPortChange ;
;---------------------------------------;--------------------------------------;
; This function is called when a change in connect status is detected on any ;
; port of any hub (including the root hub). Connect status changes are caused ;
; by devices being plugged in or removed from the USB. This routine calls ;
; ProcessSingleHubPortChange to handle the change and then checks for new hubs ;
; on the bus that need to be enumerated. ;
; ;
; Input: AL = USB Device address of hub whose status has changed ;
; 00 - 7F = Device address of hub on the USB ;
; 80 - FE = Reserved ;
; FF = Root hub ;
; AH = Port number within hub whose status has changed ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
UsbHubPortChange proc near
pusha
mov bh, 01h ;Do not ignore connect status change
call ProcessSingleHubPortChange
; Now check iteratively to see if any external hubs have been found. For any
; new external hub that has been found, check each of its ports for a new device
; attached. Since any hub port may have another external hub attached, we
; must iteratively check for new hubs until no new hub is found. An external
; hub that has been found, but has not had its ports scanned is indicated by
; its HubEnumFlag field in its DeviceTableEntry containing a value of FALSE.
HubChangeEnumNextHub:
mov si, offset DeviceTable ;SI = ptr to DeviceTable[0]
add si, size DeviceTableEntry ;SI = ptr to DeviceTable[1]
xor bl, bl ;BL = Flag: 0 if all hubs have enumerated
HubChangeNextDTE:
cmp (DeviceTableEntry ptr [si]).Present, TRUE
jne HubChangeSkipDTE ;Br if this DeviceTableEntry is not in use
cmp (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_HUB
jne HubChangeSkipDTE ;Br if this DeviceTableEntry is not a hub
cmp (DeviceTableEntry ptr [si]).HubEnumFlag, TRUE
je HubChangeSkipDTE ;Br if this hub has already been enumerated
mov bl, 1 ;Indicate that not all hubs have been enumerated
mov al, (DeviceTableEntry ptr [si]).DeviceAddress ;AL = Device address of hub
mov ah, 1 ;AH will count ports on hub (1..n)
HubChangeNextPort:
mov bh, 00h ;Ignore connect status change bit
call ProcessSingleHubPortChange ;Handle change on hub/port AL/AH
inc ah
cmp ah, (DeviceTableEntry ptr [si]).HubNumPorts
jbe HubChangeNextPort ;Br if more ports on hub to check
mov (DeviceTableEntry ptr [si]).HubEnumFlag, TRUE ;Flag hub's ports as enumerated
HubChangeSkipDTE:
add si, size DeviceTableEntry
cmp si, offset DeviceTableEnd
jb HubChangeNextDTE ;Br if more entries to check
or bl, bl
jnz HubChangeEnumNextHub ;Br if all hubs are not yet enumerated
popa
ret
UsbHubPortChange endp
;---------------------------------------;
; ProcessSingleHubPortChange ;
;---------------------------------------;--------------------------------------;
; This function is called when a change in connect status is detected on any ;
; port of any hub (including the root hub). Connect status changes are caused ;
; by devices being plugged in or removed from the USB. This routine handles ;
; the addtion or subtraction of new devices. ;
; ;
; Input: AL = USB Device address of hub whose status has changed ;
; 00 - 7F = Device address of hub on the USB ;
; 80 - FE = Reserved ;
; FF = Root hub ;
; AH = Port number within hub whose status has changed ;
; BH = 00: This hub port is being checked for the first time so ignore ;
; the hub's connect status change bit (enumerate the port even ;
; if the hub says that the connect status has not changed) ;
; 01: This hub port has been checked before, do not ignore the ;
; connect status change bit ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
ProcessSingleHubPortChange proc near
pusha
push ds
push es
test InitializationFlags, INIT_FLAG_ENUM_DISABLE
jnz PortChangeDone ;Br if USB enum is disabled
call UsbGetHubPortStatus ;Returns BL=Flags, CF
jc PortChangeDone ;Br if error or no change in connect status
or bh, bh
jz @f ;Br if connect change bit should be ignored
test bl, 00000100b ;Test connect status change bit
jz PortChangeDone ;Br if connect status has not changed
@@:
test bl, 00000001b ;Test device connected bit
jz PortChangeDisconnect ;Br if device has been disconnected
call UsbDetectNewDevice ;Handle attachment of a new device
jmp short PortChangeDone
; A device has been disconnected from the USB. First disable the hub port
; that the device was plugged into. Then free up the device's entry in the
; DeviceTable. If there an error occurs while disabling the port, assume
; that the device is still present an leave its DeviceTable entry in place.
PortChangeDisconnect:
call UsbDisableHubPort
jc PortChangeDone
call ShutdownDevice ;Shutdown device and any children
mov ah, 8 ;Issue disconnect beep (low & short)
mov cx, 1000h
call SpeakerBeep
PortChangeDone:
pop es
pop ds
popa
ret
ProcessSingleHubPortChange endp
;---------------------------------------;
; ShutdownDevice ;
;---------------------------------------;--------------------------------------;
; This function is called when a device disconnect is detected. This routine ;
; stops polling on the device, frees its DeviceTable entry, and notifies the ;
; keyboard/mouse code that the device is gone. This routine also recursively ;
; processes any childs devices if a hub is disconnected. ;
; ;
; Input: AL = USB Device address of hub that detected the diconnect ;
; 00 - 7F = Device address of hub on the USB ;
; 80 - FE = Reserved ;
; FF = Root hub ;
; AH = Port number within hub that detected the diconnect ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
ShutdownDevice proc near
push si
mov si, offset DeviceTable ;SI = ptr to DeviceTableEntry[0]
add si, size DeviceTableEntry ;Point to DeviceTableEntry[1]
DisCheckNextEntry:
cmp (DeviceTableEntry ptr [si]).Present, TRUE
jne SkipEntry ;Br if unused entry
cmp word ptr ((DeviceTableEntry ptr [si]).HubDeviceNumber), ax
jne SkipEntry ;Br if this entry not for this hub/port
cmp (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_HUB
jne DisconnectChildrenDone ;Br if device is not a hub
; A hub device is being disconnected. For each of the hub's ports disconnect
; any child device connected.
push ax
mov al, (DeviceTableEntry ptr [si]).DeviceAddress ;AL = device address
mov ah, 1 ;AH will count through hub ports
DisconnectNextPort:
call ShutdownDevice ;Disconnect device and any children
inc ah
cmp ah, (DeviceTableEntry ptr [si]).HubNumPorts
jbe DisconnectNextPort ;Br if still more ports to disconnect
pop ax
; Now free the device table entry for this device, stop polling for this device,
; and notify the keyboard/mouse code that the device is gone (if the device is
; a keyboard or mouse).
DisconnectChildrenDone:
mov (DeviceTableEntry ptr [si]).Present, FALSE ;Mark entry as unused
call _UsbDeactivatePolling ;Stop polling for DeviceTableEntry[SI]
cmp (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_KEYBOARD
je @F ;Br if disconnected device is keyboard
cmp (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_MOUSE
jne SkipEntry ;Br if disconnected device is not mouse
@@:
push ax
mov al, (DeviceTableEntry ptr [si]).DeviceAddress ;AL = device address
mov ah, (DeviceTableEntry ptr [si]).BiosDeviceType
call DisconnectDevice ;Notify keyboard/mouse code of disconnect
pop ax
SkipEntry:
add si, size DeviceTableEntry ;Point to next DeviceTableEntry
cmp si, offset DeviceTableEnd
jb DisCheckNextEntry ;Br if more entries in DeviceTable
pop si
ret
ShutdownDevice endp
;---------------------------------------;
; UsbDetectNewDevice ;
;---------------------------------------;--------------------------------------;
; This function is called when a new device is plugged into a port on a hub. ;
; The hub may be a normal USB hub or the root hub. This function does the ;
; following: ;
; ;
; 1. Set the DeviceTable entry for device 0 to be the same speed as the ;
; new device ;
; 2. Find a free entry in the DeviceTable (the position in the DeviceTable ;
; array is the same as the new device address for the device) ;
; 3. Enable the port on the hub ;
; 4. Send a GetDescriptor (Device Descriptor) command to the device using an ;
; assumed MaxPacket size of 128 bytes, and make note of the actual MaxPacket;
; size returned in the descriptor data ;
; 5. Reset th hub port to handle any noncompliant devices ;
; 6. Send a SetAddress command to the device to set it to its new address ;
; 7. Send a GetDescriptor command to the device to get its Device descriptor ;
; 8. Use GetConfiguration commands to search for a configuration that includes ;
; an interface type that the BIOS can use (keyboard, mouse, or hub). ;
; 9. Use the data returned in the Device descriptor to fill in the DeviceTable ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -