;******************
;* 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 1 IN (WebUSB data) 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 ; At address 0x40, length 0x10, shared buffer for EP0 Setup, Out, and In transfer
E1I_BUF:1<<E1I_SSH ; At address 0x50, length 0x10, HID interrupt data
E12_BUF:1<<E1I_SSH ; At address 0x60, length 0x10, WebUSB interrupt data
;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
CONFIGURED equ 0 ; the device is configured
usbPoll
banksel UIR ; Bank 29
btfsc UIR,URSTIF ; reset?
goto usbReset ; if so, reset the USB interface
; 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 ?
skpnz
return
; 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 e0o_next ; 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
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
movfw bmRequestType
bz _bm00
xorlw 0x01^0x00
bz _bm01
xorlw 0x21^0x01
bz _bm21
bsf USB_STATE,IS_CONTROL_READ ; now it is device->host
xorlw 0x80^0x21
bz _bm80
xorlw 0x81^0x80
bz _bm81
xorlw 0xA1^0x81
bz _bmA1
xorlw 0xC0^0xA1
bz _bmC0
goto _setup_stall
assume 0
_bm00 ;OUT, STD, DEVICE
movfw bRequest
xorlw 0x01^0x00
bz _setup_ok
xorlw 0x03^0x01
bz _setup_ok
xorlw 0x05^0x03
bz _setup_ok
xorlw 0x09^0x05 ; set_configuration
bnz _setup_stall
movfw wValueL ; darf nur 0 oder 1 sein
addlw -2
bc _setup_stall
movfwf wValueL,USB_STATE
;TODO: Endpoints hier konfigurieren oder totlegen
movlw 1<<DTSEN ; expect DATA0 first
call arm_e1o_w
movlwf 1<<DTS|1<<DTSEN,E1I_STA ; USB NAK and toggle bit set: Send first packet as DATA0
movwf E2I_STA
goto _setup_ok
_bm01 ;OUT, STD, IFACE[wIndexL]
movfw bRequest
xorlw 0x11 ; Set Interface (ignorieren)
bz _setup_ok
goto _setup_stall
_bm21 ;OUT, CLASS, IFACE[wIndexL]
movfw bRequest
xorlw 9 ; Set Report
bnz _setup_stall
movfw wValueL ; Report-ID
goto onEp0SetReport
_bm80 ;IN, STD, DEVICE
movfw bRequest
bz _setup_zero2
xorlw 6 ; Get Descriptor?
bz _setup_getdesc
xorlw 8^6 ; Get Configuration?
bnz _setup_stall
movlwf2 ROM01,FSR0
btfsc USB_STATE,0
addfsr FSR0,1
movlw 1
goto _setup_answer_w
_bm81 ;IN, STD, IFACE[wIndexL]
movfw bRequest
bz _setup_zero2
xorlw 6 ; Get Descriptor?
bz _setup_gethidrepdesc
xorlw 10^6 ; Get AltSetting
bnz _setup_stall
movlwf2 ROM00,FSR0
movlw 1
goto _setup_answer_w ;1 Nullbyte als Antwort
_bmA1 ;IN, CLASS, IFACE[wIndexL]
movfw bRequest
xorlw 1
bnz _setup_stall
movfw wValueL
goto onEp0GetReport
_bmC0 ;IN, VENDOR, DEVICE
movfw bRequest
xorlw 1
bz _setup_getos20desc
xorlw 2^1
bnz _setup_stall
movlwf2 LandingPageDesc,FSR0
goto _setup_answer
_setup_getos20desc
movlwf2 MsOs20Desc,FSR0
movlw MsOs20DescEnd-MsOs20Desc
goto _setup_answer_w
_setup_zero2
movlwf2 ROM00,FSR0
movlw 2
goto _setup_answer_w
_setup_gethidrepdesc
movfw wValueH
xorlw 0x22 ; HID?
bnz _setup_stall
movlwf2 HidRepDesc,FSR0
movlw HidRepDescEnd-HidRepDesc
goto _setup_answer_w
_setup_getdesc ; „Get Descriptor“ behandeln: Davon gibt es viele!
decfsz wValueH,w ;1 = DeviceDesc
goto _no_devicedesc
movlwf2 DeviceDesc,FSR0 ;Zeiger laden
goto _setup_answer
_no_devicedesc
decfsz WREG,w ;2 = ConfigDesc
goto _no_configdesc
movlwf2 ConfigDesc,FSR0
movlw ConfigDescEnd-ConfigDesc ; length includes all subordinate descriptors
goto _setup_answer_w
_no_configdesc
decfsz WREG,w ;3 = StringDesc
goto _no_stringdesc
movlwf2 StringDesc,FSR0
movfw wValueL
bz _lsf
addlw -5
bc _setup_stall
_lsd
movfw INDF0 ; Längenbyte nach W
addwf FSR0L,f
skpnc
incf FSR0H,f
loop wValueL,_lsd
_lsf goto _setup_answer
_no_stringdesc
xorlw 15-3
bnz _setup_stall
movlwf2 BosDesc,FSR0
movlw BosDescEnd-BosDesc
goto _setup_answer_w
;Daten von FSR0 abschicken, Länge = erstes Byte des Deskriptors
_setup_answer
movfw INDF0
;Daten von FSR0 abschicken, Länge = w (stets <= 255)
_setup_answer_w
movwf SETUPDAT_CNT
; If requested length is shorter, transfer less than descriptor size
tstf wLengthH
brnz _setup_complete ; more than 255 bytes requested (Windows 7: 0x109)
subwf wLengthL,w
brc _setup_complete ; if W <= f, no need to adjust
movfw wLengthL
movwf SETUPDAT_CNT
_setup_complete
movfwf2 FSR0,SETUPDAT_PTR
; Finishes a successful SETUP transaction.
; SETUPDAT_CNT contains transfer length.
_setup_ok
banksel UCON
bcf UCON,PKTDIS ; reenable packet processing
banksel USB_STATE ; Bank 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
movlw 1<<DTS|1<<DTSEN ; make OUT buffer ready for status stage
; value in W is used to specify the EP0 OUT flags
_armbfs movwf E0O_STA
movlwf 1<<E0_SSH,E0O_CNT ; reset the buffer count
bsf E0O_STA,UOWN ; arm the OUT endpoint
; Send next packet to Endpoint 0 In, size already set to E0I_CNT
e0i_next
comf E0I_STA,w ; toggle DTS
andlw 1<<DTS
iorlw 1<<DTSEN
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
; Finishes a rejected SETUP transaction: the endpoints are stalled
_setup_stall
banksel UCON
bcf UCON,PKTDIS ; reenable packet processing
banksel E0I_STA
movlw 1<<DTSEN|1<<BSTALL
movwf E0I_STA
bsf E0I_STA,UOWN
e0o_stall ;for next SETUP
movlw 1<<DTSEN|1<<BSTALL
bra e0o_arm
; Prepare reception of next Endpoint 0 Out Data (or Setup) packet
e0o_next
comf E0O_STA,w ; toggle DTS
andlw 1<<DTS
iorlw 1<<DTSEN
e0o_arm ; 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
; Handles an IN control transfer on endpoint 0.
; Can be (descriptor) data or an acknowledge 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 e0i_next ; 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
; Handle possibly multiple-chunk EP0 IN transfer:
; Reads 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
movfwf SETUPDAT_PTR,FSR0 ; set up source pointer
movfwf SETUPDAT_PTR+1,FSR0+1
movlwf E0_BUF,FSR1L ; Here: Banked address (not a problem), set up destination pointer
clrf FSR1H ; Bank 0
; byte copy loop, from FSR0 to FSR1 length SETUPDAT_CNT but max. 16 bytes
_bcopy btfsc E0I_CNT,E0_SSH ; 16 Bytes full?
bra _bcdone
moviw FSR0++
movwi FSR1++
incf E0I_CNT,f ; increase number of bytes copied
decfsz SETUPDAT_CNT,f ; decrement number of bytes remaining
bra _bcopy
; write back the updated source pointer
_bcdone movfwf FSR0,SETUPDAT_PTR
movfwf FSR0+1,SETUPDAT_PTR+1
return
;Send data chunk to host.
;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
arm_e1o_w
;movwf E1O_STA
;movlwf 1<<E1O_SSH,E1O_CNT ; length = full size
;bsf E1O_STA,UOWN ; rearm OUT buffer
retlw 1<<DTS|1<<DTSEN ; 01001000
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
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 FSR1L ; use 0x20 as loop count
clrw
_ramclr movwi FSR0++
loop FSR1L,_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
nop
nop
nop
nop ; 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 2 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
dew macro x
de low(x),high(x)
endm
; Es gibt folgende HID-Deskriptoren:
;Nr.1 Report-ID 8 (nur lesen: Interrupt)
; Zustand Rauchmelder 1
; Zustand Testalarm 1
; 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
; 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
de 0x06
dew 65442 ;G Usage Page: Unknown
de 0x09,1 ;L Usage: 1
de 0xA1,1 ;M Collection
de 0x75,8 ;G Report Size
de 0x95,15 ;G Report Count
de 0x15,0 ;G Logical Minimum
de 0x26,255,0 ;G Logical Maximum
;Nr.1
de 0x85,1 ;M Report ID (1)
de 0x09,1 ;L Usage: 1 (Byte-Array)
de 0x81,2 ;M Input: Variable
;Nr.2
de 0x85,2 ;M Report ID (2)
de 0x09,2 ;L Usage: 2 (Byte-Array)
de 0xB1,2 ;M Feature: Variable
;Nr.3
de 0x85,3 ;M Report ID (3)
de 0x09,3 ;L Usage: 3 (Byte-Array)
de 0xB1,2 ;M Feature: Variable
;Nr.4
de 0x85,4 ;M Report ID (3)
de 0x09,4 ;L Usage: 3 (Byte-Array)
de 0x95,9 ;G Report Count (hier nur 9 Bytes, Gesamtlänge 10)
de 0xB1,2 ;M Feature: Variable
de 0xC0 ;M End Collection
HidRepDescEnd
DeviceDesc
de 18 ; bLength
de 1 ; bDescriptorType
dew 0x0210 ; bcdUSB (USB 2.1)
de 0 ; bDeviceClass (see interface descriptor)
de 0 ; bDeviceSubclass
de 0 ; bDeviceProtocol
de 1<<E0_SSH ; bMaxPacketSize0 (16 bytes)
dew 0x16C0 ; idVendor (Voti)
dew 0x27D9 ; idProduct (HID no keyboard/mouse/joystick)
dew 0x0300 ; bcdDevice
de 1 ; iVendor
de 2 ; iProduct
de 3 ; iSerialNo
de 1 ; bNumConfig
ConfigDesc
de 9 ; bLength
de 2 ; bDescriptorType
dew ConfigDescEnd-ConfigDesc ; wTotalLength
de 2 ; bNumInterfaces
de 1 ; bConfigValue
de 0 ; iConfig
de 0x80 ; bmAttributes (BusPower)
de 50 ; bMaxPower (100 mA)
;INTERFACE_DESCRIPTOR_0
de 9 ; bLength
de 4 ; bDescType (IFACE)
ROM00
de 0 ; bInterfaceNumber
ROM01
de 0 ; bAlternateSetting
de 1 ; bNumEndpoints
de 3 ; bIClass (HID)
de 0 ; bISubclass
de 0 ; bIProtocol
de 4 ; iIface
;HID descriptor
de 9 ; bLength
de 0x21 ; bDescType
dew 0x0110 ; bcdHID
de 0 ; bCountryCode
de 1 ; bNumDescriptors
de 0x22 ; bDescType Report
dew HidRepDescEnd-HidRepDesc; wDescriptorLength
;Endpoint
de 7 ; bLength
de 5 ; bDescriptorType (ENDPOINT)
de 0x81 ; bEndpointAddress (1 IN)
de 0x03 ; bmAttributes (interrupt)
dew 1<<E1I_SSH ; wMaxPacketSize (16)
de 250 ; bInterval (250 ms)
;INTERFACE_DESCRIPTOR_1
de 9 ; bLength
de 4 ; bDescriptorType (IFACE)
de 1 ; bInterfaceNumber
de 0 ; bAlternateSetting
de 1 ; bNumEndpoints
de 0xFF ; bIClass (vendorspec)
de 0 ; bISubclass
de 0 ; bIProtocol
de 5 ; iIface
;ENDPOINT_DESCRIPTOR_1_IN
de 7 ; bLength
de 5 ; bDescriptorType (ENDPOINT)
de 0x82 ; bEndpointAddress (1 IN)
de 0x03 ; bmAttributes (interrupt)
dew 1<<E2I_SSH ; wMaxPacketSize (64)
de 250 ; bInterval (250 ms)
ConfigDescEnd
BosDesc
de 5 ; Length
de 0x0F ; Binary Object Store descriptor
dew 57 ; Total length
de 2 ; Number of device capabilities
; WebUSB Platform Capability descriptor (bVendorCode == 0x01).
de 0x18 ; Length
de 0x10 ; Device Capability descriptor
de 0x05 ; Platform Capability descriptor
de 0x00 ; Reserved
de 0x38,0xB6,0x08,0x34,0xA9,0x09,0xA0,0x47,0x8B,0xFD,0xA0,0x76,0x88,0x15,0xB6,0x65 ; WebUSB GUID
dew 0x0100 ; Version 1.0
de 0x01 ; Vendor request code (-> bRequest)
de 0x01 ; Landing page (-> wValueL)
; Microsoft OS 2.0 Platform Capability Descriptor (MS_VendorCode == 0x02)
de 0x1C ; Length
de 0x10 ; Device Capability descriptor
de 0x05 ; Platform Capability descriptor
de 0x00 ; Reserved
de 0xDF,0x60,0xDD,0xD8,0x89,0x45,0xC7,0x4C,0x9C,0xD2,0x65,0x9D,0x9E,0x64,0x8A,0x9F ; MS OS 2.0 GUID
de 0,0,3,6 ; Windows version
dew 0x00B2 ; Descriptor set length
de 0x02 ; Vendor request code
de 0x00 ; Alternate enumeration code
BosDescEnd
if BosDescEnd-BosDesc !=57
error "Wrong struct!"
endif
MsOs20Desc
dew 10 ; Descriptor size (10 bytes)
dew 0 ; MS OS 2.0 descriptor set header
de 0,0,3,6 ; Windows version (8.1) (0x06030000)
dew 0x00B2 ; Size, MS OS 2.0 descriptor set
; Microsoft OS 2.0 configuration subset header
dew 8 ; Descriptor size (8 bytes)
dew 1 ; MS OS 2.0 configuration subset header
dew 0 ; bConfigurationValue
dew 0x00A8 ; Size, MS OS 2.0 configuration subset
; Microsoft OS 2.0 function subset header
dew 8 ; Descriptor size (8 bytes)
dew 2 ; MS OS 2.0 function subset header
dew 1 ; iface number
dew 0x00A0 ; Size, MS OS 2.0 function subset
; Microsoft OS 2.0 compatible ID descriptor (table 13)
dew 20 ; wLength
dew 3 ; MS_OS_20_FEATURE_COMPATIBLE_ID
de "WINUSB",0,0 ; compatID[8]
de 0,0,0,0,0,0,0,0 ; subcompatID[8];
;CUSTOM_PROPERTY
dew 4+21+1+40<<1 ; wLength:
dew 4 ; wDescType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
dew 7 ; wPropertyDataType: REG_MULTI_SZ (Table 15)
dew 21<<1 ; wPropertyNameLength:
de 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0,'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,'s',0,0,0 ; bPropertyName
dew 40<<1 ; wPropertyDataLength
de '{',0,'9',0,'7',0,'5',0,'F',0,'4',0,'4',0,'D',0,'9',0,'-',0,'0',0,'D',0,'0',0,'8',0,'-',0,'4',0,'3',0,'F',0,'D',0,'-',0,'8',0,'B',0,'3',0,'E',0,'-',0
de '1',0,'2',0,'7',0,'C',0,'A',0,'8',0,'A',0,'F',0,'F',0,'F',0,'9',0,'D',0,'}',0,0,0,0,0 ; bPropertyData
MsOs20DescEnd
if MsOs20DescEnd-MsOs20Desc != 23+66<<1
error "Wrong struct!"
endif
LandingPageDesc
de 0x2E ; strlen(landingPageUrl)+3
de 0x03 ; descriptorType(String)
de 0x01 ; landingPageScheme(https://)
de "www.tu-chemnitz.de/~heha/ewa/Ofen/rauch.htm"
LandingPageDescEnd
if LandingPageDescEnd-LandingPageDesc != 0x2E
error "Wrong struct!"
endif
StringDesc ; High-Teil = DTYPE_String, Low-Teil = (String-Länge+1)*2
dew 0x0304
dew 0x0407 ; (0) Länge 1: deutsch
dew 0x0322
de 'T',0,'U',0,' ',0,'C',0,'h',0,'e',0,'m',0,'n',0,'i',0,'t',0,'z',0,',',0,' ',0,'E',0,'W',0,'A',0 ; (1) Länge 16
dew 0x0318
de 'R',0,'a',0,'u',0,'c',0,'h',0,'m',0,'e',0,'l',0,'d',0,'e',0,'r',0 ; (2) Länge 11
dew 0x0330
de 'h',0,'e',0,'h',0,'a',0,'@',0,'h',0,'r',0,'z',0,'.',0,'t',0,'u',0,'-',0,'c',0,'h',0,'e',0,'m',0,'n',0,'i',0,'t',0,'z',0,'.',0,'d',0,'e',0 ;(3) Länge 23
dew 0x0308
de 'H',0,'I',0,'D',0 ; (4) Länge 3
dew 0x030E
de 'W',0,'e',0,'b',0,'U',0,'S',0,'B',0 ; (5) Länge 6
StringDescEnd
de "ABCÄÖÜ" ; legt UTF-8 in die Low-Bytes ab, Nullen in die High-Bytes
dt "ABCÄÖÜ" ; wie oben, aber 0x34 ins High-Byte = retlw
;de L"ABCÄÖÜ" ; Syntaxfehler
de 0x1234 ; legt 0x0034 ab
da 0x1234 ; legt 0x1234 ab
da '1','2','3','4' ; legt effektiv UTF-16 ab, aber nicht bei Umlauten!
;da '12' ; Syntaxfehler
;da L'1',L'2',L'Ä' ; Syntaxfehler
da "1","2","3","4" ; Legt jedes Zeichen 7-Bit in den High-Teil ab, also '1'<<7, '2'<<7 usw.
da "1234" ; Legt '1'<<7|'2' und '3'<<7|'4' ab
dw 1234
db 0x12,0x34
;Leider keine Möglichkeit, UTF-16 (<0x4000) abzulegen! Würde für alle Buchstabenschriften reichen.
Detected encoding: UTF-8 | 0
|