📄 usbbb.asm
字号:
mov al, (HubDescriptor ptr [di]).bNumPorts
; AL = # of ports on hub
mov CurrentDevice.bHubNumPorts, al
mov al, (HubDescriptor ptr [di]).bPowerOnDelay
; AL = Port power on delay
mov CurrentDevice.bHubPowerOnDelay, al
; Increment the hub device entry count
inc bCurrentHubDeviceEntry
; Port is in USB hub. Copy the device info into the free entry (already made sure
; the entry is free during hub enumeration done below)
push cx
; Free entry found get the offset in DI
mov di, OFFSET HubDeviceTable
movzx ax, bCurrentHubDeviceEntry
mov cl, SIZE DeviceInfo
mul cl
add di, ax
; Save the offset in pCurrentHub pointer
mov pCurrentHub, di
; Copy the current device information into a new hub structure
mov si, OFFSET CurrentDevice
push es
push ds
pop es
cld
mov cx, SIZE DeviceInfo
rep movsb
pop es
; Set SI to the new hubs device info structure
mov si, pCurrentHub
; Set CL to the number of ports in the hub
mov cl, CurrentDevice.bHubNumPorts
; Enumerate the ports in the hub
call USBBB_EnumerateHubPorts
pop cx ; Restore the port number we are
; currently processing
jnz UBEHP_ValidDeviceFound
; No valid device found in the hub
; We are going to disable this port. Free the entry used for this device
; Decrement the hub device entry count
dec bCurrentHubDeviceEntry
UBEHP_DeviceInitFailed:
; Decrement device address
dec bCurrentDeviceAddress
; We have to set the SI with appropriate device info value.
; If this hub is connected to the root hub directly then
; dCurrentHubDeviceEntry value will be 0FFh. Otherwise it will hold the index
; value into the hub device table that holds the device information for
; the hub to which this hub is connected.
mov si, OFFSET CurrentDevice
cmp bCurrentHubDeviceEntry, 0FFh
je UBEHP_Done
push cx
; Get the right SI value
mov si, OFFSET HubDeviceTable
movzx ax, bCurrentHubDeviceEntry
mov cl, SIZE DeviceInfo
mul cl
add si, ax
pop cx
UBEHP_Done:
; No device found. Set the zero flag
cmp sp, sp
jmp SHORT UBEHP_Exit
UBEHP_CheckForCurrentDeviceType:
; Check the device type
cmp dl, CS:bCurrentDeviceType
jne UBEHP_DisableHubPort
; Configure the device by setting address & configuration
call USBBB_ConfigureUSBDevice
jz UBEHP_DisableHubPort
push CS:pDeviceInitializer
pop ax
or ax, ax
jz UBEHP_DisableHubPort
call ax
jz UBEHP_DisableHubPort ; Not configured
; Indicate as the device configured
UBEHP_ValidDeviceFound:
or sp, sp
UBEHP_Exit:
popa
ret
USBBB_EnumerateHubPorts ENDP
IF MKF_USB_BB_DEV_KBD
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBBB_ConfigureKeyboard
;
; Description: This function will configure the keyboard found
;
; Input: DS USB data area
;
; Output: ZR Error
; NZ Successful completion
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBBB_ConfigureKeyboard PROC NEAR PUBLIC
push ax
push bx
push si
; Set SI to the current devices device info structure
mov si, OFFSET CurrentDevice
; Send the HID SET_IDLE request
; wValue = 0 (Indefinite) - Soft Model Keyboard needs this modification
; Also Windows use this value and it works for all the keyboards
xor ax, ax
mov CurrentDevice.CntrlXfer.wValue, ax
mov CurrentDevice.CntrlXfer.wIndex, ax
mov CurrentDevice.CntrlXfer.wRequest, HID_RQ_SET_IDLE
call USBBB_IssueControlXferWithoutData
jz UBCK_Exit
; Send the set protocol command
; wValue = 0 (Boot protocol)
mov CurrentDevice.CntrlXfer.wRequest, HID_RQ_SET_PROTOCOL
call USBBB_IssueControlXferWithoutData
jz UBCK_Exit
; Activate the polling
mov bx, CurrentHC.pHCDPointer
call (BBHCDHEADER PTR CS:[bx]).pHCDActivateKeyboardPolling
; Return status in zero flag
UBCK_Exit:
pop si
pop bx
pop ax
ret
USBBB_ConfigureKeyboard ENDP
ENDIF ;; IF MKF_USB_BB_DEV_KBD
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBBB_GetDeviceType
;
; Description: This function will get the device descriptor from the device
; connected and return the type of the device present
;
; Input: DS USB data area
; SI Pointer to the device information structure
; All the HC & device specific variables are set
;
; Output: ZR Error
; NZ Successful completion
; DL Device type
;
; Modified: DL
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBBB_GetDeviceType PROC NEAR PUBLIC
push eax
push bx
push cx
push si
push di
push edx
; Set current device type as 0
mov dl, 00h
; Check the validity of the HCD pointer
mov bx, CurrentHC.pHCDPointer
or bx, bx
jz UBGDT_Exit
; Set SI to the CurrentDevice device info structure
mov si, OFFSET CurrentDevice
; Form the far buffer pointer
mov di, OFFSET ControlDataBuffer
movzx edx, di
add edx, dGlobalDataArea
; Send a GetDescriptor command to the device to get its Device
; Descriptor. Assume a MaxPacket size of 64 bytes (the device will use 8,
; 16, 32, or 64). Regardless of the packet size used by te device we can
; always get the real MaxPacket size that the device is using, because
; this piece of information is at offset 7 in the device descriptor.
mov CurrentDevice.CntrlXfer.wLength, 8
mov CurrentDevice.CntrlXfer.wIndex, 0
mov CurrentDevice.CntrlXfer.wValue, (DESC_TYPE_DEVICE SHL 8)
mov CurrentDevice.CntrlXfer.wRequest, USB_RQ_GET_DESCRIPTOR
mov CurrentDevice.CntrlXfer.fpBuffer, edx
; Issue the HCD control transfer call
call (BBHCDHEADER PTR CS:[bx]).pHCDControlTransfer
jz UBGDT_Exit
; Get and store the endpoint 0 max packet size
movzx ax, (DeviceDescriptor PTR [di]).bEndp0MaxPacket
mov CurrentDevice.wEndp0MaxPacket, ax
; Give some delay
mov cx, ((10 * 1000) / 15) ; 10ms delay
call fixed_delay_far
; Now send a GetDescriptor command to the device to get its device descriptor.
mov CurrentDevice.CntrlXfer.wLength, 18
mov CurrentDevice.CntrlXfer.fpBuffer, edx
; Issue the HCD control transfer call
call (BBHCDHEADER PTR CS:[bx]).pHCDControlTransfer
jz UBGDT_Exit
; Get the relevant information from the descriptor and store it in
; device information struture
mov eax, DWORD PTR (DeviceDescriptor PTR [di]).wVendorId
mov DWORD PTR CurrentDevice.wVendorId, eax
; Look at each of the device's ConfigDescriptors and InterfaceDescriptors
; until an InterfaceDescriptor is found with BaseClass, SubClass, and
; Protocol fields indicating boot keyboard, mouse, hub or storage support.
mov al, (DeviceDescriptor PTR [di]).bNumConfigs
mov CurrentDevice.bNumConfigs, al
; Start with configuration number 0
mov CurrentDevice.bConfigNum, 0
; ASSUME THAT WE ARE GOING TO HANDLE ONLY ONE CONFIGURATION
mov CurrentDevice.CntrlXfer.wLength, (MAX_CONTROL_DATA_SIZE - 1)
mov ah, DESC_TYPE_CONFIG
mov al, CurrentDevice.bConfigNum
mov CurrentDevice.CntrlXfer.wValue, ax
mov CurrentDevice.CntrlXfer.fpBuffer, edx
; Issue the HCD control transfer call
call (BBHCDHEADER PTR CS:[bx]).pHCDControlTransfer
jz UBGDT_Exit
; DI should now point to a ConfigDescriptor. Verify this and then get
; necessary information out of this descriptor. Then point to the next
; descriptor.
cmp (ConfigDescriptor PTR [di]).bDescType, DESC_TYPE_CONFIG
jne UBGDT_SkipConfig ; Br if device did not return config desc
mov al, (ConfigDescriptor PTR [di]).bConfigValue ;AL = Config value
mov CurrentDevice.bConfigNum, al
mov cx, (ConfigDescriptor PTR [di]).wTotalLength
cmp cx, (MAX_CONTROL_DATA_SIZE - 1) ; CX Amount of data returned
jb UBGDT_NotOverFlowed
mov cx, (MAX_CONTROL_DATA_SIZE - 1) ; Limit size of data to what we can handle
UBGDT_NotOverFlowed:
; Convert size to end offset
add cx, di
movzx ax, (ConfigDescriptor PTR [di]).bDescLength
add di, ax
; DI should now point to an InterfaceDescriptor. Verify this
; and then check its BaseClass, SubClass, and Protocol fields for
; usable devices.
UBGDT_NextInterface:
cmp (InterfaceDescriptor PTR [di]).bDescType, DESC_TYPE_INTERFACE
jne UBGDT_SkipInterface ;Br if not on an interface desc
mov al, (InterfaceDescriptor PTR [di]).bInterfaceNum
mov CurrentDevice.bInterfaceNum, al
mov al, (InterfaceDescriptor PTR [di]).bAltSettingNum
mov CurrentDevice.bAltSettingNum, al
; Check for non-compliant USB devices
call USBBB_CheckNonCompliantDevice
; Get the base, sub class & protocol values
mov eax, DWORD PTR (InterfaceDescriptor PTR [di]).bBaseClass
; Clear the top 8 bits
and eax, 000FFFFFFh
IF MKF_USB_BB_DEV_KBD
mov dl, BIOS_DEV_TYPE_KEYBOARD ; Assume as keyboard
; First check for keyboard
cmp eax, (PROTOCOL_KEYBOARD SHL 16) + (SUB_CLASS_BOOT_DEVICE SHL 8) + BASE_CLASS_HID
je UBGDT_DeviceFound
ENDIF ;; IF MKF_USB_BB_DEV_KBD
mov dl, BIOS_DEV_TYPE_HUB ; Assume as hub
; Check for hub
cmp al, BASE_CLASS_HUB
je UBGDT_DeviceFound
mov dl, BIOS_DEV_TYPE_STORAGE
; Check for BaseClass mass storage
cmp al, BASE_CLASS_MASS_STORAGE
jne UBGDT_SkipInterface
ror eax, 16
; Base class is okay. Check the protocol field for supported protocols.
; Currently we support CBI, CB and BOT protocols
cmp al, PROTOCOL_CBI
je UBGDT_DeviceFound
cmp al, PROTOCOL_CBI_NO_INT
je UBGDT_DeviceFound
cmp al, PROTOCOL_BOT
je UBGDT_DeviceFound
UBGDT_SkipInterface:
movzx ax, (ConfigDescriptor PTR [di]).bDescLength ;AX = next desc
or ax, ax
jz UBGDT_SkipConfig ; Br if 0 length desc (should never happen, but...)
add di, ax ; BX Pointer to next desc
cmp di, cx
jae UBGDT_SkipConfig ; End of data
jmp SHORT UBGDT_NextInterface
UBGDT_DeviceFound:
; Store the sub class & protocol information
mov ax, WORD PTR (InterfaceDescriptor PTR [di]).bSubClass
mov stMassDeviceInfo.bSubClass, al
mov stMassDeviceInfo.bProtocol, ah
; Update the endpoints
; Adjust BX so that ES:DI+BX points to the next descriptor, abort if we're
; past the end of the data.
movzx ax, (InterfaceDescriptor PTR [di]).bDescLength
add di, ax ; DI Pointer to next desc
cmp di, cx
jae UBGDT_SkipConfig
; DI should now point to an EndpointDescriptor. If it does not, search
; down until we either find an EndpointDescriptor or go past the
; limit in wEnd.
UBGDT_CheckNextEPDesc :
; If it is interface descriptor then leave
cmp (InterfaceDescriptor PTR [di]).bDescType, DESC_TYPE_INTERFACE
je UBGDT_Success
push dx
cmp (EndpointDescriptor PTR [di]).bDescType, DESC_TYPE_ENDPOINT
jne UBGDT_FormNextEPDesc
mov al, (EndpointDescriptor PTR [di]).bEndpointAddr
and al, EP_DESC_ADDR_EP_NUM ; Bit 3-0: Endpoint number
mov bx, (EndpointDescriptor PTR [di]).wMaxPacketSize
; Check for endpoint type
mov dl, (EndpointDescriptor PTR [di]).bEndpointFlags
and dl, EP_DESC_FLAG_TYPE_BITS ; Isolate bits 1,0
cmp dl, EP_DESC_FLAG_TYPE_BULK ; Bit 1-0: 10 = Endpoint does bulk transfers
je UBGDT_BulkEndpoint
; Otherwise assume as interrupt endpoint
mov CurrentDevice.bEndpointNum, al
mov CurrentDevice.bIntEndpoint, al
mov CurrentDevice.wIntMaxPkt, bx
jmp SHORT UBGDT_FormNextEPDesc
UBGDT_BulkEndpoint:
test (EndpointDescriptor PTR [di]).bEndpointAddr, \
EP_DESC_ADDR_DIR_BIT ; Bit 7: Dir. of the endpoint
; 1/0 = In/Out
jnz UMCM_BulkInEndpoint
mov CurrentDevice.bBulkOutEndpoint, al
mov CurrentDevice.wBulkOutMaxPkt, bx
jmp SHORT UBGDT_FormNextEPDesc
UMCM_BulkInEndpoint:
; Bulk-In Endpoint found
mov CurrentDevice.bBulkInEndpoint, al
mov CurrentDevice.wBulkInMaxPkt, bx
UBGDT_FormNextEPDesc:
pop dx
movzx ax, (EndpointDescriptor PTR [di]).bDescLength
or ax, ax
jz UBGDT_Success ; If 0 length desc (should never happen, but...)
add di, ax ; BX = Pointer to next desc
cmp di, cx
jb UBGDT_CheckNextEPDesc ; If not past end of data
UBGDT_Success:
; Return success
or sp, sp
jmp SHORT UBGDT_Exit
UBGDT_SkipConfig:
cmp sp, sp ; Indicate 0 RETURN FAILURE ALWAYS
UBGDT_Exit:
mov al, dl
pop edx
mov dl, al
pop di
pop si
pop cx
pop bx
pop eax
ret
USBBB_GetDeviceType ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBBB_ConfigureUSBDevice
;
; Description: This function will set the device address for the USB
; device by sending "SET_ADDRESS" command to the device with
; appropriate device address and also sets the configuration
; for the device by sending "SET_CONFIGURATION" command with
; appropriate config number
;
; Input: None
;
; Output: ZR Error during set address/config call
; NZ Set address/config are successful
;
; Modified: Nothing
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBBB_ConfigureUSBDevice PROC NEAR PUBLIC
push eax
push si
; Set SI to the current devices device info structure
mov si, OFFSET CurrentDevice
; Set address for the device
movzx ax, bCurrentDeviceAddress
inc ax
mov CurrentDevice.CntrlXfer.wValue, ax
mov CurrentDevice.CntrlXfer.wIndex, 0
mov CurrentDevice.CntrlXfer.wRequest, USB_RQ_SET_ADDRESS
call USBBB_IssueControlXferWithoutData
jz UBCUD_Exit
; Set device address to the value set
mov CurrentDevice.bDeviceAddress, al
inc bCurrentDeviceAddress
; Set configuration for the device
mov CurrentDevice.CntrlXfer.wRequest, USB_RQ_SET_Configuration
movzx ax, CurrentDevice.bConfigNum ; ConfigNum to set
mov CurrentDevice.CntrlXfer.wValue, ax
call USBBB_IssueControlXferWithoutData
UBCUD_Exit:
pop si
pop eax
ret
USBBB_ConfigureUSBDevice ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: USBBB_GetHubDescriptor
;
; Description: This function will get the hubs descriptor structure from
; the hub device
;
; Input: SI Pointer to the device information structure
;
; Output: ZR Error during get hub descriptor call
; NZ Get hub descriptor call is successful
; DS:DI Hub descriptor
;
; Modified: Nothing
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
USBBB_GetHubDescriptor PROC NEAR PUBLIC
push eax
push bx
; Set buffer address & length
mov (DeviceInfo PTR [si]).CntrlXfer.wLength, (MAX_CONTROL_DATA_SIZE - 1)
mov di, OFFSET ControlDataBuffer
movzx eax, di
add eax, dGlobalDataArea
mov (DeviceInfo PTR [si]).CntrlXfer.fpBuffer, eax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -