Quelltext /~heha/ewa/Kram/igr-251008.zip/usb.i15

usbInit
;Oszillator: 48MHz vom INTOSC mittels 3x PLL)
	banksel	OSCCON		;Bank 1
	movlwf	0xFC,OSCCON
;Warte bis PLL stabil
_wosc	comf	OSCSTAT,w
	andlw	(1<<PLLRDY)|(1<<HFIOFR)|(1<<HFIOFS)
	brnz	_wosc
;„active clock tuning“ aktivieren, Voraussetzung für USB Full-Speed ohne Quarz
	banksel	ACTCON		; Bank 7
	movlwf	(1<<ACTSRC)|(1<<ACTEN),ACTCON		; source = USB
;USB initialisieren
	call	usbReset
;Busverbindung herstellen
	banksel	UCON		;Bank 29
	clrf	UCON
	bsf	UCON,USBEN	; enable USB module and wait until ready
ret	return

usbPoll
	banksel	UIR		;Bank 29
	btfsc	UIR,URSTIF	;USB-Reset?
	 goto	usbReset	; if so, reset the USB interface
	btfss	UIR,TRNIF
	 return			;nichts zu tun
	movfwf	USTAT,FSR1H	;Status retten
	bcf	UIR,TRNIF	;Interruptflag löschen
	banksel	0
	andlw	0x78		;Endpoint !=0 ?
	skpz
	 return
; Handles a control transfer on endpoint 0.
; args:		BSR=0, FSR1H=USTAT
; clobbers:	W, FSR1H
	btfsc	FSR1H,DIR
	 bra	usbE0I		;In-Transfer
; it's an OUT or SETUP transfer
	movfw	E0O_STA		; All non-PID bits are zero here because SETUP comes with DATA0
	xorlw	13<<2		; 13=PID_SETUP — is it a SETUP packet?
	brnz	usbE0O		;Out-Transfer
	call	handleSetup
	banksel	0
	movwf	SETUPDAT_CNT
	incfsz	WREG,w
	 bra	_setup_complete
	bra	_usb_ctrl_invalid

handleSetup
; Handles a SETUP control transfer on endpoint 0.
	assume	0
	clrf	E0O_STA		; let start with DATA1
	clrf	E0I_STA		; let start with DATA1
;Die Datenrichtung ist später noch wichtig, deshalb hier aufheben
	bcf	USB_STATE,7
	btfsc	bmRequestType,7	; is this device->host?
	 bsf	USB_STATE,7	; if so, this is a control read
	movfw	bmRequestType
	xorlw	0xC0
        brz	_ivd		;0xC0 = in, vendor, device
	decf	bRequest,w
	brz	_get_report	;1 = GET_REPORT
; is it Set Address?
	addlw	1-5		;5 = SET_ADDRESS
	brnz	_osdn5
	bsf	USB_STATE,5	;Adresse (später) setzen!
	retlw	0

_osdn5	decfsz	WREG,w			;6 = GET_DESCRIPTOR
	 bra	_no_usb_get_descriptor
; Handles a Get Descriptor request.
; check descriptor type
	decfsz	wValueH,w	;1 = Device-Deskriptor
	 bra	_isdn1
	movlwf2	DEVICE_DESC,FSR0
	retlw	18
_isdn1	decfsz	WREG,w		;2 = Config-Deskriptor
	 bra	_isdn2
	movlwf2	CONFIG_DESC,FSR0
	retlw	CONFIG_DESC_LEN	; length includes all subordinate descriptors
_isdn2	decfsz	WREG,w		;3 = String-Deskriptor
	 bra	_isdn3
	movlw	wValueL
	sublw	STRING_DESC_N	;w = wValueL - 6
	skpb
	 retlw	-1		;Falscher Index
	movlwf2	STRING_DESC,FSR0
	incf	wValueL,f
	bra	_sdf
_sdl	moviw	FSR0
	addwf	FSR0L,f
	skpnc
	 incf	FSR0H,f
_sdf	loop	wValueL,_sdl
	moviw	FSR0
	return
_isdn3	addlw	3-15		;15 = BOS-Deskriptor
	skpz
	 retlw	-1
	movlwf2	BOS_DESC,FSR0
	retlw	BOS_DESC_LEN

_no_usb_get_descriptor
; is it Get Configuration?
	decf	WREG,w
	decfsz	WREG,w			;8 = GET_CONFIG
	 bra	_no_usb_get_configuration

; Handles a Get Configuration request.
; BSR=0
; load a pointer to either a 0 or a 1 in ROM
	movlw	low CONST0
	btfsc	USB_STATE,0	;konfiguriert?
	 movlw	low CONST1
	movwf	FSR0L
	movlwf	high CONST0,FSR0H
	retlw	1
_no_usb_get_configuration
	decfsz	WREG,w			;9 = SET_CONFIG oder SET_REPORT
	 retlw	-1
	movfw	bmRequestType
	brnz	_set_report
; Handles a Set Configuration request.
; BSR=0
	movfwf	wValueL,USB_STATE	; should be 0 or 1
; Initializes the buffers for the CDC endpoints (1 OUT, 1 IN, and 2 IN).
; clobbers:	W, BSR=0
	movlwf	1<<DTS|1<<DTSEN,E1I_STA	; USB NAK and toggle bit set: Send first packet as DATA0
	retlw	0

_get_report
	movfw	bmRequestType
	skpnz
	 retlw	-1
	movlwf2	report,FSR0
	retlw	4

_set_report
	movfw	wValueL		;Report-ID
	brz	_prep_report0
	xorlw	99		;Magische Report-ID 99 (dezimal)?
	skpz
	 retlw	-1		;nein, Fehler (STALL)
	banksel	PCON		;Bank1
	bsf	PCON,NOT_POR	;Kein Power-On-Reset
	bcf	PCON,NOT_RMCLR	;Reset-Ursache !MCLR vorgaukeln
	reset			;Reset ausführen: Zum Urlader
_prep_report0
	movlwf2	report,FSR0
	retlw	4

_ivd	;In Vendor Device
	decfsz	bRequest,w
         bra	_ivdn1
        movlwf2	URL_DESC,FSR0
        retlw	URL_DESC_LEN
_ivdn1
	decfsz	WREG,w
         retlw	-1
        movlwf2	MSOS20_DESC,FSR0
        retlw	MSOS20_DESC_LEN

_setup_complete
	movfwf2	FSR0,SETUPDAT_PTR
; If requested length is shorter, transfer less than descriptor size
	tstf	wLengthH
	brnz	_sc		; more than 255 bytes requested (Windows 7: 0x109)
	movfw	SETUPDAT_CNT
	subwf	wLengthL,w	; W = wLengthL - SETUPDAT_CNT (headroom)
	skpnb			; if W >= 0, no need to adjust
	 addwf	SETUPDAT_CNT,f	; SETUPDAT_CNT += wLengthL - SETUPDAT_CNT
_sc
	banksel	UCON
	bcf	UCON,PKTDIS		; reenable packet processing
	banksel	0
	btfss	bmRequestType,7
	 bra	_cwrite
; this is a control read; prepare the IN endpoint for the data stage
; and the OUT endpoint for the status stage
	call	ep0_send_in		; read data into IN buffer
_e0ExpectOut	
	movlw	1<<DTS|1<<DTSEN		; make OUT buffer ready for status stage
; value in W is used to specify the EP0 OUT flags
_armbfs	call	arm_e0o_w
; Send next packet to Endpoint 0 In, size already set to E0I_CNT
arm_e0i
	comf	E0I_STA,w	; toggle DTS
	andlw	1<<DTS
	iorlw	1<<DTSEN
arm_e0i_w			; W specifies STAT flags
	movwf	E0I_STA
	bsf	E0I_STA,UOWN
	return
; this is a control write: prepare the IN endpoint for the status stage
; and the OUT endpoint for the next SETUP transaction
_cwrite	bcf	E0I_STA,UOWN	; ensure we have ownership of the buffer
	clrf	E0I_CNT	; we'll be sending a zero-length packet
	tstf	SETUPDAT_CNT
	brnz	_e0ExpectOut
	movlw	1<<DTSEN|1<<BSTALL	; make OUT buffer ready for next SETUP packet
	bra	_armbfs			; arm OUT and IN buffers

; Finishes a rejected SETUP transaction: the endpoints are stalled
_usb_ctrl_invalid
	banksel	UCON
	bcf	UCON,PKTDIS	; reenable packet processing
	banksel	0
	movlw	1<<DTSEN|1<<BSTALL
	call	arm_e0i_w
arm_ep0_out_stall	;for next SETUP
	movlw	1<<DTSEN|1<<BSTALL
	bra	arm_e0o_w

;Wenn EP0-IN-Transfer beendet:
;* Control Read: Weitere Deskriptordaten senden
;* Control Write: Acknowledge-Paket war erfolgreich, ggf. USB-Adresse setzen
usbE0I	btfss	USB_STATE,7	; is this a control read or write?
	 bra	_check_for_pending_address
; fetch more data and re-arm the IN endpoint
	call	ep0_send_in
	bra	arm_e0i			; arm the IN buffer
	
; if this is the status stage of a Set Address request, assign the address here.
; The OUT buffer has already been armed for the next SETUP.
_check_for_pending_address
	btfss	USB_STATE,5	;Adresse setzen?
	 return
	bcf	USB_STATE,5	;passiert jetzt
	movfw	wValueL		;Endpoint-Puffer ist noch mit SETUP-Daten gefüllt
	banksel	UADDR
	movwf	UADDR
	return

;Wenn EP0-OUT-Transfer beendet:
;* Control Read: Acknowledge-Paket
;* Control Write: (Weiteres) Datenpaket
usbE0O	btfsc	USB_STATE,7
	 bra	_e0oe
	tstf	SETUPDAT_CNT
	brz	_e0oe
	movfwf2	SETUPDAT_PTR,FSR0
	movlwf2	E0_BUF,FSR1
_e0oc	tstf	E0O_CNT
	brz	_e0od
	decf	E0O_CNT,f
	moviw	FSR1++		;EP0-Daten
	movwi	FSR0++		;in RAM kopieren
	loop	SETUPDAT_CNT,_e0oc
_e0od	movfwf2	FSR0,SETUPDAT_PTR
_e0oe	comf	E0O_STA,w	;DTS kippen
	andlw	1<<DTS
	iorlw	1<<DTSEN
arm_e0o_w			; W specifies STAT flags
	movwf	E0O_STA
	movlwf	1<<E0_SSH,E0O_CNT	; reset the buffer count
	bsf	E0O_STA,UOWN	; arm the OUT endpoint
	return

; Reads descriptor data from SETUPDAT_PTR, copies it to the EP0 IN buffer,
; and decrements SETUPDAT_CNT.
; Cannot simply point EP0_ADDR to flash as it is not accessible by USB SIE
; args:		BSR=0
; returns:	SETUPDAT_PTR advanced
;		SETUPDAT_CNT decremented
; clobbers:	W, FSR0, FSR1
ep0_send_in
	clrf	E0I_CNT	; initialize transfer length to 0
	tstf	SETUPDAT_CNT	; do nothing if there are 0 bytes to send
	skpnz
	 return
	movfwf2	SETUPDAT_PTR,FSR0	; set up source pointer
	movlwf2	E0_BUF,FSR1
; byte copy loop
_bcopy	btfsc	E0I_CNT,E0_SSH	; 8 Bytes full?
	 bra	_bcdone
	moviw	FSR0++
	movwi	FSR1++
	incf	E0I_CNT,f	; increase number of bytes copied
	loop	SETUPDAT_CNT,_bcopy
; write back the updated source pointer
_bcdone	movfwf2	FSR0,SETUPDAT_PTR
	return

;WebUSB-Transmitpuffer EP1IN absenden
;PE:	E1ISTA.UOWN gelöscht
;	EP1IN-Puffer gefüllt (mit 4..8 Byte)
;	E1I_CNT = Füllstand
;VR:	W,BSR=0
e1i_tx
	banksel	0
	comf	E1I_STA,w	;DataToggle
	andlw	1<<DTS
	iorlw	1<<DTSEN	;0↕001000
	movwf	E1I_STA
	bsf	E1I_STA,UOWN	;Puffer an SIE übergeben
	return

; Initializes the USB system and resets all associated registers.
; clobbers:	W,BSR=0,FSR0,FSR1L
usbReset
; clear USB registers
	banksel	UIR		; Bank 29
	clrf	UIR
; set configuration
	movlwf	(1<<UPUEN)|(1<<FSEN),UCFG	; enable pullups, full speed, no ping-pong buffering
	;movlwf	(1<<TRNIE)|(1<<URSTIE),UIE	; TODO: Need interrupts for CPU wakeup later
; clear all BDT entries, variables, and buffers
	clrf	FSR0H
	movlwf	0x20,FSR0L	; BDT starts at 0x2000 aka 0x20, clear all Bank0 variables except RxBuf
	movwf	CL		; use 0x20 as loop count
	clrw
_ramclr	movwi	FSR0++
	loop	CL,_ramclr
; reset ping-pong buffers and address
	banksel	UCON		; Bank 29: All about USB
	bsf	UCON,PPBRST
	clrf	UADDR
	bcf	UCON,PKTDIS	; enable packet processing
	bcf	UCON,PPBRST	; clear ping-pong buffer reset flag
; flush pending transactions
_tflush	btfss	UIR,TRNIF
	 bra	_initep
	bcf	UIR,TRNIF
	call	ret		; need at least 6 cycles before checking TRNIF again
	bra	_tflush

; initialize endpoints:
; 0 für control
; 1 in für WebUSB (vergleichbar mit HID)
_initep	movlwf	1<<EPHSHK|1<<EPOUTEN|1<<EPINEN,UEP0
	movlwf	1<<EPHSHK|1<<EPCONDIS|1<<EPOUTEN|1<<EPINEN,UEP1
; initialize endpoint buffers and counts
	banksel	0
	movlwf2	LIN_E0_BUF,E0O_ADR	; set endpoint 0 address low
	movlwf2	LIN_E0_BUF,E0I_ADR
	movlwf2	LIN_E1I_BUF,E1I_ADR	; set endpoint 1 IN address low
	goto	arm_ep0_out_stall

Vorgefundene Kodierung: UTF-80