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

📄 usbmain.asm

📁 CY7C63743 usb键盘的源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	call	no_data_control					; handshake with host
	ret										; for interface 0 then we are done
							

; Set the endpoint stall feature for the selected endpoint.
SetEndpointStall:
	mov		A, [wValue]						; load wValue
	cmp		A, endpoint_stall				; test for valid feature
	jnz		SendStall						; stall unsupported features
    mov     A,[wIndexHi]
    cmp     A,0
    jnz     SendStall
    mov     A,[wIndex]
    cmp     A,0                             ; if stalling endpoint 0
    jz      SendStall
    cmp     A,80h                           ; in's or out, ack it but do nothing
    jz      SendStall                       ; about it
    mov		A, [configuration_status]       ; if not configured
	cmp		A, UNCONFIGURED                 ; anything else is illegal
    jz      SendStall
    mov     A,[wIndex]
    cmp     A,81h
    jnz     .se2
    mov     A,1
	mov		[ep1_stall_status], A		    ; stalled
	mov		A, STALL						; stall endpoint one
	iowr	EP_A1_Mode
    jmp     .done
.se2:
    cmp     A,082h
    jnz     SendStall
    mov     A,1
	mov		[ep2_stall_status], A		    ; stalled
	mov		A, STALL						; stall endpoint two
	iowr	EP_A2_Mode
.done:
	call	no_data_control					; handshake with host

	ret										; return

; The device status is a 16-bit value (two bytes) with only D[1:0]
; defined.  D0=0 specifies bus-powered, which never changes.  D1
; reflects the status of the device_remote_wakeup feature.  This
; feature can either be disabled (D1=0) or enabled (D1=1).
GetDeviceStatus:
    mov A, 2							; send two bytes
    mov [data_count], A
	mov A,[remote_wakeup_status]
	jmp Send






; There are five descriptor types.  The descriptor type will be in
; the high byte of wValue.  The descriptor index will be in the low
; byte of wValue.  The standard request to a device supports three
; of these types: device, configuration, and string.  The standard
; request does not support interface or endpoint descriptor types.


GetDescriptor:
		mov		X,report_id_tbl_len			;init X to size of descriptor type/index table
.loop:
		dec		X
		jc      SendStall					;if X is neg, table has been completely traversed
		dec     X	
        mov     A,X						
		index  report_id_tbl				;else get 1st byte of table entry
		cmp		A,[wValueHi]				;compare with descriptor type
		jnz		.loop						;no match, contine
		mov		A,X							;else get 2nd byte of table entry
		index   report_id_tbl+1				;compare with decrptor index
		cmp		A,[wValue]					;
		jnz		.loop						;no match, continue
.found:										;X points to table entry
		mov		A,X
		asr		A							;make it a unary index
		mov		X,A							;and save it
		mov		A,[wValueHi]				;if we're getting a HID descriptor
		cmp		A,HID
		jz		.adjust
		cmp		A,report					;or a report descriptor,
		jz		.adjust                     ;adjust it
		jmp		.continue
.adjust:
        mov     A,[wIndexHi]
        cmp     A,0
        jnz     SendStall
		mov		A,[wIndex]					;wIndex indicates which of 2
		cmp		A,2
		jnc		SendStall
		mov		A,X		
        dec     A					        ;adjust the index in X by this value
		add		A,[wIndex]
		mov		X,A
.continue:
		mov		A,X							;A now contains index of exact descriptor we require
		jmp		SendRom						;

XPAGEOFF
report_id_tbl:
db device,00,configuration,00,string,00
db string,01,string,02,string,03,string,04,string,05,string,06
db HID,00,HID,00,report,00,report,00
report_id_tbl_end:
XPAGEON
report_id_tbl_len: EQU (report_id_tbl_end - report_id_tbl) 

	

; Return the current device configuration to the host.  The possible
; values are zero (unconfigured) and one (configured).
GetConfiguration:
	mov		A, 1								; send one byte
	mov		[data_count], A
	mov		A,[configuration_status]
	jmp		Send

; The interface status is a 16-bit value (two bytes) that is always
; zero for both bytes.
GetInterfaceStatus:
	mov		A,2
	mov		[data_count],A
	mov		A,0
	jmp		Send

; The interface status is an 8bit value that is always zero since
; there are no alternate interface settings defined
GetInterface:
    call    Interface0
    jz      .get
    call    Interface1
    jnz     SendStall
.get:
	mov		A,1
	mov		[data_count],A
	mov		A,0
	jmp		Send

; The endpoint status is a 16-bit value (two bytes) with only one
; bit (D0) defined.  If D0=0, then the selected endpoint is not
; stalled.  If D0=1, then the selected endpoint is stalled.
GetEndpointStatus:
    mov		A, 2							; send two bytes
    mov		[data_count], A
    mov     A,[wIndexHi]
    cmp     A,0
    jnz     SendStall
    mov     A,[wIndex]
    cmp     A,0
    jz      Send                            ;endpoint 0 status, always not stalled
    cmp     A,80h
    mov     A,0
    jz      Send                            ;endpoint 0 status again
    mov		A, [configuration_status]
	cmp		A, UNCONFIGURED					;if unconfigured, nothing else to do
    jz      SendStall
    mov     A,[wIndex]						;EP1 status?
    cmp     A,081h
    jnz     .ge2
    mov		A, [ep1_stall_status]			;send status of EP1
	jmp		Send
.ge2:
    cmp     A,082h							;EP2 status?
    jnz     SendStall
    mov     A,[ep2_stall_status]
    jmp     Send							;send status of EP2
;------------------------------------------------------------------------
; Set Report is used to control the LEDs in the keyboard.  An OUT packet
; will be received that will have a bit set for every LED that should be
; turned on.
SetReport:
    call    Interface0
    jnz     SendStall
    mov     A,[wValueHi]
    cmp     A,02
    jnz      SendStall
    mov		A, [configuration_status]
	cmp		A, UNCONFIGURED					;ignore if unconfigures
    jz      SendStall
    mov	A, ACKOUTSTATUSIN				    ; accept OUT, enable TX0 IN
    mov     [EP0_Next_Mode],A
    ret



;table to translate usb-command enumeration of leds into our own bits
XPAGEOFF
usb_led_tbl:
    db  0
    db  NUM_LOCK_LED
	db	CAPS_LOCK_LED
    db  NUM_LOCK_LED + CAPS_LOCK_LED
    db  SCROLL_LOCK_LED
    db  SCROLL_LOCK_LED + NUM_LOCK_LED
    db  SCROLL_LOCK_LED + CAPS_LOCK_LED
    db  SCROLL_LOCK_LED + NUM_LOCK_LED + CAPS_LOCK_LED	

XPAGEON

; Set Idle silences a particular report on the interrupt pipe until a new
; event occurs or the specified amount of time (wValueHi) passes.
; The resolution of the specified duration is 4ms (i.e the weight of the
; LSB is 4ms)
SetIdle:
    call    Interface0
    jz      .SetIfc0Idle
    call    Interface1
    jz      .SetIfc1Idle
    jmp		SendStall                         ;else it's a bogus request

.SetIfc0Idle:                                  ;
    mov		A,kbd_idle_period                 ;point A at base of keyboard idle table
    call    AdjustIdle
    jmp		.done_SetIdle

.SetIfc1Idle:                                  ;interface 1 supports both consumer and power keys
    mov		A,[wValue]
    cmp		A,0                               ;if setting all idles,
    jnz		.setifc01

    mov     X,id_tbl_len                      ;init X to length of report ID table  
.all_loop:
    dec     X
    jc      .done_SetIdle                     ;done, get out
    mov     A,X
    index   idle_tbl
    call    AdjustIdle                        ;adjust idle for this report
    jmp     .all_loop                         ;and get out

.setifc01:                                    ;else if setting only one
 	mov		X,id_tbl_len			          ;init X to size of report id table
.loop:
	dec		X
	jc      SendStall				          ;if X is neg, table has been completely traversed
    mov     A,X						
	index   id_tbl				              ;else get  byte of table entry
	cmp		A,[wValue]				           ;compare with report ID
    jnz		.loop					            ;no match, contine
.found:								          ;X points to table index
    mov     A,X         
    index   idle_tbl                          ;get address of idle setting variable
    call    AdjustIdle                        ;adjust idle for this index
.done_SetIdle:
	call	no_data_control                    ; handshake with host
    ret

AdjustIdle:
                                                ;entered with A = address of idle variable
	push	X
	mov		X,A
	mov		A,[X+0]                             ; get current idle period
	cmp		A,0									; if zero, 
	jnz		.set1
	mov		A,[wValueHi]						; institute new idle period immediately
	mov		[X+0],A
	mov		[X+1],A
	jmp		.exit
.set1:
	mov		A,[X+1]                             ;else get time left in current idle period
	cmp		A,2
	jc		.start_new_idle_period              ;if less than 4 ms, 
      
	mov		A,[wValueHi]						; write next idle period only
	mov		[X+0],A                             ;and leave current idle period alone
	jmp		.exit

.start_new_idle_period:
	mov		A,[wValueHi]						;compare new period with old
	cmp		A,[X+0]								;if new period is shorter than the old,
    mov		[X+0],A                
    jnc		.set2
    mov		A,1									;set next report period and 
    mov		[X+1],A								;and force a new report immediately
    jmp		.exit                       
.set2:											;else new period is longer than old,
    sub		A,[X+1]								;so adjust current period to expire sooner
    mov		[X+1],A             
       
.exit:
    pop		X
    ret
; Set Protocol switches between the boot protocol and the report protocol.
; For boot protocol, wValue=0.  For report protocol, wValue=1.
SetProtocol:
    call    Interface0
    jz      .setprot0
    call    Interface1
    jnz     SendStall
    mov     A,[wValue]
    cmp     A,1
    jnz     SendStall
    jmp     .done
.setprot0:    
	mov		A, [wValue]						    ; load wValue
	cmp		A, REPORT_PROTOCOL+1			    ; only valid protocols are BOOT & REPORT
	jnc		SendStall
	mov		[protocol_status], A				; write new protocol value
.done:
	call	no_data_control						; handshake with host
	ret											; return





; Get Report returns a report over the control pipe
GetReport:
    mov		A, [configuration_status]           ;skip if unconfigured
	cmp		A, UNCONFIGURED
    jz      SendStall
    call    Interface0                          ;check which interface requested
    jz      .getifc0
    call    Interface1
    jnz     SendStall
    jmp     .getifc1
.getifc0:                                       ;interface 0!
    mov     A,[wValueHi]
    cmp     A,2
    jz      .getleds                            ;wValueHi = 2, get led report
    cmp     A,1
    jnz     SendStall


    mov		A,8                                 ;wValueHi = 1, get keyboard report
    mov     [data_count],A

    mov		A,[usb_current_state]
	cmp		A,USB_REPORT_ERROR
	jnz		.keys

    mov		A,0									;if we need to send an error report
	index   key_error_offset
    mov		[page],A							;point at ROM with all 1's
    mov		A,0
	index   key_error_offset + 1
    mov		[data_start],A					 
    jmp		SendAll


.keys:                                          ; else we need to send the key buffer  
	mov		A, usb_report_buffer				; set the start address to report_buffer
	jmp		SendRam								; send report (from RAM) to host
 	

.getifc1:                                       ;interface 1!
    cmp		A,1
    jnz		SendStall                           ;anything other than interface 1 not supported

	mov		X,id_tbl_len			            ;init X to length of report ID table
.loop:
	dec		X
	jc      SendStall				            ;if X is neg, table has been completely traversed
    mov     A,X						
	index  id_tbl				                ;else get id
	cmp		A,[wValue]				            ;compare with requested report ID
	jnz		.loop					            ;no match, contine
.found:								            ;X now indexes to report ID
    mov     A,X
    index   report_len_tbl                      ;use it to get the report length
    mov     [data_count],A                      ;store this in data count
    mov     A,X
    index   report_addr_tbl                     ;now get starting address in RAM of report
    jmp     SendRam                             ;and go send it
        

.getleds:
    mov		A,1
    mov     [data_count],A
    mov     A,[usb_leds]
    jmp     Send	


⌨️ 快捷键说明

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