usbhidio.asm
上传用户:lyzyl198
上传日期:2008-05-19
资源大小:174k
文件大小:54k
- ;Filename: usbhidio.asm
- ;Version: 1.3
- ;Date: 11/5/99
- ;Copyright 1999 by Jan Axelson (jan@lvr.com)
- ;
- ;Chip: Cypress Semiconductor CY7C63001 USB Microcontroller
- ;Assembler: cyasm.exe
- ;Purpose: demonstrates USB communications with an HID-class device
- ;Description:
- ;Handles all required standard USB and HID-class requests.
- ;Receives data from the host in output reports
- ;using interrupt transfers on Endpoint 1.
- ;Sends data to the host in input reports
- ;using control transfers on Endpoint 0.
- ;(The chip doesn't support OUT transfers on Endpoint 1.)
- ;I used Cypress Semiconductor's js50.asm joystick example code as a base
- ;in creating this program.
- ;The companion host software is the Visual-Basic project usbhidio.vbp.
- ;For more information, visit Lakeview Research at http://www.lvr.com .
- ;Send comments, bug reports, etc. to jan@lvr.com .
- ;Changes:
- ;V1.3: 11/20/99
- ;The length of the string descriptors is now correct.
- ;(Thanks, John Hyde)
- ;Changed the control_read routine to prevent error when sending a
- ;multiple of 8 bytes.
- ;(Thanks, Dave Wright)
- ;V1.2:
- ;added watchdog resets in wait loops,
- ;took out the watchdog reset in the 1-msec. timer ISR.
- ;V1.1:
- ;Clears the watchdog only in the main routine
- ;(so the watchdog will detect if the main routine crashes).
- ;Additions to the comments.
- ;V1.0:
- ;Clears the Watchdog timer on 1-msec. interrupt.
- ;(Not needed on the development board, but needed for stand-alone.)
- ;The Endpoint 1 ISR now sets bit 7 of Endpoint 1 TX config to 1.
- ;(The bit is cleared on EP1 interrupt.)
- ;======================================================================
- ;assembler directives (equates)
- ;======================================================================
- ;----------------------------------------------------------------------
- ;I/O registers
- ;----------------------------------------------------------------------
- ;I/O ports
- Port0_Data: equ 00h ; GPIO data port 0
- Port1_Data: equ 01h ; GPIO data port 1
- Port0_Interrupt: equ 04h ; Interrupt enable for port 0
- Port1_Interrupt: equ 05h ; Interrupt enable for port 1
- Port0_Pullup: equ 08h ; Pullup resistor control for port 0
- Port1_Pullup: equ 09h ; Pullup resistor control for port 1
- ;USB ports
- USB_EP0_TX_Config: equ 10h ; USB EP0 transmit configuration
- USB_EP1_TX_Config: equ 11h ; USB EP1 transmit configuration
- USB_Device_Address: equ 12h ; USB device address assigned by host
- USB_Status_Control: equ 13h ; USB status and control register
- USB_EP0_RX_Status: equ 14h ; USB EP0 receive status
- ;Control ports
- Global_Interrupt: equ 20h ; Global interrupt enable
- Watchdog: equ 21h ; clear watchdog Timer
- Timer: equ 23h ; free-running Timer
- ;GPIO Isink registers
- Port0_Isink: equ 30h
- Port0_Isink0: equ 30h
- Port0_Isink1: equ 31h
- Port0_Isink2: equ 32h
- Port0_Isink3: equ 33h
- Port0_Isink4: equ 34h
- Port0_Isink5: equ 35h
- Port0_Isink6: equ 36h
- Port0_Isink7: equ 37h
- Port1_Isink: equ 38h
- Port1_Isink0: equ 38h
- Port1_Isink1: equ 39h
- Port1_Isink2: equ 3Ah
- Port1_Isink3: equ 3Bh
- ;Control port
- Status_Control: equ FFh
- ;----------------------------------------------------------------------
- ;Register bit values
- ;----------------------------------------------------------------------
- ;CPU Status and Control (Status_Control)
- RunBit: equ 1h ; CPU Run bit
- USBReset: equ 20h ; USB Bus Reset bit
- WatchDogReset: equ 40h ; Watchdog Reset bit
- ; USB EP1 transmit configuration (USB_EP1_TX_Config)
- DataToggle: equ 40h ; Data 0/1 bit
- DISABLE_REMOTE_WAKEUP: equ 0 ; bit[1] = 0
- ENABLE_REMOTE_WAKEUP: equ 2 ; bit[1] = 1
- ;----------------------------------------------------------------------
- ;Interrupt masks
- ;----------------------------------------------------------------------
- ;The timer-only mask enables the 1-millisecond timer interrupt.
- TIMER_ONLY: equ 4h
- ;The enumerate mask enables the following interrupts:
- ;1-millisecond timer, USB Endpoint 0
- ENUMERATE_MASK: equ 0Ch
- ;The runtime mask enables the following interrupts:
- ;1-millisecond timer, USB Endpoint 0, USB Endpoint 1, GPIO
- RUNTIME_MASK: equ 5Ch
- ;----------------------------------------------------------------------
- ; USB Constants
- ; from the USB Spec v1.1
- ;----------------------------------------------------------------------
- ;standard request codes
- get_status: equ 0
- clear_feature: equ 1
- set_feature: equ 3
- set_address: equ 5
- get_descriptor: equ 6
- set_descriptor: equ 7
- get_configuration: equ 8
- set_configuration: equ 9
- get_interface: equ 10
- set_interface: equ 11
- synch_frame: equ 12
- ; standard descriptor types
- device: equ 1
- configuration: equ 2
- string: equ 3
- interface: equ 4
- endpoint: equ 5
- ; standard feature selectors
- endpoint_stalled: equ 0 ; recipient endpoint
- device_remote_wakeup: equ 1 ; recipient device
- ;----------------------------------------------------------------------
- ;HID-class descriptors
- ;from HID Class Definition v1.1 Draft
- ;----------------------------------------------------------------------
- ;Class-specific descriptor types from section 7.1 Standard Requests
- HID: equ 21h
- report: equ 22h
- physical: equ 23h
-
- ;Class-specific request codes from section 7.2 Class Specific Requests
- get_report: equ 1
- get_idle: equ 2
- get_protocol: equ 3
- set_report: equ 9
- set_idle: equ 10
- set_protocol: equ 11
- ;----------------------------------------------------------------------
- ;USB buffer bytes
- ;----------------------------------------------------------------------
- ;Control Endpoint 0 buffer
- Endpoint_0: equ 70h ; control endpoint
- Endpoint0_Byte0: equ 70h ; Endpoint 0, byte 0
- Endpoint0_Byte1: equ 71h ; Endpoint 0 byte 1
- Endpoint0_Byte2: equ 72h ; Endpoint 0 byte 2
- Endpoint0_Byte3: equ 73h ; Endpoint 0 byte 3
- Endpoint0_Byte4: equ 74h ; Endpoint 0 byte 4
- Endpoint0_Byte5: equ 75h ; Endpoint 0 byte 5
- Endpoint0_Byte6: equ 76h ; Endpoint 0 byte 6
- Endpoint0_Byte7: equ 77h ; Endpoint 0 byte 7
- ;Endpoint 0 SETUP packet bytes
- bmRequestType: equ 70h
- bRequest: equ 71h
- wValue: equ 72h ; default wValue (8 bits)
- wValueHi: equ 73h
- wIndex: equ 74h ; default wIndex (8 bits)
- wIndexHi: equ 75h
- wLength: equ 76h ; default wLength (8 bits)
- wLengthHi: equ 77h
- ;Endpoint 1 buffer
- endpoint_1: equ 78h
- Endpoint1_Byte0: equ 78h ; Endpoint 1, byte 0
- Endpoint1_Byte1: equ 79h ; Endpoint 1 byte 1
- Endpoint1_Byte2: equ 7Ah ; Endpoint 1 byte 2
- Endpoint1_Byte3: equ 7Bh ; Endpoint 1 byte 3
- Endpoint1_Byte4: equ 7Ch ; Endpoint 1 byte 4
- Endpoint1_Byte5: equ 7Dh ; Endpoint 1 byte 5
- Endpoint1_Byte6: equ 7Eh ; Endpoint 1 byte 6
- Endpoint1_Byte7: equ 7Fh ; Endpoint 1 byte 7
- ;----------------------------------------------------------------------
- ; Variables stored in data memory
- ;----------------------------------------------------------------------
- ;USB status
- remote_wakeup_status: equ 30h ;0=disabled, 2-enabled
- configuration_status: equ 31h ;0=unconfigured, 1=configured
- ;idle_status: equ 33h ;support SetIdle and GetIdle
- protocol_status: equ 34h ;0=boot protocol, 1=report protocol
- ;Other variables:
- suspend_counter: equ 35h ;number of idle bus milliseconds
- loop_temp: equ 37h ;temporary loop variable
- start_send: equ 32h ;0=false, 1=true
- ;Received data:
- Data_Byte0: equ 38h
- Data_Byte1: equ 39h
- Data_Byte2: equ 3Ah
- Data_Byte3: equ 3Bh
- Data_Byte4: equ 3Ch
- Data_Byte5: equ 3Dh
- Data_Byte6: equ 3Eh
- Data_Byte7: equ 3Fh
- temp: equ 25h
- start_time: equ 21h
- testbit: equ 22h
- interrupt_mask: equ 20h
- endp0_data_toggle: equ 23h
- loop_counter: equ 24h
- data_start: equ 27h
- data_count: equ 28h
- endpoint_stall: equ 29h
- ;======================================================================
- ;interrupt vectors
- ;======================================================================
- org 00h ; Reset vector; begin here after a reset.
- jmp Reset
- org 02h ; 128-microsecond interrupt
- jmp DoNothing_ISR
- org 04h ; 1024-millisecond interrupt
- jmp One_mSec_ISR
- org 06h ; Endpoint 0 interrupt
- jmp USB_EP0_ISR
- org 08h ; Endpoint 1 interrupt
- jmp USB_EP1_ISR
- org 0Ah ; reserved interrupt
- jmp Reset
- org 0Ch ; general purpose I/O interrupt
- jmp GPIO_ISR ; not used
- org 0Eh ; Wakeup_ISR or resume interrupt
- jmp DoNothing_ISR ; not used
- ORG 10h
- ;======================================================================
- ;Interrupt routines
- ;======================================================================
- ;----------------------------------------------------------------------
- ; 128-microsecond interrupt, Cext
- ; Unused. If this interrupt occurs, just push the accumulator (because
- ; ipret pops it) and re-enable the interrupts.
- ;----------------------------------------------------------------------
- DoNothing_ISR:
- push A
- ;Enable interrupts and return
- mov A,[interrupt_mask]
- ipret Global_Interrupt
- ;----------------------------------------------------------------------
- ; 1-millisecond interrupt
- ; Check to see if the chip is in suspend mode and take appropriate action.
- ; Copy values to Endpoint 1's buffer for sending.
- ;----------------------------------------------------------------------
- One_mSec_ISR:
- push A
- iowr Watchdog
- ;Find out if enumeration is complete.
- ;If enumerating is in progress, loop_temp = 0.
- mov A, [loop_temp]
- cmp A, 0h
- ;If enumeration is still in progress, jump.
- jz not_main
- ;Enumeration has ended, so decrement the loop counter
- ;(so it no longer = 0).
- dec [loop_temp]
- not_main:
- ;Check for bus activity.
- iord USB_Status_Control
- and A, 01h
- cmp A,0h
- ;If no bus activity, increment the suspend counter.
- jz Inc_counter
- ;If bus activity detected, clear the bus-activity bit,
- iord USB_Status_Control
- and A, 0FEh
- iowr USB_Status_Control
- ;and clear the suspend counter.
- mov A, 0h
- mov [suspend_counter], A
- jmp Suspend_end
- Inc_counter:
- ;Keep track of the amount of time with no bus activity.
- inc [suspend_counter]
- ;Get the number of milliseconds the bus has been idle.
- mov A, [suspend_counter]
- ;Has it been 3 milliseconds?
- cmp A, 03h
- ;If no, there's nothing else to do.
- jnz Suspend_end
- ;If yes, put the chip in Suspend mode.
- ;Clear the Suspend counter.
- mov A, 0h
- mov [suspend_counter], A
- ;Enable pullups on Port 1; disable the output DAC.
- mov A, 0h
- iowr Port1_Pullup
- mov A, 0ffh
- iowr Port1_Data
- ;Set the Suspend bit.
- iord Status_Control
- or A, 08h
- iowr Status_Control
- ;The chip is now in Suspend mode.
- ;On exiting Suspend mode, the chip will begin
- ;executing instructions here:
- nop
- ;Disable pullups on Port 1. Enable the output DAC.
- mov A, 0ffh
- iowr Port1_Pullup
- mov A, 0h
- iowr Port1_Data
- Suspend_end:
- ;Is endpoint 1 enabled?
- iord USB_EP1_TX_Config
- cmp A,0
- ;If no, do nothing.
- jz Select
- ;If yes, is start_send = 1?
- ;(Start_send adds a short delay after enumeration.)
- mov A, [start_send]
- cmp A, 01h
- ;If no, do nothing
- jnz Select
- ;If yes, send data:
- jmp send_value
- send_value:
- ;Copies values from RAM into Endpoint 1's buffer
- ;and enables sending the bytes on the next poll.
- ;disable Endpoint 1 interrupts
- mov A,[interrupt_mask]
- and A, EFh
- mov [interrupt_mask],A
- iowr Global_Interrupt
- ;Copy values from RAM to Endpoint 1's buffer for transmitting to the host.
- ;Two bytes:
- mov A, [Data_Byte0]
- mov [Endpoint1_Byte0], A
- mov A, [Data_Byte1]
- mov [Endpoint1_Byte1], A
- ;Add more bytes if the report format specifies it:
- ; mov A, [Data_Byte2]
- ; mov [Endpoint1_Byte2], A
- ; mov A, [Data_Byte3]
- ; mov [Endpoint1_Byte3], A
- ; mov A, [Data_Byte4]
- ; mov [Endpoint1_Byte4], A
- ; mov A, [Data_Byte5]
- ; mov [Endpoint1_Byte5], A
- ; mov A, [Data_Byte6]
- ; mov [Endpoint1_Byte6], A
- ; mov A, [Data_Byte7]
- ; mov [Endpoint1_Byte7], A
- ;Other things to try:
- ;Set the value at Port 0 to equal byte 0 in Endpoint 1's buffer:
- ; iord Port0_Data
- ; mov [Endpoint1_Byte0], A
- ;Or set a value here and copy to Endpoint 1's buffer, byte 1:
- ; mov A, A5h
- ; mov [Endpoint1_Byte1], A
- ;Configure Endpoint 1's transmit register
- ;so that the bytes will transmit on the next poll.
- iord USB_EP1_TX_Config
- ;Don't change the Data 0/1 bit.
- and A,40h
- ;Set bits 4 and 7 to 1 enable transmitting.
- ;The low nibble is the number of data bytes (2).
- or A,92h
- iowr USB_EP1_TX_Config
- Select:
- ;Enable Endpoint 1 interrupts.
- mov A,[interrupt_mask]
- or A, 10h
- mov [interrupt_mask],A
- ipret Global_Interrupt
- ;----------------------------------------------------------------------
- ;GPIO interrupt
- ;Can be configured to trigger when a port bit toggles.
- ;Unused here.
- ;----------------------------------------------------------------------
- GPIO_ISR:
- push A
- push X
- pop X
- mov [interrupt_mask],A
- ipret Global_Interrupt
- ;----------------------------------------------------------------------
- ;Endpoint 1 ISR
- ;Endpoint 1 can do IN (device to host) transfers only.
- ;This interrupt triggers when the host acknowledges
- ;receiving data from Endpoint 1.
- ;The ISR toggles the data 0/1 bit for the next transaction and
- ;sets the EnableRespondToIN bit so the chip will respond to the
- ;next poll of the endpoint.
- ;----------------------------------------------------------------------
- USB_EP1_ISR:
- push A
- ;Toggle the data 0/1 bit so it's correct for the next transaction.
- iord USB_EP1_TX_Config
- xor A,40h
- ;The interrupt clears the EnableRespondToIN bit (bit 7) in the TX Config.
- ;Set this bit to 1 so data will go out on the next poll.
- ;This will ensure that a ReadFile API call in a Windows application
- ;won't hang, waiting for the device to send something.
- or A, 92h
- iowr USB_EP1_TX_Config
- ;Enable interrupts and return.
- mov A, [interrupt_mask]
- ipret Global_Interrupt
- ;----------------------------------------------------------------------
- ; Reset processing
- ; Triggers on Reset or "reserved" interrupt.
- ;To be safe, initialize everything.
- ;----------------------------------------------------------------------
- Reset:
- ;Place the data stack pointer at the lowest address of Endpoint 0's buffer.
- ;This keeps the stack from writing over the USB buffers.
- ;The USB buffers are in high RAM;
- ;the data stack pointer pre-decrements on a Push instruction.
- mov A, Endpoint_0
- swap A, dsp
- ;Initialize to FFh
- mov A, 0ffh
- iowr Port0_Data ; output ones to port 0
- iowr Port1_Pullup ; disable port 1 pullups
- ; select rising edge interrupts
- iowr Port1_Isink0 ; maximum isink current Port1 bit 0
- iowr Port1_Isink1 ; maximum isink current Port1 bit 1
- iowr Port1_Isink2 ; maximum isink current Port1 bit 2
- iowr Port1_Isink3 ; maximum isink current Port1 bit 3
- ;Initialize to 00h
- mov A, 0h
- iowr Port1_Data ; output zeros to port 1
- iowr Port0_Interrupt ; disable port 0 interrupts
- iowr Port0_Pullup ; enable port 0 pullups
- iowr Port0_Isink0 ; minimum sink current Port0 bit 0
- iowr Port0_Isink1 ; minimum sink current Port0 bit 1
- iowr Port0_Isink2 ; minimum sink current Port0 bit 2
- iowr Port0_Isink3 ; minimum sink current Port0 bit 3
- iowr Port0_Isink4 ; minimum sink current Port0 bit 4
- iowr Port0_Isink5 ; minimum sink current Port0 bit 5
- iowr Port0_Isink6 ; minimum sink current Port0 bit 6
- iowr Port0_Isink7 ; minimum sink current Port0 bit 7
- mov [Endpoint1_Byte0],A
- mov [Endpoint1_Byte1],A
- mov [Endpoint1_Byte2],A
- mov [endpoint_stall], A
- mov [remote_wakeup_status], A
- mov [configuration_status], A
- mov [loop_temp], A
- mov [start_send], A
- iowr Watchdog ; clear watchdog timer
- ;Initialize values to transmit at Endpoint 1.
- ; mov A, A5h
- ; mov [Data_Byte0], A
- ; mov A, F0h
- ; mov [Data_Byte1], A
- ;Enable Port 1, bit 0 interrupts.
- ; mov A, 01h
- ; iowr Port1_Interrupt
- ;
- ;Test what kind of reset occurred: bus or watchdog?
- iord Status_Control
- ;Was it a bus reset?
- and A, USBReset
- ;If yes, jump to handle it.
- jnz BusReset
- iord Status_Control
- ;Was it a watchdog reset?
- and A, WatchDogReset
- ;If no, continue to wait for a bus reset
- jz suspendReset
- ;
- ;Watchog reset:
- ;A watchdog reset means that the watchdog timer
- ;wasn't cleared for 8.192 milliseconds.
- ;Wait for a bus reset to bring the system alive again.
- ;Enable 1-millisecond interrupt only
- mov A, TIMER_ONLY
- mov [interrupt_mask],A
- iowr Global_Interrupt
- ;Wait for a bus reset.
- WatchdogHandler:
- jmp WatchdogHandler
- suspendReset:
- ;Return to suspend mode to wait for a USB bus reset.
- mov A, 09h
- iowr Status_Control
- nop
- jmp suspendReset
- BusReset:
- ;Clear all reset bits.
- ;Set bit 0 (the run bit).
- mov A, RunBit
- iowr Status_Control
- ;Set up for enumeration (Endpoint 0 and 1-millisecond interrupts enabled)
- mov A, ENUMERATE_MASK
- mov [interrupt_mask],A
- iowr Global_Interrupt
- wait:
- ;Wait until configured.
- iord USB_EP1_TX_Config
- cmp A, 0
- ;Clear the watchdog timer
- iowr Watchdog
- ;If not configured, continue to wait.
- jz wait
- ;When configured, initialize loop_temp.
- ;Loop_temp adds a delay in the start of transmission of data.
- ;The chip will respond to the first IN packet no sooner than
- ;230 milliseconds after enumeration is complete.
- ;The delay was included in Cypress' joystick code to prevent problems
- ;that occurred when power cycled off and on or the joystick was plugged
- ;in before the host powered up.
- ;I've left it in because it does no harm and
- ;other hardware might have similar behavior.
- ;During the delay, the chip sends a NAK in response to any IN packet.
- mov A, 0ffh
- mov [loop_temp], A
- ;Enable endpoint 1
- iord USB_EP1_TX_Config
- or A, 92h
- iowr USB_EP1_TX_Config
- ;======================================================================
- ; The main program loop.
- ;======================================================================
- main:
- ;Find out if the loop_temp delay has timed out.
- ;Loop_temp =0 if not timed out, FFh if timed out.
- mov A, [loop_temp]
- cmp A, 0Ah
- ;If no, don't enable transmitting.
- jnc no_set
- ;If yes, enable transmitting.
- mov A, 01h
- mov [start_send], A
- no_set:
- ;Clear the watchdog timer.
- ;This has to be done at least once every 8 milliseconds!
- iowr Watchdog
- iord Port0_Data
- nochange:
- jmp main
- ;----------------------------------------------------------------------
- ;The Endpoint 0 ISR supports the control endpoint.
- ;This code enumerates and configures the hardware.
- ;It also responds to Set Report requests that receive data from the host.
- ;----------------------------------------------------------------------
- USB_EP0_ISR:
- push A
- iord USB_EP0_RX_Status
- ;Has a Setup packet been received?
- and A, 01h
- ;If no, find out if it's an OUT packet.
- jz check_for_out_packet
- ;If yes, handle it.
- ;Disable Endpoint 0 interrupts.
- mov A,[interrupt_mask]
- and A, 0F7h
- mov [interrupt_mask], A
- iowr Global_Interrupt
- ;Find out what the Setup packet contains and handle the request.
- call StageOne
- ;Re-enable Endpoint 0 interrupts.
- mov A, [interrupt_mask]
- or A, 08h
- mov [interrupt_mask], A
- jmp done_with_packet
- check_for_out_packet:
- iord USB_EP0_RX_Status
- ;Is it an OUT packet?
- and A, 02h
- ;If no, ignore it.
- jz done_with_packet
- ;If yes, process the received data.
- ;Disable Endpoint 0 interrupts.
- mov A,[interrupt_mask]
- and A, 0F7h
- mov [interrupt_mask], A
- iowr Global_Interrupt
- ;For debugging: set Port 0, bit 1 to show that we're here.
- ; iord Port0_Data
- ; or a, 2
- ; iowr Port0_Data
- ;Read the first byte in the buffer
- mov a, [Endpoint_0]
- ;For debugging: if the first byte =12h, bring Port 0, bit 0 high
- ; cmp a, 12h
- ; jnz not_a_match
- ; iord Port0_Data
- ; or a, 4
- ; iowr Port0_Data
- not_a_match:
- ;For debugging, add 1 to each byte read
- ;and copy the bytes to RAM.
- ;These bytes will be sent back to the host.
- push X
- ;data_count holds the number of bytes left to read.
- ;X holds the index of the address to read
- ;and the index of the address to store the received data.
- ;Initialize the X register.
- mov X, 0
-
- Get_Received_Data:
- ;Find out if there are any bytes to read.
- mov A, 0
- cmp A, [data_count]
- ;Jump if nothing to read.
- jz DoneWithReceivedData
- ;Get a byte.
- mov A, [X + Endpoint_0]
- ;For debugging, increment the received value.
- ;(Endpoint 1 will send it back to the host.)
- ;If the value is 255, reset to 0.
- ;Otherwise increment it.
- cmp A, 255
- jz ResetToZero
- inc A
- jmp NewValueSet
- ResetToZero:
- mov A, 0
- NewValueSet:
- ;Save the value.
- mov [X + Data_Byte0], A
- ;Decrement the number of bytes left to read.
- dec [data_count]
- ;Increment the address to read.
- inc X
- ;Do another
- jmp Get_Received_Data
- DoneWithReceivedData:
- pop X
- ;For debugging, set Port 0 to match the value written.
- ; iowr Port0_Data
- ;Handshake by sending a 0-byte data packet.
- call Send0ByteDataPacket
- done_with_packet:
- ;Re-enable Endpoint 0 interrupts.
- mov A,[interrupt_mask]
- or A, 08h
- mov [interrupt_mask], A
- ipret Global_Interrupt
- ;========================================================================
- ;Control transfers
- ;========================================================================
- ;------------------------------------------------------------------------
- ;Control transfer, stage one.
- ;Find out whether the request is a standard device or HID-class request,
- ;the direction of data transfer,
- ;and whether the request is to a device, interface, or endpoint.
- ;(from Table 9.2 in the USB spec)
- ;------------------------------------------------------------------------
- StageOne:
- ;Clear the Setup flag
- mov A, 00h
- iowr USB_EP0_RX_Status
- ;Set the StatusOuts bit to cause auto-handshake after receiving a data packet.
- mov A, 8
- iowr USB_Status_Control
- ;bmRequestType contains the request.
- mov A, [bmRequestType]
- ;Standard device requests. From the USB spec.
- ; host to device requests
- cmp A, 00h
- jz RequestType00 ; bmRequestType = 00000000 device
- ; cmp A, 01h *** not required ***
- ; jz RequestType01 ; bmRequestType = 00000001 interface
- cmp A, 02h
- jz RequestType02 ; bmRequestType = 00000010 endpoint
- cmp A, 80h
- ; device to host requests
- jz RequestType80 ; bmRequestType = 10000000 device
- cmp A, 81h
- jz RequestType81 ; bmRequestType = 10000001 interface
- cmp A, 82h
- jz RequestType82 ; bmRequestType = 10000010 endpoint
- ;HID-class device requests. From the HID spec
- ; host to device requests
- cmp A, 21h
- jz RequestType21 ; bmRequestType = 00100001 interface
- cmp A, 22h ; *** not in HID spec ***
- jz RequestType22 ; bmRequestType = 00100010 endpoint
- ; device to host requests
- cmp A, A1h
- jz RequestTypeA1 ; bmRequestType = 10100001 interface
- ; Stall unsupported requests
- SendStall:
- mov A, A0h
- iowr USB_EP0_TX_Config
- ret
- ;----------------------------------------------------------------------
- ;Control transfer, stage two
- ;Find out which request it is.
- ;----------------------------------------------------------------------
- ;Host to device with device as recipient
- RequestType00:
- ;The Remote Wakeup feature is disabled on reset.
- mov A, [bRequest] ; load bRequest
- ; Clear Feature bRequest = 1
- cmp A, clear_feature
- jz ClearRemoteWakeup
- ; Set Feature bRequest = 3
- cmp A, set_feature
- jz SetRemoteWakeup
- ; Set the device address to a non-zero value.
- ; Set Address bRequest = 5
- cmp A, set_address
- jz SetAddress
- ; Set Descriptor is optional.
- ; Set Descriptor bRequest = 7 *** not supported ***
- ;If wValue is zero, the device is not configured.
- ;The only other legal value for this firmware is 1.
- ;Set Configuration bRequest = 9
- cmp A, set_configuration
- jz SetConfiguration
- ;Stall unsupported requests.
- jmp SendStall
- ;Host to device with interface as recipient *** not required ***
- ; RequestType01:
- ; mov A, [bRequest] ; load bRequest
- ; There are no interface features defined in the spec.
- ; Clear Feature bRequest = 1 *** not supported ***
- ; Set Feature bRequest = 3 *** not supported ***
- ; Set Interface is optional.
- ; Set Interface bRequest = 11 *** not supported ***
- ;Stall unsupported requests.
- ; jmp SendStall
- ;Host to device with endpoint as recipient
- RequestType02:
- mov A, [bRequest] ; load bRequest
- ; The only standard feature defined for an endpoint is endpoint_stalled.
- ; Clear Feature bRequest = 1
- cmp A, clear_feature
- jz ClearEndpointStall
- ; Set Feature bRequest = 3
- cmp A, set_feature
- jz SetEndpointStall
-
- ;Stall unsupported functions.
- jmp SendStall
- ;Device to host with device as recipient
- RequestType80:
- mov A, [bRequest] ; load bRequest
- ; Get Status bRequest = 0
- cmp A, get_status
- jz GetDeviceStatus
- ; Get Descriptor bRequest = 6
- cmp A, get_descriptor
- jz GetDescriptor
- ; Get Configuration bRequest = 8
- cmp A, get_configuration
- jz GetConfiguration
- ;Stall unsupported requests.
- jmp SendStall
- ;Device to host with interface as recipient
- RequestType81:
- mov A, [bRequest] ; load bRequest
- ; Get Status bRequest = 0
- cmp A, get_status
- jz GetInterfaceStatus
- ; Get Interface returns the selected alternate setting.
- ; This firmware supports no alternate settings.
- ; Get Interface bRequest = 10 *** not supported ***
- ;The HID class defines one more request for bmRequestType=10000001
- ; Get Descriptor bRequest = 6
- cmp A, get_descriptor
- jz GetDescriptor
- ;Stall unsupported functions
- jmp SendStall
- ;Device to host with endpoint as recipient
- RequestType82:
- mov A, [bRequest] ; load bRequest
- ; Get Status bRequest = 0
- cmp A, get_status
- jz GetEndpointStatus
- ; Get Descriptor bRequest = 6
- cmp A, get_descriptor
- jz GetDescriptor
- ; Sync Frame bRequest = 12 *** not supported ***
- ;Stall unsupported functions.
- jmp SendStall
- ;Check for HID class requests
- ;Host to device with endpoint as recipient
- RequestType21:
- mov A, [bRequest] ; load bRequest
- ; Set Report bRequest = 9
- cmp A, set_report
- jz SetReport
- ; Set Idle bRequest = 10
- cmp A, set_idle
- jz SetIdle
- ; Set Protocol bRequest = 11
- cmp A, set_protocol
- jz SetProtocol
- ;Stall unsupported requests
- jmp SendStall
- RequestType22:
- mov A, [bRequest] ; load bRequest
- ; Set Report bRequest = 9
- cmp A, set_report
- jz SetReport
- ;Stall unsupported requests
- jmp SendStall
- ;Device to host with endpoint as recipient
- RequestTypeA1:
- mov A, [bRequest] ; load bRequest
- ; Get Report bRequest = 1
- cmp A, get_report
- jz GetReport
- ; Get Idle bRequest = 2
- cmp A, get_idle
- jz GetIdle
- ; Get Protocol bRequest = 3
- cmp A, get_protocol
- jz GetProtocol
- ;Stall unsupported requests
- jmp SendStall
- ;----------------------------------------------------------------------
- ;Control transfer, stage three
- ;Process the request.
- ;----------------------------------------------------------------------
- ;The host controls whether or not a device can request a remote wakeup.
- ; Disable the remote wakeup capability.
- ClearRemoteWakeup:
- mov A, [wValue]
- cmp A, device_remote_wakeup
- jnz SendStall
- ;Handshake by sending a data packet
- call Send0ByteDataPacket
- mov A, DISABLE_REMOTE_WAKEUP
- mov [remote_wakeup_status], A
- ret
- ; Enable the remote wakeup capability.
- SetRemoteWakeup:
- mov A, [wValue]
- cmp A, device_remote_wakeup
- ;If not a match, stall.
- jnz SendStall
- ;Handshake by sending a 0-byte data packet
- call Send0ByteDataPacket
- ;Perform the request.
- mov A, ENABLE_REMOTE_WAKEUP
- mov [remote_wakeup_status], A
- ret
- SetAddress:
- ; Set the device address to match wValue in the Setup packet.
- ;Complete the requested action after completing the transaction.
- ;Handshake by sending a 0-byte data packet.
- call Send0ByteDataPacket
- ;Perform the request
- mov A, [wValue]
- iowr USB_Device_Address
- ret
- SetConfiguration:
- ;Unconfigured: wValue=0, configured: wValue=1.
- ;Also clear any stall condition and set Data 0/1 to Data0.
- ;Handshake by sending a 0-byte data packet.
- call Send0ByteDataPacket
- ;Save the configuration status.
- mov A, [wValue]
- mov [configuration_status], A
- ;Clear any stall condtion
- mov A, 0
- mov [endpoint_stall], A
- ;Set data 0/1 to Data0
- iord USB_EP1_TX_Config
- and A, ~DataToggle
- ;Set the configuration status.
- iowr USB_EP1_TX_Config
- mov A, [configuration_status]
- cmp A, 0
- ;If configured, jump.
- jnz device_configured
- ;If unconfigured:
- ;Disable Endpoint 1
- iord USB_EP1_TX_Config
- and A, EFh
- iowr USB_EP1_TX_Config
- ;Disable Endpoint 1 interrupts.
- mov A, [interrupt_mask]
- and A, EFh
- mov [interrupt_mask], A
- jmp done_configuration
- ;If configured:
- device_configured:
- ;Send NAK in response to IN packets
- iord USB_EP1_TX_Config
- and A,7Fh
- ;Enable Endpoint 1
- or A, 10h
- iowr USB_EP1_TX_Config
- ;Enable interrupts: Endpoint 1 and GPIO
- mov A, [interrupt_mask]
- or A, 50h
- mov [interrupt_mask], A
- ;Send NAK in response to Endpoint 0 OUT packets.
- iord USB_Status_Control
- and A,0EFh
- iowr USB_Status_Control
- done_configuration:
- ret
- ClearEndpointStall:
- ;Clear the stall (halt) condition for Endpoint 1.
- ;wValue = 0.
- mov A, [wValue]
- cmp A, endpoint_stalled
- ;If endpoint_stalled = 0, the endpoint isn't stalled
- ;and there's nothing to clear. Return a Stall for the request.
- jnz SendStall
- ;
- ;Clear Endpoint 1 stall
- ;Handshake by sending a 0-byte data packet
- call Send0ByteDataPacket
- ;Clear the stall condition
- mov A,0
- mov [endpoint_stall], A
- ;Set Data 0/1 to Data0
- iord USB_EP1_TX_Config
- and A, ~DataToggle
- iowr USB_EP1_TX_Config
- ;Send NAK in response to Endpoint 0 OUT packets.
- iord USB_Status_Control
- and A,0EFh
- iowr USB_Status_Control
- ret
- ;Stall Endpoint 1
- SetEndpointStall:
- ;wValue = 0.
- mov A, [wValue]
- cmp A, endpoint_stalled
- ;If endpoint_stalled = 1, the endpoint is already stalled,
- ;so return a Stall for this request.
- jnz SendStall
- ;Handshake by sending a 0-byte data packet.
- call Send0ByteDataPacket
- ;Stall the endpoint.
- mov A,1
- mov [endpoint_stall], A
- mov A, 30h
- iowr USB_EP1_TX_Config
- ret
- GetDeviceStatus:
- ;Device Status is a 2-byte value.
- ;Bit 0 must be 0 (bus-powered).
- ;Bit 1 is remote wakeup: 0=disabled, 1=enabled.
- ;All other bits are unused.
- ;Return to status bytes to the host.
- mov A, 2
- mov [data_count], A
- ;control_read_table holds the two possible values for device status.
- ;Get the address of the first value.
- mov A, (get_dev_status_table - control_read_table)
- ;Add an index value to select the correct value.
- add A, [remote_wakeup_status]
- ;Send the value.
- jmp SendDescriptor
- GetDescriptor:
- ;The high byte of wValue contains the descriptor type.
- ;The low byte of wValue contains the descriptor index.
- mov A, [wValueHi] ; load descriptor type
- ;Test for standard descriptor types first.
- ;Supported descriptor types are device, configuration, string.
- ;Unsupported descriptor types are interface, endpoint.
- ; Get Descriptor (device) wValueHi = 1
- cmp A, device
- jz GetDeviceDescriptor
- ; Get Descriptor (configuration) wValueHi = 2
- cmp A, configuration
- jz GetConfigurationDescriptor
- ; Get Descriptor (string) wValueHi = 3
- cmp A, string
- jz GetStringDescriptor
- ; Test for HID-class descriptor types.
- ; Get Descriptor (HID) wValueHi = 21h
- cmp A, HID
- jz GetHIDDescriptor
- ; Get Descriptor (report) wValueHi = 22h
- cmp A, report
- jz GetReportDescriptor
- ; Get Descriptor (physical) wValueHi = 23h *** not supported ***
- ;Stall unsupported requests.
- jmp SendStall
- GetConfiguration:
- ;Send the current device configuration.
- ;0 = unconfigured, 1 = configured.
- ;Send 1 byte
- mov A, 1
- mov [data_count], A
- ;Get the address of the data to send.
- mov A, (get_configuration_status_table - control_read_table)
- ;Add an index to point to the correct configuration.
- add A, [configuration_status]
- ;Send the data.
- jmp SendDescriptor
- GetInterfaceStatus:
- ;Interface status is 2 bytes, which are always 0.
- ;Send 2 bytes.
- mov A, 2
- mov [data_count], A
- ;Get the address of the data to send.
- mov A, (get_interface_status_table - control_read_table)
- ;Send the data.
- jmp SendDescriptor
- GetEndpointStatus:
- ;Endpoint status is 2 bytes.
- ;Bit 0 = 0 when the endpoint is not stalled.
- ;Bit 0 = 1 when the endpoint is stalled.
- ;All other bits are unused.
- ;Send 2 bytes.
- mov A, 2
- mov [data_count], A
- ;Get the stall status.
- mov A, [endpoint_stall]
- ;Shift left to get an index (0 or 2) to point to data
- ;in the endpoint status table
- asl A
- ;Get the address of the data to send.
- add A, (get_endpoint_status_table - control_read_table)
- ;Send the data.
- jmp SendDescriptor
- SetReport:
- ;The CY7C63000 doesn't support interrupt-mode OUT transfers.
- ;So the host uses Control transfers with Set_Report requests
- ;to get data from the device.
- ;Get the report data.
- ;For debugging: set Port 0, bit 0 =1 to show that we're here.
- ; iord Port0_Data
- ; or a, 1
- ; iowr Port0_Data
- ;Find out how many bytes to read. This value is in WLength.
- ;Save the length in data_count.
- mov A, [wLength]
- mov [data_count], A
- ;Enable receiving data at Endpoint 0 by setting the EnableOuts bit
- ;The bit clears following any Setup or OUT transaction.
- iord USB_Status_Control
- or A, 10h
- ;Clear the StatusOuts bit to disable automatic sending of ACK after
- ;receiving a valid status packet in a Control read (IN) transfer.
- ;Otherwise, the USB engine will respond to a data OUT packet with a Stall.
- and A, F7h
- iowr USB_Status_Control
- ;Now we're ready to receive the report data.
- ;An Endpoint 0 OUT interrupt indicates the arrival of the report data.
- ret
- SetIdle:
- jmp SendStall ; *** not supported ***
- SetProtocol:
- ;Switches between a boot protocol (wValue=0) and report protocol (wValue=1).
- ;This firmware doesn't distinguish between protocols.
- mov A, [wValue]
- mov [protocol_status], A
- call Send0ByteDataPacket
- ret
- GetReport:
- ;Sends a report to the host.
- ;The high byte of wValue contains the report type.
- ;The low byte of wValue contains the report ID.
- ;Not supported (Use interrupt transfers to send data.)
- jmp SendStall
- GetReportDescriptor:
- ;Save the descriptor length
- mov A, (end_hid_report_desc_table - hid_report_desc_table)
- mov [data_count], A
- ;Get the descriptor's starting address.
- mov A, (hid_report_desc_table - control_read_table)
- call SendDescriptor
- ret
- GetIdle:
- ;Not supported
- jmp SendStall
- GetProtocol:
- ;Send the current protocol status.
- ;Send 1 byte.
- mov A, 1
- mov [data_count], A
- ;Get the address of the data to send.
- mov A, (get_protocol_status_table - control_read_table)
- ;Add an index that points to the correct data.
- add A, [protocol_status]
- ;Send the data.
- jmp SendDescriptor
-
- ; Standard Get Descriptor routines
- ;
- ;Send the device descriptor.
- GetDeviceDescriptor:
- ;Get the length of the descriptor
- ;(stored in the first byte in the device descriptor table).
- mov A, 0
- index device_desc_table
- mov [data_count], A
- ;Get the starting address of the descriptor.
- mov A, (device_desc_table - control_read_table)
- ;Send the descriptor.
- jmp SendDescriptor
- GetConfigurationDescriptor:
- ;Send the configuration descriptor.
- ;Get the length of the descriptor.
- mov A, (end_config_desc_table - config_desc_table)
- mov [data_count], A
- ;Get the starting address of the descriptor.
- mov A, (config_desc_table - control_read_table)
- ;Send the descriptor.
- jmp SendDescriptor
- GetStringDescriptor:
- ;Use the string index to find out which string it is.
- mov A, [wValue]
- cmp A, 0h
- jz LanguageString
- cmp A, 01h
- jz ManufacturerString
- cmp A, 02h
- jz ProductString
- ; cmp A, 03h
- ; jz SerialNumString
- ; cmp A, 04h
- ; jz ConfigurationString
- ; cmp A, 05h
- ; jz InterfaceString
- ; No other strings supported
- jmp SendStall
- SendDescriptor:
- ;The starting address of the descriptor is in the accumulator. Save it.
- mov [data_start], A
- ;Get the descriptor length.
- call get_descriptor_length
- ;Send the descriptor.
- call control_read
- ret
- ;Send the requested string.
- ;For each, store the descriptor length in data_count, then send the descriptor.
- LanguageString:
- mov A, (USBStringDescription1 - USBStringLanguageDescription)
- mov [data_count], A
- mov A, (USBStringLanguageDescription - control_read_table)
- jmp SendDescriptor
- ManufacturerString:
- mov A, ( USBStringDescription2 - USBStringDescription1)
- mov [data_count], A
- mov A, (USBStringDescription1 - control_read_table)
- jmp SendDescriptor
- ProductString:
- mov A, ( USBStringDescription3 - USBStringDescription2)
- mov [data_count], A
- mov A, (USBStringDescription2 - control_read_table)
- jmp SendDescriptor
- ;SerialNumString:
- ; mov A, ( USBStringDescription4 - USBStringDescription3)
- ; mov [data_count], A
- ; mov A, (USBStringDescription3 - control_read_table)
- ; jmp SendDescriptor
- ;ConfigurationString:
- ; mov A, ( USBStringDescription5 - USBStringDescription4)
- ; mov [data_count], A
- ; mov A, (USBStringDescription4 - control_read_table)
- ; jmp SendDescriptor
- ;InterfaceString:
- ; mov A, ( USBStringEnd - USBStringDescription5)
- ; mov [data_count], A
- ; mov A, (USBStringDescription5 - control_read_table)
- ; jmp SendDescriptor
- ; HID class Get Descriptor routines
- ;
- GetHIDDescriptor:
- ;Send the HID descriptor.
- ;Get the length of the descriptor.
- mov A, (Endpoint_Descriptor - Class_Descriptor)
- mov [data_count], A
- ;Get the descriptor's starting address.
- mov A, ( Class_Descriptor - control_read_table)
- ;Send the descriptor.
- call SendDescriptor
- ret
- ;======================================================================
- ;USB support routines
- ;======================================================================
- get_descriptor_length:
- ;The host sometimes lies about the number of bytes it
- ;wants from a descriptor.
- ;A request to get a descriptor should return the smaller of the number
- ;of bytes requested or the actual length of the descriptor.
- ;Get the requested number of bytes to send
- mov A, [wLengthHi]
- ;If the requested high byte is >0,
- ;ignore the high byte and use the firmware's value.
- ;(255 bytes is the maximum allowed.)
- cmp A, 0
- jnz use_actual_length
- ;If the low byte =0, use the firmware's value.
- mov A, [wLength]
- cmp A, 0
- jz use_actual_length
- ;If the requested number of bytes => the firmware's value,
- ;use the firmware's value.
- cmp A, [data_count]
- jnc use_actual_length
- ;If the requested number of bytes < the firmware's value,
- ;use the requested number of bytes.
- mov [data_count], A
- use_actual_length:
- ret
- Send0ByteDataPacket:
- ;Send a data packet with 0 bytes.
- ;Use this handshake after receiving an OUT data packet.
- ;Enable responding to IN packets and set Data 0/1 to Data 1.
- mov A, C0h
- iowr USB_EP0_TX_Config
- ;Enable interrupts.
- mov A, [interrupt_mask]
- iowr Global_Interrupt
- WaitForDataToTransfer:
- ;Wait for the data to transfer.
- ;Clear the watchdog timer
- iowr Watchdog
- ;Bit 7 of USB_EP0_TX_Config is cleared when the host acknowledges
- ;receiving the data.
- iord USB_EP0_TX_Config
- and A, 80h
- jnz WaitForDataToTransfer
- ret
- control_read:
- ;Do a Control Read transfer.
- ;The device receives a Setup packet in the Setup stage,
- ;sends 1 or more data packets (IN) in the Data stage,
- ;and receives a 0-length data packet (OUT) in the Status stage.
- ;Before calling this routine, the firmware must set 2 values:
- ;data_start is the starting address of the descriptor to send,
- ;expressed as an offset from the control read table.
- ;data_count is the number of bytes in the descriptor.
- push X
- ;Set the Data 0/1 bit to 0.
- mov A, 00h
- mov [endp0_data_toggle], A
- control_read_data_stage:
- ;Initialize count variables.
- mov X, 00h
- mov A, 00h
- mov [loop_counter], A
- ;Clear the Setup bit.
- iowr USB_EP0_RX_Status
- ;Check the Setup bit.
- iord USB_EP0_RX_Status
- and A, 01h
- ;If not cleared, another setup packet has arrived,
- ;so exit the routine.
- jnz control_read_status_stage
- ;Set the StatusOuts bit to 1 to cause the device to automatically return
- ;ACK in response to a received OUT packet in the Status stage.
- mov A, 08h
- iowr USB_Status_Control
- ;If there is no data to send, prepare a 0-length data packet.
- ;(The host might require a final 0-length packet if the descriptor is
- ;a multiple of 8 bytes.)
- mov A, [data_count]
- cmp A, 00h
- jz dma_load_done
- dma_load_loop:
- ;Copy up to 8 bytes for transmitting into Endpoint 0's buffer
- ;and increment/decrement the various counting variables.
- ;Place the byte to send in the accumulator:
- ;(control_read_table) + (data_start).
- mov A, [data_start]
- index control_read_table
- ;Place the byte in Endpoint 0's buffer.
- mov [X + Endpoint_0], A
- ;Increment the offset of the data being sent.
- inc [data_start]
- ;Increment the offset of Endpoint 0's buffer.
- inc X
- ;Increment the number of bytes stored in the buffer.
- inc [loop_counter]
- ;Decrement the number of bytes left to send.
- dec [data_count]
- ;If the count = 0, there's no more data to load.
- jz dma_load_done
- ;If 8 bytes haven't been loaded into the buffer, get another byte.
- ;If 8 bytes have been loaded, it's the maximum for the transaction,
- ;so send the data.
- mov A, [loop_counter]
- cmp A, 08h
- jnz dma_load_loop
- dma_load_done:
- ;Send the data.
- ;Check the Setup bit.
- ;If it's not 0, another Setup packet has arrived,
- ;so exit the routine.
- iord USB_EP0_RX_Status
- and A, 01h
- jnz control_read_status_stage
- ;Set the bits in the USB_EP0_TX_Config register.
- ;Toggle the Data 0/1 bit.
- mov A, [endp0_data_toggle]
- xor A, 40h
- mov [endp0_data_toggle], A
- ;Enable responding to IN token packets.
- or A, 80h
- ;The low 4 bits hold the number of bytes to send.
- or A, [loop_counter]
- iowr USB_EP0_TX_Config
- ;Enable interrupts
- mov A, [interrupt_mask]
- iowr Global_Interrupt
- wait_control_read:
- ;Clear the watchdog timer
- iowr Watchdog
- ;Wait for the data to transfer and the host to acknowledge,
- ;indicated by Bit 7 = 0.
- iord USB_EP0_TX_Config
- and A, 80h
- ;When all of the transaction's data has transferred,
- ;find out if there is more data to send in the transfer.
- jz control_read_data_stage
- ;Find out if the host has sent an OUT packet to acknowledge
- ;and end the transfer.
- iord USB_EP0_RX_Status
- and A, 02h
- jz wait_control_read
- control_read_status_stage:
- ;The transfer is complete.
- pop X
- mov A, [interrupt_mask]
- iowr Global_Interrupt
- ret
- ;======================================================================
- ;Lookup Tables
- ;Contain the descriptors and the codes for status indicators.
- ;The firmware accesses the information by referencing a specific
- ;table's address as an offset from the control_read_table.
- ;======================================================================
- control_read_table:
- device_desc_table:
- db 12h ; Descriptor length (18 bytes)
- db 01h ; Descriptor type (Device)
- db 10h,01h ; Complies with USB Spec. Release (0110h = release 1.10)
- db 00h ; Class code (0)
- db 00h ; Subclass code (0)
- db 00h ; Protocol (No specific protocol)
- db 08h ; Maximum packet size for Endpoint 0 (8 bytes)
- db 25h,09h ; Vendor ID (Lakeview Research, 0925h)
- db 34h,12h ; Product ID (1234)
- db 01h,00h ; Device release number (0001)
- db 01h ; Manufacturer string descriptor index
- db 02h ; Product string descriptor index
- db 00h ; Serial Number string descriptor index (None)
- db 01h ; Number of possible configurations (1)
- end_device_desc_table:
- config_desc_table:
- db 09h ; Descriptor length (9 bytes)
- db 02h ; Descriptor type (Configuration)
- db 22h,00h ; Total data length (34 bytes)
- db 01h ; Interface supported (1)
- db 01h ; Configuration value (1)
- db 00h ; Index of string descriptor (None)
- db 80h ; Configuration (Bus powered)
- db 32h ; Maximum power consumption (100mA)
- Interface_Descriptor:
- db 09h ; Descriptor length (9 bytes)
- db 04h ; Descriptor type (Interface)
- db 00h ; Number of interface (0)
- db 00h ; Alternate setting (0)
- db 01h ; Number of interface endpoint (1)
- db 03h ; Class code ()
- db 00h ; Subclass code ()
- db 00h ; Protocol code ()
- db 00h ; Index of string()
- Class_Descriptor:
- db 09h ; Descriptor length (9 bytes)
- db 21h ; Descriptor type (HID)
- db 00h,01h ; HID class release number (1.00)
- db 00h ; Localized country code (None)
- db 01h ; # of HID class dscrptr to follow (1)
- db 22h ; Report descriptor type (HID)
- ; Total length of report descriptor
- db (end_hid_report_desc_table - hid_report_desc_table),00h
- Endpoint_Descriptor:
- db 07h ; Descriptor length (7 bytes)
- db 05h ; Descriptor type (Endpoint)
- db 81h ; Encoded address (Respond to IN, 1 endpoint)
- db 03h ; Endpoint attribute (Interrupt transfer)
- db 06h,00h ; Maximum packet size (6 bytes)
- db 0Ah ; Polling interval (10 ms)
-
- end_config_desc_table:
- ;----------------------------------------------------------------------
- ;The HID-report descriptor table
- ;----------------------------------------------------------------------
- hid_report_desc_table:
- db 06h, A0h, FFh ; Usage Page (vendor defined) FFA0
- db 09h, 01h ; Usage (vendor defined)
- db A1h, 01h ; Collection (Application)
- db 09h, 02h ; Usage (vendor defined)
- db A1h, 00h ; Collection (Physical)
- db 06h, A1h, FFh ; Usage Page (vendor defined)
- ;The input report
- db 09h, 03h ; usage - vendor defined
- db 09h, 04h ; usage - vendor defined
- db 15h, 80h ; Logical Minimum (-128)
- db 25h, 7Fh ; Logical Maximum (127)
- db 35h, 00h ; Physical Minimum (0)
- db 45h, FFh; Physical Maximum (255)
- ; db 66h, 00h, 00h; Unit (None (2 bytes))
- db 75h, 08h ; Report Size (8) (bits)
- db 95h, 02h ; Report Count (2) (fields)
- db 81h, 02h ; Input (Data, Variable, Absolute)
- ;The output report
- db 09h, 05h ; usage - vendor defined
- db 09h, 06h ; usage - vendor defined
- db 15h, 80h ; Logical Minimum (-128)
- db 25h, 7Fh ; Logical Maximum (127)
- db 35h, 00h ; Physical Minimum (0)
- db 45h, FFh ; Physical Maximum (255)
- ; db 66h, 00h, 00h; Unit (None (2 bytes))
- db 75h, 08h ; Report Size (8) (bits)
- db 95h, 02h ; Report Count (2) (fields)
- db 91h, 02h ; Output (Data, Variable, Absolute)
- db C0h ; End Collection
- db C0h ; End Collection
- end_hid_report_desc_table:
- ;----------------------------------------------------------------------
- ;String Descriptors
- ;----------------------------------------------------------------------
- ;Define the strings
- ; string 0
- USBStringLanguageDescription:
- db 04h ; Length
- db 03h ; Type (3=string)
- db 09h ; Language: English
- db 04h ; Sub-language: US
- ; string 1
- ;The Length value for each string =
- ;((number of characters) * 2) + 2
- USBStringDescription1: ; IManufacturerName
- db 1Ah ; Length
- db 03h ; Type (3=string)
- dsu "USB Complete" ;
- ; string 2
- USBStringDescription2: ; IProduct
- db 16h ; Length
- db 03h ; Type (3=string)
- dsu "HID Sample" ;
- ;string 3
- ;If the firmware contains a serial number, it must be unique
- ;for each device or the devices may not enumerate properly.
- USBStringDescription3: ; serial number
- ; string 4
- ;USBStringDescription4: ; configuration string descriptor
- ; db 16h ; Length
- ; db 03h ; Type (3=string)
- ; dsu "Sample HID" ;
- ;string 5
- ;USBStringDescription5: ; configuration string descriptor
- ; db 32h ; Length
- ; db 03h ; Type (3=string)
- ; dsu "EndPoint1 Interrupt Pipe" ;
- USBStringEnd:
- ;----------------------------------------------------------------------
- ;Status information.
- ;The status can apply to the device or an interface or endpoint.
- ;An index selects the correct value.
- ;----------------------------------------------------------------------
- get_dev_status_table:
- db 00h, 00h ; remote wakeup disabled, bus powered
- db 02h, 00h ; remote wakeup enabled, bus powered
- get_interface_status_table:
- db 00h, 00h ; always return both bytes zero
- get_endpoint_status_table:
- db 00h, 00h ; not stalled
- db 01h, 00h ; stalled
- get_configuration_status_table:
- db 00h ; not configured
- db 01h ; configured
- get_protocol_status_table:
- db 00h ; boot protocol
- db 01h ; report protocol