📄 usb_ch9.asm
字号:
movwf BufferData+5
incf FSR,f
movf INDF,w
movwf BufferData+6
incf FSR,f
movf INDF,w
movwf BufferData+7
bsf STATUS, RP0
movlw 0x88 ; set UOWNs bit back to SIE
movwf BD0OST
movlw 0x08
movwf BD0OBC ; reset the byte count too.
movwf BD0IST ; return the in buffer to us (dequeue any pending requests)
bcf UCTRL,PKT_DIS ; Assuming there is nothing to dequeue, clear the packet disable bit
bcf STATUS,RP0 ; bank 2
clrf USB_dev_req ; clear the device request..
movf BufferData+bmRequestType,w
btfsc STATUS,Z
goto HostToDevice
movf BufferData+bmRequestType,w
xorlw 0x01 ; test for host to Interface tokens
btfsc STATUS,Z
goto HostToInterface
movf BufferData+bmRequestType,w
xorlw 0x02 ; test for host to Endpoint tokens
btfsc STATUS,Z
goto HostToEndpoint
movf BufferData+bmRequestType,w
xorlw 0x80 ; test for device to Host tokens
btfsc STATUS,Z
goto DeviceToHost
movf BufferData+bmRequestType,w
xorlw 0x81 ; test for device to Interface tokens
btfsc STATUS,Z
goto InterfaceToHost
movf BufferData+bmRequestType,w
xorlw 0x82 ; test for device to Endpoint tokens
btfsc STATUS,Z
goto EndpointToHost
pagesel ClassSpecificRequest
movf BufferData+bmRequestType,w
andlw 0x60 ; mask off type bits
xorlw 0x20 ; test for class specific
btfsc STATUS,Z ; was it a standard request?
goto ClassSpecificRequest ; nope, see if it was a class specific request
CheckForVendorRequest
movf BufferData+bmRequestType,w
andlw 0x60 ; mask off type bits
xorlw 0x40 ; test for vendor specific
btfss STATUS,Z ; was it a standard request?
pagesel wrongstate
goto wrongstate
pagesel CheckVendor
goto CheckVendor ; nope, see if it was a vendor specific
return
; now test bRequest to see what the request was.
CheckForStandardRequest
; bmRequestType told us it was a Host to Device transfer. Now look at
; the specifics to see what's up
HostToDevice ; starts in bank 2
movf BufferData+bRequest,w ; what was our request
xorlw CLEAR_FEATURE
btfsc STATUS,Z
goto Clear_Device_Feature
movf BufferData+bRequest,w ; was our request Set Address
xorlw SET_ADDRESS
btfsc STATUS,Z
goto Set_Address
movf BufferData+bRequest,w ; was our request Set Configuration
xorlw SET_CONFIGURATION
btfsc STATUS,Z
goto Set_Configuration
movf BufferData+bRequest,w ; was our request Set Feature
xorlw SET_FEATURE
btfsc STATUS,Z
goto Set_Device_Feature
goto wrongstate
HostToInterface ; starts in bank 2
movf BufferData+bRequest,w ; what was our request
xorlw CLEAR_FEATURE
btfsc STATUS,Z
goto Clear_Interface_Feature
movf BufferData+bRequest,w ; was our request Set Interface
xorlw SET_INTERFACE
btfsc STATUS,Z
goto Set_Interface
movf BufferData+bRequest,w ; was our request Set Feature
xorlw SET_FEATURE
btfsc STATUS,Z
goto Set_Interface_Feature
HostToEndpoint ; starts in bank2
movf BufferData+bRequest,w ; what was our request
xorlw CLEAR_FEATURE
btfsc STATUS,Z
goto Clear_Endpoint_Feature
movf BufferData+bRequest,w ; was our request Set Feature
xorlw SET_FEATURE
btfsc STATUS,Z
goto Set_Endpoint_Feature
DeviceToHost ; starts in bank2
movf BufferData+bRequest,w ; what was our request
xorlw GET_CONFIGURATION
btfsc STATUS,Z
goto Get_Configuration
movf BufferData+bRequest,w ; was our request Get Decriptor?
xorlw GET_DESCRIPTOR
btfsc STATUS,Z
goto Get_Descriptor
movf BufferData+bRequest,w ; was our request Get Status?
xorlw GET_STATUS
btfsc STATUS,Z
goto Get_Device_Status
InterfaceToHost ; starts in bank2
movf BufferData+bRequest,w ; was our request Get Interface?
xorlw GET_INTERFACE
btfsc STATUS,Z
goto Get_Interface
movf BufferData+bRequest,w ; was our request Get Status?
xorlw GET_STATUS
btfsc STATUS,Z
goto Get_Interface_Status
movf BufferData+bRequest,w ; was our request Get Decriptor?
xorlw GET_DESCRIPTOR
btfsc STATUS,Z
goto Get_Descriptor
EndpointToHost ; starts in bank2
movf BufferData+bRequest,w ; was our request Get Status?
xorlw GET_STATUS
btfsc STATUS,Z
goto Get_Endpoint_Status
pagesel wrongstate ; unrecognised token, stall EP0
goto wrongstate
return
; ******************************************************************
; Get Descriptor
; Handles the three different Get Descriptor commands
; ******************************************************************
Get_Descriptor ; starts in bank2
pagesel Get_Report_Descriptor
movf BufferData+(wValue+1),w ; request, which seems to be undefined,
xorlw 0x22 ; but it won't enumerate without it
btfsc STATUS,Z
goto Get_Report_Descriptor
movf BufferData+(wValue+1),w
xorlw 0x21
btfsc STATUS,Z
goto Get_HID_Descriptor
pagesel GetCh9Descriptor
GetCh9Descriptor
movlw high StartGDIndex ; set up PCLATH with the current address
movwf PCLATH ; set up pclath for the computed goto
movf BufferData+(wValue+1),w ; get descriptor type
andlw 0x03 ; keep things under control
addlw low StartGDIndex
btfsc STATUS,C ; was there an overflow?
incf PCLATH,f ; yes, bump PCLATH
movwf PCL ; adjust PC
StartGDIndex
goto wrongstate ; 0
goto Get_Device_Descriptor ; 1
goto Get_Config_Descriptor ; 2
goto Get_String_Descriptor ; 3
; goto Get_Interface_Descriptor ; 4 - not used
; goto Get_EndPoint_Descriptor ; 5 - not used
; goto wrongstate ; 6
; goto wrongstate ; 7
; *********************************************************************
; Looks up the offset of the device descriptor via the low order byte
; of wValue. The pointers are set up and the data is copied to the
; buffer, then the flags are set.
;
; EP0_start points to the first word to transfer
; EP0_end points to the last, limited to the least of the message length
; or the number of bytes requested in the message (wLength).
; EP0_maxLength is the number of bytes to transfer at a time, 8 bytes
; ******************************************************************
Get_Device_Descriptor ; starts in bank 2
pagesel Descriptions ; set up PCLATH for call below
movlw GET_DESCRIPTOR
movwf USB_dev_req ; currently processing a get descriptor request
movlw 8
movwf EP0_maxLength
movlw low DeviceDescriptor
movwf EP0_start
movlw high DeviceDescriptor
movwf EP0_start+1
call Descriptions ; get length of device descriptor
movwf EP0_end ; save length
pagesel DeviceEndPtr
movf BufferData+(wLength+1),f ; move it to itself, check for non zero.
btfss STATUS,Z ; if zero, we need to compare EP0_end to requested length.
goto DeviceEndPtr ; if not, no need to compare. EP0_end is shorter than request length
subwf BufferData+wLength,w ; compare against requested length
movf BufferData+wLength,w
btfss STATUS,C
movwf EP0_end
DeviceEndPtr
incf EP0_end,f
pagesel copy_descriptor_to_EP0
call copy_descriptor_to_EP0
return
; *********************************************************************
; Looks up the offset of the config descriptor via the low order byte
; of wValue. The pointers are set up and the data is copied to the
; buffer, then the flags are set.
;
; EP0_start points to the first word to transfer
; EP0_end points to the last, limited to the least of the message length
; or the number of bytes requested in the message (wLength).
; EP0_maxLength is the number of bytes to transfer at a time, 8 bytes
; ******************************************************************
Get_Config_Descriptor ; starts in bank2
pagesel Descriptions ; set up PCLATH for call below
movlw GET_DESCRIPTOR
movwf USB_dev_req ; currently processing a get descriptor request
bcf STATUS,C
rlf BufferData+wValue,w
call Config_desc_index ; translate index to offset into descriptor table
movwf EP0_start
bcf STATUS,C
rlf BufferData+wValue,w
addlw 1 ; point to high order byte
call Config_desc_index ; translate index to offset into descriptor table
movwf EP0_start+1
movlw 2 ; bump pointer by 2 to get the complete descriptor
addwf EP0_start,f ; length, not just config descriptor
btfsc STATUS,C
incf EP0_start+1,f
call Descriptions ; get length of the config descriptor
movwf EP0_end ; Get message length
movlw 2 ; move EP0_start pointer back to beginning
subwf EP0_start,f
btfss STATUS,C
decf EP0_start+1,f
movf BufferData+(wLength+1),f ; test for 0
btfsc STATUS,Z
pagesel CmpLowerByte
goto CmpLowerByte
goto ConfigEndPtr ; if not, no need to compare. EP0_end is shorter than request length
CmpLowerByte
movf EP0_end,w
subwf BufferData+wLength,w ; compare against requested length
btfsc STATUS,C
goto ConfigEndPtr
LimitSize
movf BufferData+wLength,w ; if requested length is shorter..
movwf EP0_end ; save it.
ConfigEndPtr
movlw 8
movwf EP0_maxLength
incf EP0_end,f
pagesel copy_descriptor_to_EP0
call copy_descriptor_to_EP0
return
; ******************************************************************
; Set up to return String descriptors
; Looks up the offset of the string descriptor via the low order byte
; of wValue. The pointers are set up and the data is copied to the
; buffer, then the flags are set.
; ******************************************************************
Get_String_Descriptor ; starts in bank2
movlw GET_STRING_DESCRIPTOR
movwf USB_dev_req ; currently processing a get descriptor request
movf BufferData+wIndex,w
btfss STATUS,Z
goto not_string0
movf BufferData+(wIndex+1),w
btfss STATUS,Z
goto not_string0
movlw low String0
movwf EP0_start
movlw high String0
movwf EP0_start+1
goto found_string
not_string0
movlw high (String0+2)
movwf EP0_start+1
movlw low (String0+2)
movwf EP0_start
clrf inner
check_langid
pagesel StringDescriptions
call StringDescriptions
pagesel wrong_langid
incf EP0_start,f
subwf BufferData+wIndex, w
btfss STATUS, Z
goto wrong_langid
pagesel StringDescriptions
call StringDescriptions
pagesel right_langid
subwf BufferData+(wIndex+1), w
btfsc STATUS, Z
goto right_langid
wrong_langid
incf EP0_start,f
incf inner,f
movlw low String0_end ; compare EP0_start to the addr of
subwf EP0_start,w ; the last langid
btfss STATUS,C ; if EP0_start is equal or lager,
goto check_langid ; we've checked all langid and didn't find it
clrf USB_dev_req ; clear USB_dev_req, since GET_descriptor is over
pagesel wrongstate
goto wrongstate
right_langid
movlw 6 ; number of strings we have per language + 1
subwf BufferData+wValue,w
btfss STATUS,C
goto right_string
clrf USB_dev_req
pagesel wrongstate
goto wrongstate
right_string
rlf BufferData+wValue,w
movwf EP0_start+1
movf inner,w
pagesel string_index
call string_index
movwf EP0_start
incf EP0_start+1,f
movf inner,w
call string_index
movwf EP0_start+1
found_string
pagesel StringDescriptions
call StringDescriptions ; get length of the string descriptor
movwf EP0_end ; save length
subwf BufferData+wLength,w ; compare against requested length
movf BufferData+wLength,w ; if requested length is shorter..
btfss STATUS,C
movwf EP0_end ; save it.
movlw 8 ; each transfer may be 8 bytes long
movwf EP0_maxLength
incf EP0_end,f
pagesel copy_descriptor_to_EP0
call copy_descriptor_to_EP0
return
; ******************************************************************
; Stalls the EP0 endpoint to signal that the command was not recognised.
; This gets reset as the result of a Setup Transaction.
; ******************************************************************
wrongstate
global wrongstate
banksel UEP0
bsf UEP0,EP_STALL
bcf STATUS,RP0 ; back to page 2
return
; ******************************************************************
; Loads the device status byte into the EP0 In Buffer.
; ******************************************************************
Get_Device_Status ; starts in bank2
bsf STATUS,RP0
movf BD0IAL,w ; get buffer pointer
movwf FSR
bcf STATUS,RP0 ; bank 2
bsf STATUS,IRP ; select indirectly banks 2-3
movf USB_status_device,w ; get device status byte
movwf INDF
incf FSR,f
clrf INDF
bsf STATUS,RP0 ; bank 3
movlw 0x02
movwf BD0IBC ; set byte count to 2
movlw 0xC8
movwf BD0IST ; Data 1 packet, set owns bit
return
; ******************************************************************
; A do nothing response. Always returns a two byte record, with all
; bits zero.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -