⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbkbd.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;
; Input: 	SI	Pointer to HCStruc
;		BX	Pointer to device information structure
;		DI	Pointer to the data buffer
;
; Output: 	Nothing
;
; Modified:	Nothing
;
; Notes:	TD's control status field has the packet length (0 based).
;		It could be one of three values 0,1 or 7 indicating packet
;		lengths of 1, 2 & 8 repectively.
;		The format of 8 byte data packet is as follow:
;		     Byte              Description
;		-----------------------------------------------------------
;			0	Modifier key (like shift, cntr & LED status)
;			1	Reserved
;			2	Keycode of 1st key pressed
;			3	Keycode of 2nd key pressed
;			4	Keycode of 3rd key pressed
;			5	Keycode of 4th key pressed
;			6	Keycode of 5th key pressed
;			7	Keycode of 6th key pressed
;		-----------------------------------------------------------
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBKBDProcessKeyboardData	PROC NEAR SYSCALL PUBLIC USES AX BX CX SI DI

; Save the device info pointer for later use
	mov	SavedHCStrucPtr, si

; SI	HCStruc
; BX	Device Info
; DI	Pointer to data buffer
	call	USBKB_Scanner

; Update the LED status
	mov	al, 0FFh
	call	USBKB_UpdateLEDState

	ret
USBKBDProcessKeyboardData	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBKBDPeriodicInterruptHandler
;
; Description:	This routine is called every 16ms and is used to send
;		the characters read from USB keyboard to the keyboard
;		controller for legacy operation. Also this function updates
;		the keyboard LED status
;
; Input: 	SI	Pointer to the HCStruc structure
;
; Output: 	Nothing
;
; Modified:	Nothing
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBKBDPeriodicInterruptHandler		PROC NEAR SYSCALL PUBLIC USES BX DX DI

; Save the HCStruc pointer for later use
	mov	SavedHCStrucPtr, si

; Update the LED status
	xor	al, al
	call	USBKB_UpdateLEDState

; Check for break code generation
	mov	al, bBreakCodeDeviceID
	or	al, al			; Check for break code generation
	jz	UHPIH_Continue

	mov	ah, 0
UHPIH_ContConversion:
	inc	ah			; Form device id (1,2,3,4,5,6,7,8)
	shr	al, 1
	jnc	UHPIH_ContConversion

	mov	dl, ah

; Get the corresponding device info structure
	call	USBGetDeviceInfoFromDevAddr	; DL - Device address
	mov	bx, ax

	mov	di, OFFSET pKBInputBuffer	; Scratch to generate break code
	mov	DWORD PTR ds:[di], 0
	mov	DWORD PTR ds:[di+4], 0
; Generate break code
; BX	Device info pointer
; SI	HCStruc pointer
; DI	Pointer to the keyboard buffer buffer
	call	USBKB_Scanner

UHPIH_Continue:

; Check and send KBC data
	INVOKE	USBKBC_SendKBCData

UPIH_Exit:
	ret

USBKBDPeriodicInterruptHandler	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBKBDFindUSBKBDeviceTableEntry
;
; Description:	This routine searches for the HID table entry which matches
;		the provided device info structure
;
; Input: 	AX	Pointer to DeviceInfo structure
;
; Output: 	NZ	Matching HID table structure found
;			SI	Matching HID table structure
;		ZR	0 on error
;
; Modified:	SI
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBKBDFindUSBKBDeviceTableEntry	PROC NEAR SYSCALL

	push	cx

	mov	cx, MKF_HID_DEVICE_LIMIT
	mov	si, OFFSET pUSBKBDeviceTable
UHFHTE_CheckNextEntry:
	cmp	WORD PTR [si], ax
	je	UHFHTE_Found
	add	si, 2
	loop	UHFHTE_CheckNextEntry
	cmp	sp, sp		; Set zero flag
	jmp	SHORT UHFHTE_Exit

UHFHTE_Found:
	or	sp, sp		; Clear zero flag
UHFHTE_Exit:
	pop	cx
	ret
USBKBDFindUSBKBDeviceTableEntry	ENDP

;----------------------------------------------------------------------------
;			END OF ROUTINES
;----------------------------------------------------------------------------
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBKB_Scanner
;
; Description:	This routine converts the USB keyboard input data into
;		IBM PC format scan code
;
; Input: 	BX	Pointer to the device info. structure
;		DI	Pointer to the 8byte USB keyboard data
;
; Output: 	Nothing
;
; Modified:	Nothing
;
; Notes:	The format of the 8byte USB keyboard data is as follows:
;----------------------------------------------------------------------------
;	Byte                     Description
;----------------------------------------------------------------------------
;  Byte 0		Contains modifier key bits like SHIFT, CTRL, ALT etc
;  Byte 1		Reserved
;  Byte 2 - 7		Keycode (1-6) of the keys pressed
;----------------------------------------------------------------------------
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBKB_Scanner		PROC NEAR SYSCALL PUBLIC USES AX BX CX SI DI ES

	LOCAL	bKeyCode:BYTE, wWorkOffset:WORD
; Set ES
	push	ds
	pop	es

	mov	si, di

	mov	ah, (DeviceInfo PTR [bx]).bDeviceAddress

; Convert the device address (1,2,3 .. 8) into
; device ID bit pattern (001h, 002h, 004h .. 080h)
; AH - Device Address
	mov	al, 80h
UKS_CheckNextID:
	rol	al, 1
	dec	ah
	jnz	UKS_CheckNextID

	mov	bCurrentDeviceID, al	; Save current device ID

; The 8 byte USB keyboard data is first copied into the input buffer
; for processing. Modifier bits are expanded into bytes.

; Convert modifier key bits to key code bytes. If bit 0 is set output
; 0E0h, 0E1h for bit 1 and so on.
	mov	di, OFFSET pKBInputBuffer
	mov	cx, 8			; Number of bits to process
	lodsb				; Load modifier byte
	mov	ah, 0E0h		; First modifier byte
	xchg	ah, al			; AL = 0E0h
UKS_CheckNextModBit:
	shr	ah, 1
	jnc	UKS_ModKeyNotPressed
; Modifier key pressed. Send appropriate byte to the input buffer
	stosb
UKS_ModKeyNotPressed:
	inc	al
	loop	UKS_CheckNextModBit

; Discard the reserved byte from the USB KB input data stream
	lodsb

; Process the remaining 6 input bytes
	mov	cx, 6
UKS_ProcessNextByte:
; Get next byte
	lodsb

; Check whether it has valid data, if not skip it
	or	al, al
	jz	UKS_SkipCurrentByte

; Check whether the input is overrun. Overrun condition occurs if more than
; 6 keys are pressed at a same time. In that case, USB KB sends 01h in all
; its 6 key code bytes
	cmp	al, 01h		; Keyboard error roll over (overrun) ?
	jne	UKS_StoreData	; No. Put the data byte into the buffer

; Check the space availability for the overrun code in the character buffer
; Overrun code needs 1 byte (0+1)
	xor	al, al
	call	USBKBC_CheckCharacterBufferFull
	jz	UKS_Exit	; Buffer full, Exit.

	mov	al, 0FFh	; Scan code set 2 & 3 overrun code

IF	MKF_USB_KBC_EMULATION
; The following routine returns overrun code depending upon the scan code
; set chosen. This facility is available only when 60/64h port trapping
; is enabled. Otherwise the scan code set is locked to set 2.
	call	USBTrap_GetOverrunCode
ENDIF

	call	USBKBC_SendToCharacterBuffer	; Data in AL

; Invalidate the last key code processed data
	mov	bLastUSBKeyCode, 000h

	jmp	UKS_Exit

UKS_StoreData:
	stosb

UKS_SkipCurrentByte:
	loop	UKS_ProcessNextByte

; Null terminate the input buffer
	xor	al, al
	stosb			; Null terminated

; Check for break code generation condition
	mov	cx, di
	mov	di, OFFSET pKBInputBuffer
	sub	cx, di			; CX - Length of the buffer
	xor	al, al
	repz	scasb
	jnz	UKS_KeyCodePresent	; Key is pressed in the keyboard

; No key pressed. Set flags to generate break code
	mov	al,bCurrentDeviceID
	or	bBreakCodeDeviceID, al	; set breakcode generation flag

UKS_KeyCodePresent:

	mov	si, OFFSET pKBInputBuffer
UKS_KeyCodeGenerateLoop:
	lodsb

; Save the keycode in the local variable
	mov	bKeyCode, al

; Check end of the list
	cmp	bKeyCode, 0
	je	UKS_CheckBreakCodeGen	; EOL reached, check break code

; Get scan code buffer size
	mov	di, OFFSET pKBCScanCodeBufferStart
	mov	cx, pKBCScanCodeBufferPtr
	sub	cx, di

; Is scan code buffer is empty ?
	jcxz	UKS_ScanCodeBufEmpty	; Yes.

; Check whether the scan code buffer already have this key value
	repnz	scasb
	jz	UKS_AlreadyInBuffer	; Yes found.

; Check whether end of scan code buffer reached
	cmp	di, OFFSET pKBCScanCodeBufferEnd
	jae	UKS_CheckBreakCodeGen	; Yes buffer full ! Check break code.

UKS_ScanCodeBufEmpty:

; The key code is not in the buffer and also the buffer is not full. So
; generate the make code for the newly pressed key.

	INVOKE	USBKB_GenerateScanCode, USB_GEN_MAKE_CODE, bKeyCode, 0

	mov	bLastUSBKeyCode, al

	mov	BYTE PTR [di], al	; Put in scan code buffer

; Get the index
	sub	di, OFFSET pKBCScanCodeBufferStart

; Store the device ID
	add	di, OFFSET pKBCDeviceIDBufferStart
	mov	al, bCurrentDeviceID
	mov	BYTE PTR [di], al	; Store device ID

; Get the index
	sub	di, OFFSET pKBCDeviceIDBufferStart

; Store the shift key status
	add	di, OFFSET pKBCShiftKeyStatusBufferStart
	mov	al, bUSBKBShiftKeyStatus
	mov	BYTE PTR [di], al	; Store bUSBKBShiftKeyStatus info

; Update pointer
	inc	pKBCScanCodeBufferPtr

; Check and load typematic rate setting
	mov	ax, wUSBKBC_StatusFlag
	and	ax, KBC_TYPE_DELAY_BIT_MASK
	shr	ax, KBC_TYPE_DELAY_BIT_SHIFT

	push	bx
	mov	bx, ax
	movzx	ax, BYTE PTR [bx + cs:pTypematicRateDelayTable]
	pop	bx

	mov	wRepeatRate, ax
	mov	wRepeatCounter, 0
	jmp	UKS_KeyCodeGenerateLoop		; Continue

UKS_AlreadyInBuffer:
; Update pointer
	dec	di

; Get Index
	sub	di, OFFSET pKBCScanCodeBufferStart

; Save current device id
	add	di, OFFSET pKBCDeviceIDBufferStart
	mov	al, bCurrentDeviceID
	or	BYTE PTR [di], al		; Store device ID
	jmp	UKS_KeyCodeGenerateLoop		; Continue

UKS_CheckBreakCodeGen:
; SI - pKBInputBuffer
; Check for break code generation
; Update pointer
	dec	si
; Get index
	sub	si, OFFSET pKBInputBuffer
	mov	cx, si

	mov	si, OFFSET pKBCScanCodeBufferStart
UKS_ProcessNextCharacter:
	cmp	si, pKBCScanCodeBufferPtr
	jae	UKS_BreakCodeGenCompleted	; Breakcode generation over

; Get next input character
	lodsb

	mov	di, OFFSET pKBInputBuffer
	jcxz	UKS_EndOfBufferReached

	push	cx
	repnz	scasb
	pop	cx
	jz	UKS_ProcessNextCharacter	; Found, continue

UKS_EndOfBufferReached:
; Update pointer
	mov	di, si
	dec	di

; Get Index
	sub	di, OFFSET pKBCScanCodeBufferstart

; Save the index
	mov	wWorkOffset, di

; Clear device ID
	add	di, OFFSET pKBCDeviceIDBufferStart
	mov	al, bCurrentDeviceID
	not	al
	and	BYTE PTR [di], al		; Clear device ID
	jnz	UKS_ProcessNextCharacter	; Continue

; Get Index
	sub	di, OFFSET pKBCDeviceIDBufferStart

; Get shift key status from the buffer
	add	di, OFFSET pKBCShiftKeyStatusBufferStart
	mov	al, BYTE PTR [di]

	xchg	al, bUSBKBShiftKeyStatus	; Modify bUSBKBShiftKeyStatus
						; for break code generation

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -