;******************
;* HID und WebUSB *
;******************
;Auch wenn sich das Datenblatt darüber auslässt, dass sich die
;„Buffer Descriptor Table“ ab der linearen Adresse 0x2000 befindet,
;befindet sie sich genauso im Bank 0 und belegt diese zwangsweise:
;Wenn man USB benutzt, dann geht effektiv die Bank 0 dafür drauf.
;So passt alles in Bank 0:
E0_SSH equ 4 ; endpoint 0 buffer size = 16
E1I_SSH equ 4 ; endpoint 1 IN (HID interrupt) buffer size = 16
E2I_SSH equ 4 ; endpoint 2 IN (WebUSB interrupt) buffer size = 16
;Exy_STA bits (in Bank 0)
BSTALL equ 2
DTSEN equ 3
DTS equ 6
UOWN equ 7
;list of Bank0 RAM variables, starting with BDT
cblock 0x20 ;Bank 0 (geradeso voll)
E0O_STA
E0O_CNT
E0O_ADR:2
E0I_STA
E0I_CNT
E0I_ADR:2
E1O_STA ; unused
E1O_CNT ; unused
E1O_ADR:2 ; unused
E1I_STA
E1I_CNT
E1I_ADR:2
E2O_STA ; unused
E2O_CNT ; unused
E2O_ADR:2 ; unused
E2I_STA
E2I_CNT
E2I_ADR:2
; Normalerweise sind die Variablen E1O_xxx und E2O_xxx frei.
; Aber vielleicht will ja jemand später noch OUT-Endpoints dazufummeln.
USB_STATE ; some flags, see below
SETUPDAT_CNT ; remaining bytes to be sent
SETUPDAT_PTR:2 ; pointer to descriptor to be sent
free:4
E0_BUF:1<<E0_SSH ;@0x40 shared buffer for EP0 Setup, Out, and In transfer
E1I_BUF:1<<E1I_SSH ;@0x50
E2I_BUF:1<<E1I_SSH ;@0x60
;Dadurch passt alles in die Bank 0, und die HID- und Interruptdaten können in einem Stück gesendet werden!
endc
bmRequestType equ E0_BUF+0
bRequest equ E0_BUF+1
wValueL equ E0_BUF+2
wValueH equ E0_BUF+3
wIndexL equ E0_BUF+4
wIndexH equ E0_BUF+5
wLengthL equ E0_BUF+6
wLengthH equ E0_BUF+7
LIN_E0_BUF equ E0_BUF+0x1FE0 ;0x2020 .. 0x202F
LIN_E1I_BUF equ E1I_BUF+0x1FE0 ;0x2030 .. 0x203F
LIN_E2I_BUF equ E1I_BUF+0x1FE0 ;0x2040 .. 0x204F
; USB_STATE bit flags
IS_CONTROL_READ equ 7 ; current EP0 transaction is a control read
DECOMP equ 1 ; for descriptor decompression
CONFIGURED equ 0 ; the device is configured
usbPoll
banksel UIR ; Bank 29
btfsc UIR,URSTIF ; reset?
goto usbReset ; if so, reset the USB iface
; service transactions
btfss UIR,TRNIF
return
movfwf USTAT,FSR1H ; store the status (endpoint number + direction)
bcf UIR,TRNIF ; clear flag and advance USTAT fifo
banksel E0O_STA ; Bank 0
andlw 0x78 ; endpoint number !=0 ?
skpz
retlw 0 ; if not endpoint 0, trash it
; Handles a control transfer on endpoint 0.
; args: BSR=0, FSR1H=USTAT
; clobbers: W, FSR1H
btfsc FSR1H,DIR ; is it an IN transfer or an OUT/SETUP?
bra _usb_ctrl_in
; 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 arm_e0o ; if not, it's a DATA or STATUS OUT, ignore data and rearm buffer
;=============================
;= EP0 SETUP packet received =
;=============================
; Handles a SETUP control transfer on endpoint 0.
; BSR=0
assume 0
clrf E0O_STA ; let start with DATA1
clrf E0I_STA ; let start with DATA1
clrf SETUPDAT_CNT ; No data phase as standard
bcf USB_STATE,IS_CONTROL_READ
; get bmRequestType, but don't bother checking whether it's standard/class/vendor...
; the CDC and standard requests we'll receive have distinct bRequest numbers
btfsc bmRequestType,7 ; is this device->host?
bsf USB_STATE,IS_CONTROL_READ ; if so, this is a control read
call onSetup
incfsz WREG,w
bra _ans
; Finishes a rejected SETUP transaction: the endpoints are stalled
;_usb_ctrl_invalid
banksel UCON
bcf UCON,PKTDIS ; reenable packet processing
banksel E0I_STA
movlw 1<<DTSEN|1<<BSTALL
call arm_e0i_w
e0o_stall ;for next SETUP
movlw 1<<DTSEN|1<<BSTALL
bra arm_e0o_w
; Prepare reception of next Endpoint 0 Out Data (or Setup) packet
arm_e0o
comf E0O_STA,w ; toggle DTS
andlw 1<<DTS
iorlw 1<<DTSEN
arm_e0o_w ; W specifies STAT flags
;assume E0_BUF
movwf E0O_STA
movlwf 1<<E0_SSH,E0O_CNT ; reset the buffer count
bsf E0O_STA,UOWN ; arm the OUT endpoint
return
_ans decf WREG,w
banksel SETUPDAT_CNT
movwf SETUPDAT_CNT
; If requested length is shorter, transfer less than descriptor size
tstf wLengthH
brnz _sc1 ; more than 255 bytes requested (Windows 7: 0x109)
subwf wLengthL,w
brc _sc1 ; if W <= f, no need to adjust
movfwf wLengthL,SETUPDAT_CNT
_sc1 movfwf2 FSR0,SETUPDAT_PTR
; Finishes a successful SETUP transaction.
; SETUPDAT_CNT contains transfer length.
banksel UCON
bcf UCON,PKTDIS ; reenable packet processing
banksel USB_STATE
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
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
movlw 1<<DTSEN|1<<BSTALL ; make OUT buffer ready for next SETUP packet
bra _armbfs ; arm OUT and IN buffers
;========================
;= EP0 Setup Dispatcher =
;========================
; Must return W = AnswerLength and FSR0 = AnswerPointer for queries (RAM or Flash)
; Or W == -1 for error. Caller will then handle data output.
onSetup
assume 0
movlwf2 ROM001,FSR0 ; zur Rückgabe von 0, 0-0 oder 0-1 vorbereiten
movfw bmRequestType
bz _bm00
xorlw 0x01
bz _bm01
xorlw 0x21^0x01
bz _bm21
xorlw 0x80^0x21
bz _bm80
xorlw 0x81^0x80
bz _bm81
xorlw 0xA1^0x81
bz _bmA1
xorlw 0xC0^0xA1
bz _bmC0
retlw -1
_bm00 ;OUT, STD, DEVICE
decfsz bRequest,w
retlw 0 ;1 = Clear Feature (ignorieren)
addlw -2
skpnz
retlw 0 ;3 = Set Feature (ignorieren)
addlw -2
skpnz
retlw 0 ;5 = SET_ADDRESS (passiert später)
addlw -4
skpz ;9 = SET_CONFIG?
retlw -1
; Handles a Set Configuration request.
movfw wValueL ; should be 0 or 1
movwf USB_STATE
; Initializes the buffers for the CDC endpoints (1 OUT, 1 IN, and 2 IN).
; clobbers: W, BSR=0
movlw 1<<DTSEN ; expect DATA0 first
;call arm_e1o_w
movwf E1I_STA ; USB NAK and toggle bit set: Send first packet as DATA0
;bra _setup_complete
retlw 0
_bm01 ;OUT, STD, IFACE[wIndexL]
movfw bRequest
addlw -11 ;11 = Set Iface
skpz
retlw -1
retlw 0 ;ignorieren und OK
_bm21 ;OUT, CLASS, IFACE[wIndexL]
movfw bRequest
addlw -9 ;9 = Set Report
skpz
retlw -1
movfw wValueL
goto onEp0SetReport
_bm80 ;IN, STD, DEVICE
movfw bRequest ;0 = Get Status (BusPower)
skpnz
retlw 2 ;2 Nullbytes liefern
xorlw 6 ;6 = GET_DESCRIPTOR
brz getDesc
xorlw 8^6
skpz ;8 = Get Config
retlw -1
addfsr FSR0,1
btfsc USB_STATE,CONFIGURED ; bit 0
addfsr FSR0,1
retlw 1 ;0 oder 1 liefern
_bm81 ;IN, STD, IFACE[wIndexL]
movfw bRequest ;0 = Get Status
skpnz
retlw 2 ;2 Nullbytes liefern
xorlw 10
skpnz
retlw 1 ;10 = Get Iface: 1 Nullbyte liefern
xorlw 6^10
skpz
retlw -1
movfw wValueH
xorlw 0x22 ; HID?
skpz
retlw -1
movlwf2 HidRepDesc,FSR0
retlw HidRepDescLen
_bmA1 ;IN, CLASS, IFACE[wIndexL]
decfsz bRequest,w
retlw -1
movfw wValueL
goto onEp0GetReport
_bmC0 ;IN, VENDOR, DEVICE
decfsz bRequest,w
bra _nvr01
movlwf2 LandingPageDesc,FSR0
bra retind ;Länge aus Deskriptor
_nvr01
decfsz WREG,w
retlw -1
movlwf2 MsOs20Desc,FSR0
retlw MsOs20DescLen
;=================================
;= Device-Deskriptoren festlegen =
;=================================
;PE: wValueH = Deskriptortyp
;PA: FSR0 = Zeiger auf (gepackten) Deskriptor
; W = Länge in (ausgepackten) Bytes
; W = -1 bei Fehler (EP0STALL)
getDesc:
assume 0
; Handles a Get Descriptor request.
; check descriptor type
decfsz wValueH,w ;1 = DESC_DEVICE
bra _ndesc01
movlwf2 DeviceDesc,FSR0
bra retind
_ndesc01
decfsz WREG,w ;2 = DESC_CONFIG
bra _ndesc02
movlwf2 ConfigDesc,FSR0
retlw ConfigDescLen ; length includes all subordinate descriptors
_ndesc02
decfsz WREG,w ;3 = String-Deskriptor
bra _ndesc03
movlwf2 StringDesc,FSR0
incf wValueL,f
bra _d3f
_d3l movfw INDF0
lsrf WREG,w ;halbieren weil String-Deskriptoren gepackt abgelegt sind
addwf FSR0L,f
skpnc
incf FSR0H,f
_d3f loop wValueL,_d3l
retind movfw INDF0 ;Länge aus Deskriptor
return
_ndesc03
addlw 3-0x0F ; BOS?
skpz
retlw -1 ; Kein gültiger Deskriptor
movlwf2 BosDesc,FSR0
retlw BosDescLen
; Handles an IN control transfer on endpoint 0.
; Can be (descriptor) data or an acknowledge zero-length packet
; BSR=0
_usb_ctrl_in
btfss USB_STATE,IS_CONTROL_READ ; 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
movfw bRequest
xorlw 5
skpz
return
; read the address out of the setup packed in the OUT buffer
movfw wValueL
banksel UADDR
movwf UADDR
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
movlwf E0_BUF,FSR1L ; Here: Banked address (not a problem), set up destination pointer
clrf FSR1H
clrdc
btfsc USB_STATE,DECOMP
setdc ; copy DECOMP flag to STATUS.DC (free inside loop and non-banked)
; byte copy loop with decompression, STATUS.C is free too (for another compression)
_bcopy: btfsc E0I_CNT,E0_SSH ; 16 Bytes full?
bra _bcdone
btfss FSR0H,7 ;Flash?
bra _bcram ;nein, vom RAM (Byte) lesen
banksel PMCON1
brdc _bchi
clrf PMCON1
movfwf2 FSR0,PMADR
bsf PMCON1,RD ;vom Flash (14 bit) lesen
nop
nop
movfw PMDATH
xorlw 0x34 ; unpacked byte if == 0x34xx
skpz
setdc ; packed word if != 0x34xx
movfw PMDATL
addfsr FSR0,1
bra _bclo
_bchi: clrdc
movfw PMDATH ; For next byte, deliver high byte (Bits 6 and 7 are zero)
_bclo: banksel USB_STATE
bra _bcput
_bcram: moviw FSR0++
_bcput: movwi FSR1++
incf E0I_CNT,f ; increase number of bytes in transmit buffer
loop SETUPDAT_CNT,_bcopy ; decrement number of bytes remaining
; write back the updated source pointer
_bcdone bcf USB_STATE,DECOMP
skpndc
bsf USB_STATE,DECOMP ;copy STATUS.DC to USB_STATE.DECOMP
movfwf2 FSR0,SETUPDAT_PTR
return
if 0
;Send data chunk to host. Note that a short packet ends a transfer unit (= chunk for ReadFile).
;In case the last packet is full, a zero-length packet must be appended to mark the end of chunk.
;args: W=Bytes (0..64)
; EP1IN buffer filled with data
;clobbers: W,bank=0
usbTx banksel 0
_u1 btfsc E1I_STA,UOWN ; spinloop until previous buffer is read by USB host
bra _u1 ; (Bug: May hang if USB connection is somehow lost in between)
movwf E1I_CNT ; put transfer size
comf E1I_STA,w ; toggle DTS
andlw 1<<DTS ; clear all other bits (STALL too)
iorlw 1<<DTSEN ; 0↕001000 = use toggle bit
movwf E1I_STA
bsf E1I_STA,UOWN ; give to SIE
return
endif
;Stellt EP0 scharf und wartet auf OUT-Paket
usbEp0Recv
banksel UCON
bcf UCON,PKTDIS ; reenable packet processing
banksel 0
call arm_e0o
_busy banksel UIR ; Bank 29
btfsc UIR,URSTIF ; reset?
goto err ;Böse: Stack aufräumen lassen, USB-Reset später abarbeiten
; service transactions
btfss UIR,TRNIF
goto _busy
bcf UIR,TRNIF
banksel E0O_STA ; Bank 0
btfsc E0O_STA,UOWN ;Daten vorhanden?
goto _busy ;nein, anderes Ereignis, hier ignorieren
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?
brz err ;ja, aber es muss hier ein OUT-Paket sein!
clrc
return ;okay
err setc
return ;nicht okay
usbInit
; Configure the oscillator (48MHz from INTOSC using 3x PLL)
banksel OSCCON ; bank 1
movlwf 0xFC,OSCCON
; Wait for the oscillator and PLL to stabilize
_wosc comf OSCSTAT,w
andlw (1<<PLLRDY)|(1<<HFIOFR)|(1<<HFIOFS)
brnz _wosc
; Enable active clock tuning
banksel ACTCON ; Bank 7
movlwf (1<<ACTSRC)|(1<<ACTEN),ACTCON ; source = USB
; Initialize USB
call usbReset
; Attach to the bus (could be a subroutine, but inlining it saves 2 instructions)
banksel UCON ; Bank 29
clrf UCON ; reset UCON
bsf UCON,USBEN ; enable USB module and wait until ready
ret 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
call ZeroMemory ; use 0x20 as loop count
; 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 for control
; 1 for HID interrupt
; 2 for WebUSB interrupt
_initep movlwf 1<<EPHSHK|1<<EPOUTEN|1<<EPINEN,UEP0
movlwf 1<<EPHSHK|1<<EPCONDIS|1<<EPINEN,UEP1
movlwf 1<<EPHSHK|1<<EPCONDIS|1<<EPINEN,UEP2
; initialize endpoint buffers and counts
banksel E0O_ADR ; Bank 0
movlwf low LIN_E0_BUF, E0O_ADR ; set endpoint 0 address low
movwf E0I_ADR
movlwf low LIN_E1I_BUF,E1I_ADR ; set endpoint 1 IN address low
movlwf low LIN_E2I_BUF,E2I_ADR ; set endpoint 1 IN address low
movlwf high LIN_E0_BUF,E0O_ADR+1 ; set all ADRH values to 0x20
movwf E0I_ADR+1
movwf E1I_ADR+1
movwf E2I_ADR+1
goto e0o_stall
; Descriptors
;########################################################################
;# Die Deskriptoren sind in die 14-Bit-Flash-Wörter derart gepackt, #
;# dass WORD-Werte <0x4000 direkt im Flash abgelegt werden #
;# und Byte-Werte mit dem High-Byte 0x34 (für Opcode retlw aus dt) #
;# Der Spareffekt ist erheblich, weil WinUSB/WebUSB viel Platz braucht. #
;# Größenberechnungen funktionieren so nicht mehr. #
;########################################################################
dt2 macro x,y ; für Bytes, wenn das 2. Byte < 0x40 und nicht 0x34 ist
dw y<<8|x
endm
; Es gibt folgende HID-Deskriptoren:
;Nr.1 Report-ID 8 (nur lesen: Interrupt)
; Zustand Rauchmelder 1
; Zustand Testalarm 1
; Grenzwertalarm 4
; A/D-Wert Gassensor 16
; A/D-Wert Chiptemperatur 16
; Wert vom Pyrosensor 16
; Werte von DS18B20 4×16
;Nr.2 Report-ID 8 (schreiben/lesen: Feature)
; Testalarm 1
; Sprung zum Urlader 1 (write-only)
; Kontroll-LED 1
; Grenzwert Gassensor 16
; Grenzwert Chiptemp. 16
; Grenzwert Pyrosensor 16
; Grenzwerte DS18B20 4×16
;Nr.3 Report-ID 8 (schreiben/lesen: Feature)
; Cookies 15×8
;Nr.4 Report-ID 8 (schreiben/lesen: Feature)
; Index DS18B20 2 (8)
; ID der DS18B20 64 (nur lesen)
; Die Größe ist auf 16 Bytes beschränkt.
; Die gleichen „Deskriptoren“ werden auch für WebUSB verwendet.
; Eine Umrechnung in °C muss das Anwendungsprogramm machen.
HidRepDesc
dt2 0x06,0x3F
dt 0xFF ;G Usage Page: Unknown (0xFF3F)
dt2 0x09,1 ;L Usage: 1
dt2 0xA1,1 ;M Collection
dt2 0x75,8 ;G Report Size
dt2 0x95,15 ;G Report Count
dt2 0x15,0 ;G Logical Minimum
dt 0x26;,255,0 ;G Logical Maximum
dt2 255,0
;Nr.1
dt2 0x85,1 ;M Report ID (1)
dt2 0x09,1 ;L Usage: 1 (Byte-Array)
dt2 0x81,2 ;M Input: Variable
;Nr.2
dt2 0x85,2 ;M Report ID (2)
dt2 0x09,2 ;L Usage: 2 (Byte-Array)
dt2 0xB1,2 ;M Feature: Variable
;Nr.3
dt2 0x85,3 ;M Report ID (3)
dt2 0x09,3 ;L Usage: 3 (Byte-Array)
dt2 0xB1,2 ;M Feature: Variable
;Nr.4
dt2 0x85,4 ;M Report ID (3)
dt2 0x09,4 ;L Usage: 3 (Byte-Array)
dt2 0x95,9 ;G Report Count (hier nur 9 Bytes, Gesamtlänge 10)
dt2 0xB1,2 ;M Feature: Variable
dt 0xC0 ;M End Collection
HidRepDescLen equ (16+6+6+6+9)
DeviceDesc
dt2 18,1 ; bLength ; bDescriptorType
dw 0x0210 ; bcdUSB (USB 2.1)
dt2 0,0 ; bDeviceClass ; bDeviceSubclass
dt2 0,1<<E0_SSH ; bDeviceProtocol ; bMaxPacketSize0 (16 bytes)
dw 0x16C0 ; idVendor (Voti)
dw 0x27D9 ; idProduct (HID no keyboard/mouse/joystick)
dw 0x0300 ; bcdDevice
dt2 1,2 ; iVendor ; iProduct
dt2 3,1 ; iSerialNo ; bNumConfig
ConfigDesc
dt2 9,2 ; bLength ; bDescType
dw ConfigDescLen ; wTotalLength
dt2 2,1 ; bNumIfaces ; bConfigValue
dt 0 ; iConfig
dt2 0x80,50 ; bmAttributes (BusPwr) ; bMaxPower (100 mA)
;iface 0
dt2 9,4 ; bLength ; bDescType (IFACE)
ROM001 ; Three adjanced addresses containing [0,0,1]
dt 0 ; bIfaceNumber
dt 0 ; bAlternateSetting
dt 1 ; bNumEndpoints
dt2 3,0 ; bIfaceClass (HID) ; bIfaceSubclass
dt2 0,4 ; bIfaceProtocol ; iIface
;HID descr.
dt2 9,0x21 ; bLength ; bDescType
dw 0x0110 ; bcdHID
dt2 0,1 ; bCountryCode ; bNumDescs
dt 0x22 ; bDescType Report
dw HidRepDescLen ; wDescLength
;endpoint
dt2 7,5 ; bLength ; bDescType (ENDPOINT)
dt2 0x81,3 ; bEndpointAddr (1 IN) ; bmAttributes (interrupt)
dw 1<<E1I_SSH ; wMaxPacketSize (16)
dt 250 ; bInterval (250 ms)
;iface 1
dt2 9,4 ; bLength ; bDescType (INTERFACE)
dt2 1,0 ; bIfaceNumber ; bAlternateSetting
dt 1 ; bNumEndpoints
dt2 0xFF,0 ; bIfaceClass (vendor) ; bIfaceSubclass
dt2 0,5 ; bIfaceProtocol ; iIface
;endpoint
dt2 7,5 ; bLength ; bDescType (ENDPOINT)
dt2 0x82,3 ; bEndpointAddr (2 IN) ; bmAttributes (interrupt)
dw 1<<E2I_SSH ; wMaxPacketSize (16)
dt 250 ; bInterval (250 ms)
ConfigDescLen equ (9+9+9+7+9+7)
BosDesc
dt2 5,0x0F ; Length ; Binary Object Store descriptor
dw 57 ; Total length
dt 2 ; Number of device capabilities
; WebUSB Platform Capability descriptor (bVendorCode == 0x01).
dt2 0x18,0x10 ; Length ; Device Capability descriptor
dt2 0x05,0x00 ; Platform Capability descriptor ; Reserved
dt 0x38,0xB6,0x08,0x34,0xA9,0x09,0xA0,0x47,0x8B,0xFD,0xA0,0x76,0x88,0x15,0xB6,0x65 ; WebUSB GUID
dw 0x0100 ; Version 1.0
dt2 0x01,0x01 ; Vendor request code (-> bRequest) ; Landing page (-> wValueL)
; Microsoft OS 2.0 Platform Capability Descriptor (MS_VendorCode == 0x02)
dt2 0x1C,0x10 ; Length ; Device Capability descriptor
dt2 0x05,0x00 ; Platform Capability descriptor ; Reserved
dt 0xDF,0x60,0xDD,0xD8,0x89,0x45,0xC7,0x4C,0x9C,0xD2,0x65,0x9D,0x9E,0x64,0x8A,0x9F ; MS OS 2.0 GUID
dw 0,0x0603 ; Windows version
dw 0x00B2 ; Descriptor set length
dt2 0x02,0x00 ; Vendor request code ; Alternate enumeration code
BosDescLen equ 57
MsOs20Desc
dw 10 ; Descriptor size (10 bytes)
dw 0 ; MS OS 2.0 descriptor set header
dw 0,0x0603 ; Windows version (8.1) (0x06030000)
dw 0x00B2 ; Size, MS OS 2.0 descriptor set
; Microsoft OS 2.0 configuration subset header
dw 8 ; Descriptor size (8 bytes)
dw 1 ; MS OS 2.0 configuration subset header
dw 0 ; bConfigurationValue
dw 0x00A8 ; Size, MS OS 2.0 configuration subset
; Microsoft OS 2.0 function subset header
dw 8 ; Descriptor size (8 bytes)
dw 2 ; MS OS 2.0 function subset header
dw 1 ; iface number
dw 0x00A0 ; Size, MS OS 2.0 function subset
; Microsoft OS 2.0 compatible ID descriptor (table 13)
dw 20 ; wLength
dw 3 ; MS_OS_20_FEATURE_COMPATIBLE_ID
dt "WINUSB" ; compatID[8]
dw 0
dw 0,0,0,0 ; subcompatID[8];
;CUSTOM_PROPERTY
dw 4+21+1+40<<1 ; wLength:
dw 4 ; wDescType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
dw 7 ; wPropertyDataType: REG_MULTI_SZ (Table 15)
dw 21<<1 ; wPropertyNameLength:
dw 'D','e','v','i','c','e','I','n','t','e','r','f','a','c','e','G','U','I','D','s',0 ; bPropertyName
dw 40<<1 ; wPropertyDataLength
dw '{','9','7','5','F','4','4','D','9','-','0','D','0','8','-','4','3','F','D','-','8','B','3','E','-'
dw '1','2','7','C','A','8','A','F','F','F','9','D','}',0,0 ; bPropertyData
MsOs20DescLen equ (23+66<<1)
LandingPageDesc
dw 0x032E ; strlen(landingPageUrl)+3 ; descriptorType(String)
dt 0x01 ; landingPageScheme(https://)
dt "www.tu-chemnitz.de/~heha/ewa/Ofen/rauch.htm"
;Der String-Deskriptor darf laut Programmlogik nur aus "dw" bestehen, chinesisch geht dann nicht, Unicodes < 0x4000
StringDesc ; High-Teil = DTYPE_String, Low-Teil = (String-Länge+1)*2
dw 0x0304
dw 0x0407 ; (0) Länge 1: deutsch
dw 0x0322
dw 'T','U',' ','C','h','e','m','n','i','t','z',',',' ','E','W','A' ; (1) Länge 16
dw 0x0318
dw 'R','a','u','c','h','m','e','l','d','e','r' ; (2) Länge 11
dw 0x0330
dw 'h','e','h','a','@','h','r','z','.','t','u','-','c','h','e','m','n','i','t','z','.','d','e' ;(3) Länge 23
dw 0x0308
dw 'H','I','D' ; (4) Länge 3
dw 0x030E
dw 'W','e','b','U','S','B' ; (5) Länge 6
StringDescEnd
Detected encoding: UTF-8 | 0
|