usbhidio.asm
上传用户:lyzyl198
上传日期:2008-05-19
资源大小:174k
文件大小:54k
源码类别:

C#编程

开发平台:

C#

  1. ;Filename: usbhidio.asm
  2. ;Version: 1.3
  3. ;Date: 11/5/99
  4. ;Copyright 1999 by Jan Axelson (jan@lvr.com)
  5. ;
  6. ;Chip: Cypress Semiconductor CY7C63001 USB Microcontroller
  7. ;Assembler: cyasm.exe
  8. ;Purpose: demonstrates USB communications with an HID-class device
  9. ;Description:
  10. ;Handles all required standard USB and HID-class requests.
  11. ;Receives data from the host in output reports
  12. ;using interrupt transfers on Endpoint 1.
  13. ;Sends data to the host in input reports
  14. ;using control transfers on Endpoint 0.
  15. ;(The chip doesn't support OUT transfers on Endpoint 1.)
  16. ;I used Cypress Semiconductor's js50.asm joystick example code as a base 
  17. ;in creating this program.
  18. ;The companion host software is the Visual-Basic project usbhidio.vbp.
  19. ;For more information, visit Lakeview Research at http://www.lvr.com .
  20. ;Send comments, bug reports, etc. to jan@lvr.com .
  21. ;Changes:
  22. ;V1.3: 11/20/99
  23. ;The length of the string descriptors is now correct.
  24. ;(Thanks, John Hyde)
  25. ;Changed the control_read routine to prevent error when sending a 
  26. ;multiple of 8 bytes.
  27. ;(Thanks, Dave Wright)
  28. ;V1.2:
  29. ;added watchdog resets in wait loops,
  30. ;took out the watchdog reset in the 1-msec. timer ISR.
  31. ;V1.1:
  32. ;Clears the watchdog only in the main routine
  33. ;(so the watchdog will detect if the main routine crashes).
  34. ;Additions to the comments.
  35. ;V1.0:
  36. ;Clears the Watchdog timer on 1-msec. interrupt.
  37. ;(Not needed on the development board, but needed for stand-alone.)
  38. ;The Endpoint 1 ISR now sets bit 7 of Endpoint 1 TX config to 1.
  39. ;(The bit is cleared on EP1 interrupt.)
  40. ;======================================================================
  41. ;assembler directives (equates)
  42. ;======================================================================
  43. ;----------------------------------------------------------------------
  44. ;I/O registers
  45. ;----------------------------------------------------------------------
  46. ;I/O ports
  47. Port0_Data:            equ     00h      ; GPIO data port 0
  48. Port1_Data:            equ     01h      ; GPIO data port 1
  49. Port0_Interrupt:       equ     04h      ; Interrupt enable for port 0
  50. Port1_Interrupt:       equ     05h      ; Interrupt enable for port 1
  51. Port0_Pullup:          equ     08h      ; Pullup resistor control for port 0
  52. Port1_Pullup:          equ     09h      ; Pullup resistor control for port 1
  53. ;USB ports
  54. USB_EP0_TX_Config:      equ     10h     ; USB EP0 transmit configuration
  55. USB_EP1_TX_Config:      equ     11h     ; USB EP1 transmit configuration
  56. USB_Device_Address:     equ     12h     ; USB device address assigned by host
  57. USB_Status_Control:     equ     13h     ; USB status and control register
  58. USB_EP0_RX_Status:      equ     14h     ; USB EP0 receive status
  59. ;Control ports
  60. Global_Interrupt:       equ     20h     ; Global interrupt enable
  61. Watchdog:               equ     21h     ; clear watchdog Timer
  62. Timer:                  equ     23h     ; free-running Timer
  63. ;GPIO Isink registers
  64. Port0_Isink:            equ     30h
  65. Port0_Isink0:           equ     30h
  66. Port0_Isink1:           equ     31h
  67. Port0_Isink2:           equ     32h
  68. Port0_Isink3:           equ     33h
  69. Port0_Isink4:           equ     34h
  70. Port0_Isink5:           equ     35h
  71. Port0_Isink6:           equ     36h
  72. Port0_Isink7:           equ     37h
  73. Port1_Isink:            equ     38h
  74. Port1_Isink0:           equ     38h
  75. Port1_Isink1:           equ     39h
  76. Port1_Isink2:           equ     3Ah
  77. Port1_Isink3:           equ     3Bh
  78. ;Control port
  79. Status_Control:         equ     FFh
  80. ;----------------------------------------------------------------------
  81. ;Register bit values
  82. ;----------------------------------------------------------------------
  83. ;CPU Status and Control (Status_Control)
  84. RunBit:                 equ     1h     ; CPU Run bit
  85. USBReset:               equ    20h     ; USB Bus Reset bit
  86. WatchDogReset:          equ    40h     ; Watchdog Reset bit
  87. ; USB EP1 transmit configuration (USB_EP1_TX_Config)
  88. DataToggle:               equ     40h     ; Data 0/1 bit
  89. DISABLE_REMOTE_WAKEUP:  equ   0         ; bit[1] = 0
  90. ENABLE_REMOTE_WAKEUP:   equ   2         ; bit[1] = 1
  91. ;----------------------------------------------------------------------
  92. ;Interrupt masks
  93. ;----------------------------------------------------------------------
  94. ;The timer-only mask enables the 1-millisecond timer interrupt.
  95. TIMER_ONLY:               equ      4h
  96. ;The enumerate mask enables the following interrupts:
  97. ;1-millisecond timer, USB Endpoint 0
  98. ENUMERATE_MASK:          equ     0Ch
  99. ;The runtime mask enables the following interrupts:
  100. ;1-millisecond timer, USB Endpoint 0, USB Endpoint 1, GPIO
  101. RUNTIME_MASK:          equ     5Ch
  102. ;----------------------------------------------------------------------
  103. ; USB Constants
  104. ; from the USB Spec v1.1
  105. ;----------------------------------------------------------------------
  106. ;standard request codes
  107. get_status:             equ   0
  108. clear_feature:          equ   1
  109. set_feature:            equ   3
  110. set_address:            equ   5
  111. get_descriptor:         equ   6
  112. set_descriptor:         equ   7
  113. get_configuration:      equ   8
  114. set_configuration:      equ   9
  115. get_interface:          equ  10
  116. set_interface:          equ  11
  117. synch_frame:            equ  12
  118. ; standard descriptor types
  119. device:              equ  1
  120. configuration:       equ  2
  121. string:              equ  3
  122. interface:           equ  4
  123. endpoint:            equ  5
  124. ; standard feature selectors
  125. endpoint_stalled:       equ  0              ; recipient endpoint
  126. device_remote_wakeup:   equ  1              ; recipient device
  127. ;----------------------------------------------------------------------
  128. ;HID-class descriptors
  129. ;from HID Class Definition v1.1 Draft
  130. ;----------------------------------------------------------------------
  131. ;Class-specific descriptor types from section 7.1 Standard Requests
  132. HID:                    equ  21h
  133. report:                 equ  22h
  134. physical:               equ  23h
  135.   
  136. ;Class-specific request codes from section 7.2 Class Specific Requests
  137. get_report:             equ   1
  138. get_idle:               equ   2
  139. get_protocol:           equ   3
  140. set_report:             equ   9
  141. set_idle:               equ  10
  142. set_protocol:           equ  11
  143. ;----------------------------------------------------------------------
  144. ;USB buffer bytes
  145. ;----------------------------------------------------------------------
  146. ;Control Endpoint 0 buffer
  147. Endpoint_0:             equ  70h        ; control endpoint
  148. Endpoint0_Byte0:        equ  70h        ; Endpoint 0, byte 0
  149. Endpoint0_Byte1:        equ  71h        ; Endpoint 0 byte 1
  150. Endpoint0_Byte2:        equ  72h        ; Endpoint 0 byte 2
  151. Endpoint0_Byte3:        equ  73h        ; Endpoint 0 byte 3
  152. Endpoint0_Byte4:        equ  74h        ; Endpoint 0 byte 4
  153. Endpoint0_Byte5:        equ  75h        ; Endpoint 0 byte 5
  154. Endpoint0_Byte6:        equ  76h        ; Endpoint 0 byte 6
  155. Endpoint0_Byte7:        equ  77h        ; Endpoint 0 byte 7
  156. ;Endpoint 0 SETUP packet bytes
  157. bmRequestType:          equ  70h
  158. bRequest:               equ  71h
  159. wValue:                 equ  72h        ; default wValue (8 bits)
  160. wValueHi:               equ  73h
  161. wIndex:                 equ  74h        ; default wIndex (8 bits)
  162. wIndexHi:               equ  75h
  163. wLength:                equ  76h        ; default wLength (8 bits)
  164. wLengthHi:              equ  77h
  165. ;Endpoint 1 buffer
  166. endpoint_1:             equ  78h
  167. Endpoint1_Byte0:        equ  78h        ; Endpoint 1, byte 0
  168. Endpoint1_Byte1:        equ  79h        ; Endpoint 1 byte 1
  169. Endpoint1_Byte2:        equ  7Ah        ; Endpoint 1 byte 2
  170. Endpoint1_Byte3:        equ  7Bh        ; Endpoint 1 byte 3
  171. Endpoint1_Byte4:        equ  7Ch        ; Endpoint 1 byte 4
  172. Endpoint1_Byte5:        equ  7Dh        ; Endpoint 1 byte 5
  173. Endpoint1_Byte6:        equ  7Eh        ; Endpoint 1 byte 6
  174. Endpoint1_Byte7:        equ  7Fh        ; Endpoint 1 byte 7
  175. ;----------------------------------------------------------------------
  176. ; Variables stored in data memory
  177. ;----------------------------------------------------------------------
  178. ;USB status
  179. remote_wakeup_status:   equ  30h          ;0=disabled, 2-enabled
  180. configuration_status:   equ  31h          ;0=unconfigured, 1=configured
  181. ;idle_status:           equ  33h          ;support SetIdle and GetIdle
  182. protocol_status:        equ  34h          ;0=boot protocol, 1=report protocol
  183. ;Other variables:
  184. suspend_counter:        equ  35h          ;number of idle bus milliseconds 
  185. loop_temp:              equ  37h          ;temporary loop variable
  186. start_send:             equ  32h          ;0=false, 1=true
  187. ;Received data:
  188. Data_Byte0:               equ  38h
  189. Data_Byte1:               equ  39h
  190. Data_Byte2:               equ  3Ah
  191. Data_Byte3:               equ  3Bh
  192. Data_Byte4:               equ  3Ch
  193. Data_Byte5:               equ  3Dh
  194. Data_Byte6:               equ  3Eh
  195. Data_Byte7:               equ  3Fh
  196. temp:                   equ  25h
  197. start_time:             equ  21h
  198. testbit:                equ  22h
  199. interrupt_mask:         equ  20h
  200. endp0_data_toggle:      equ  23h
  201. loop_counter:           equ  24h
  202. data_start:             equ  27h
  203. data_count:             equ  28h
  204. endpoint_stall:         equ  29h
  205. ;======================================================================
  206. ;interrupt vectors
  207. ;======================================================================
  208. org  00h                ; Reset vector; begin here after a reset.
  209. jmp  Reset
  210. org  02h                ; 128-microsecond interrupt
  211. jmp  DoNothing_ISR
  212. org  04h                ; 1024-millisecond interrupt 
  213. jmp  One_mSec_ISR
  214. org  06h                ; Endpoint 0 interrupt 
  215. jmp  USB_EP0_ISR
  216. org  08h                ; Endpoint 1 interrupt 
  217. jmp  USB_EP1_ISR
  218. org  0Ah                ; reserved interrupt 
  219. jmp  Reset
  220. org  0Ch                ; general purpose I/O interrupt 
  221. jmp  GPIO_ISR           ; not used
  222. org  0Eh                ; Wakeup_ISR or resume interrupt 
  223. jmp  DoNothing_ISR      ; not used
  224. ORG  10h
  225. ;======================================================================
  226. ;Interrupt routines
  227. ;======================================================================
  228. ;----------------------------------------------------------------------
  229. ; 128-microsecond interrupt, Cext
  230. ; Unused. If this interrupt occurs, just push the accumulator (because
  231. ; ipret pops it) and re-enable the interrupts.
  232. ;----------------------------------------------------------------------
  233. DoNothing_ISR:
  234.      push A
  235.      ;Enable interrupts and return
  236.      mov A,[interrupt_mask]
  237.      ipret Global_Interrupt
  238. ;----------------------------------------------------------------------
  239. ; 1-millisecond interrupt
  240. ; Check to see if the chip is in suspend mode and take appropriate action.
  241. ; Copy values to Endpoint 1's buffer for sending.
  242. ;----------------------------------------------------------------------
  243. One_mSec_ISR:
  244.      push A
  245. iowr Watchdog
  246. ;Find out if enumeration is complete.
  247. ;If enumerating is in progress, loop_temp = 0.
  248.      mov A, [loop_temp]
  249.      cmp A, 0h
  250. ;If enumeration is still in progress, jump.
  251.      jz not_main
  252. ;Enumeration has ended, so decrement the loop counter
  253. ;(so it no longer = 0).
  254.      dec [loop_temp]
  255. not_main:                         
  256. ;Check for bus activity.
  257.      iord USB_Status_Control
  258.      and A, 01h
  259.      cmp A,0h
  260. ;If no bus activity, increment the suspend counter.
  261.      jz Inc_counter
  262. ;If bus activity detected, clear the bus-activity bit,
  263.      iord USB_Status_Control
  264.      and A, 0FEh
  265.      iowr USB_Status_Control
  266. ;and clear the suspend counter.
  267.      mov A, 0h
  268.      mov [suspend_counter], A
  269.      jmp Suspend_end
  270. Inc_counter:
  271. ;Keep track of the amount of time with no bus activity.
  272.      inc [suspend_counter]
  273. ;Get the number of milliseconds the bus has been idle.
  274.      mov A, [suspend_counter]
  275. ;Has it been 3 milliseconds?
  276.      cmp A, 03h
  277. ;If no, there's nothing else to do.
  278.      jnz Suspend_end
  279. ;If yes, put the chip in Suspend mode.
  280. ;Clear the Suspend counter.
  281.      mov A, 0h
  282.      mov [suspend_counter], A
  283. ;Enable pullups on Port 1; disable the output DAC.
  284.      mov A, 0h
  285.      iowr Port1_Pullup
  286.      mov A, 0ffh
  287.      iowr Port1_Data
  288. ;Set the Suspend bit. 
  289.      iord Status_Control
  290.      or A, 08h
  291.      iowr Status_Control
  292. ;The chip is now in Suspend mode. 
  293. ;On exiting Suspend mode, the chip will begin 
  294. ;executing instructions here:
  295.      nop     
  296. ;Disable pullups on Port 1. Enable the output DAC.
  297.      mov A, 0ffh
  298.      iowr Port1_Pullup
  299.      mov A, 0h
  300.      iowr Port1_Data
  301. Suspend_end:
  302. ;Is endpoint 1 enabled?
  303.      iord USB_EP1_TX_Config
  304.      cmp A,0
  305. ;If no, do nothing.
  306.      jz Select
  307. ;If yes, is start_send = 1?
  308. ;(Start_send adds a short delay after enumeration.)
  309.      mov A, [start_send]
  310.      cmp A, 01h
  311. ;If no, do nothing
  312.      jnz Select
  313. ;If yes, send data:
  314.      jmp send_value
  315. send_value:
  316. ;Copies values from RAM into Endpoint 1's buffer
  317. ;and enables sending the bytes on the next poll.
  318. ;disable Endpoint 1 interrupts
  319.      mov A,[interrupt_mask]
  320.      and A, EFh
  321.      mov [interrupt_mask],A
  322.      iowr Global_Interrupt
  323. ;Copy values from RAM to Endpoint 1's buffer for transmitting to the host.
  324. ;Two bytes:
  325.      mov A, [Data_Byte0]
  326.      mov [Endpoint1_Byte0], A
  327.      mov A, [Data_Byte1]
  328.      mov [Endpoint1_Byte1], A
  329. ;Add more bytes if the report format specifies it:
  330. ;     mov A, [Data_Byte2]
  331. ;     mov [Endpoint1_Byte2], A
  332. ;     mov A, [Data_Byte3]
  333. ;     mov [Endpoint1_Byte3], A
  334. ;     mov A, [Data_Byte4]
  335. ;     mov [Endpoint1_Byte4], A
  336. ;     mov A, [Data_Byte5]
  337. ;     mov [Endpoint1_Byte5], A
  338. ;     mov A, [Data_Byte6]
  339. ;     mov [Endpoint1_Byte6], A
  340. ;     mov A, [Data_Byte7]
  341. ;     mov [Endpoint1_Byte7], A
  342. ;Other things to try:
  343. ;Set the value at Port 0 to equal byte 0 in Endpoint 1's buffer:
  344. ;     iord Port0_Data
  345. ;     mov [Endpoint1_Byte0], A
  346. ;Or set a value here and copy to Endpoint 1's buffer, byte 1:
  347. ;     mov A, A5h
  348. ;      mov [Endpoint1_Byte1], A
  349. ;Configure Endpoint 1's transmit register 
  350. ;so that the bytes will transmit on the next poll.
  351.      iord USB_EP1_TX_Config
  352. ;Don't change the Data 0/1 bit.
  353.      and A,40h
  354. ;Set bits 4 and 7 to 1 enable transmitting.
  355. ;The low nibble is the number of data bytes (2).
  356.      or A,92h
  357.      iowr USB_EP1_TX_Config
  358. Select:
  359. ;Enable Endpoint 1 interrupts.
  360.      mov A,[interrupt_mask]
  361.      or A, 10h
  362.      mov [interrupt_mask],A
  363.      ipret Global_Interrupt
  364. ;----------------------------------------------------------------------
  365. ;GPIO interrupt
  366. ;Can be configured to trigger when a port bit toggles.
  367. ;Unused here.
  368. ;----------------------------------------------------------------------
  369. GPIO_ISR:
  370.      push A
  371.      push X
  372.      pop X
  373.      mov [interrupt_mask],A
  374.      ipret Global_Interrupt
  375. ;----------------------------------------------------------------------
  376. ;Endpoint 1 ISR
  377. ;Endpoint 1 can do IN (device to host) transfers only.
  378. ;This interrupt triggers when the host acknowledges
  379. ;receiving data from Endpoint 1.
  380. ;The ISR toggles the data 0/1 bit for the next transaction and
  381. ;sets the EnableRespondToIN bit so the chip will respond to the 
  382. ;next poll of the endpoint.
  383. ;----------------------------------------------------------------------
  384. USB_EP1_ISR:
  385.      push A
  386. ;Toggle the data 0/1 bit so it's correct for the next transaction.
  387.      iord USB_EP1_TX_Config  
  388.      xor A,40h
  389. ;The interrupt clears the EnableRespondToIN bit (bit 7) in the TX Config.
  390. ;Set this bit to 1 so data will go out on the next poll.
  391. ;This will ensure that a ReadFile API call in a Windows application
  392. ;won't hang, waiting for the device to send something.
  393.      or A, 92h
  394.      iowr USB_EP1_TX_Config
  395. ;Enable interrupts and return.
  396.      mov A, [interrupt_mask]
  397.      ipret Global_Interrupt
  398. ;----------------------------------------------------------------------
  399. ; Reset processing
  400. ; Triggers on Reset or "reserved" interrupt.
  401. ;To be safe, initialize everything.
  402. ;----------------------------------------------------------------------
  403. Reset:
  404. ;Place the data stack pointer at the lowest address of Endpoint 0's buffer.
  405. ;This keeps the stack from writing over the USB buffers.
  406. ;The USB buffers are in high RAM;
  407. ;the data stack pointer pre-decrements on a Push instruction.
  408.      mov A, Endpoint_0
  409.      swap A, dsp
  410. ;Initialize to FFh
  411.      mov A, 0ffh
  412.      iowr Port0_Data                 ; output ones to port 0
  413.      iowr Port1_Pullup               ; disable port 1 pullups
  414.                                      ; select rising edge interrupts
  415.      iowr Port1_Isink0               ; maximum isink current Port1 bit 0
  416.      iowr Port1_Isink1               ; maximum isink current Port1 bit 1
  417.      iowr Port1_Isink2               ; maximum isink current Port1 bit 2
  418.      iowr Port1_Isink3               ; maximum isink current Port1 bit 3
  419. ;Initialize to 00h
  420.      mov A, 0h
  421.      iowr Port1_Data                 ; output zeros to port 1
  422.      iowr Port0_Interrupt            ; disable port 0 interrupts
  423.      iowr Port0_Pullup               ; enable port 0 pullups
  424.      iowr Port0_Isink0               ; minimum sink current Port0 bit 0
  425.      iowr Port0_Isink1               ; minimum sink current Port0 bit 1
  426.      iowr Port0_Isink2               ; minimum sink current Port0 bit 2
  427.      iowr Port0_Isink3               ; minimum sink current Port0 bit 3
  428.      iowr Port0_Isink4               ; minimum sink current Port0 bit 4
  429.      iowr Port0_Isink5               ; minimum sink current Port0 bit 5
  430.      iowr Port0_Isink6               ; minimum sink current Port0 bit 6
  431.      iowr Port0_Isink7               ; minimum sink current Port0 bit 7
  432.      mov [Endpoint1_Byte0],A
  433.      mov [Endpoint1_Byte1],A
  434.      mov [Endpoint1_Byte2],A
  435.      mov [endpoint_stall], A
  436.      mov [remote_wakeup_status], A
  437.      mov [configuration_status], A
  438.      mov [loop_temp], A
  439.      mov [start_send], A
  440.      iowr Watchdog                   ; clear watchdog timer
  441. ;Initialize values to transmit at Endpoint 1.
  442. ;     mov A, A5h
  443. ;     mov [Data_Byte0], A
  444. ;     mov A, F0h
  445. ;     mov [Data_Byte1], A
  446. ;Enable Port 1, bit 0 interrupts.
  447. ;     mov A, 01h
  448. ;     iowr Port1_Interrupt
  449. ;
  450. ;Test what kind of reset occurred: bus or watchdog?
  451.      iord Status_Control
  452. ;Was it a bus reset?
  453.      and A, USBReset
  454. ;If yes, jump to handle it.
  455.      jnz BusReset
  456.      iord Status_Control
  457. ;Was it a watchdog reset?
  458.      and A, WatchDogReset
  459. ;If no, continue to wait for a bus reset
  460.      jz suspendReset
  461. ;
  462. ;Watchog reset:
  463. ;A watchdog reset means that the watchdog timer
  464. ;wasn't cleared for 8.192 milliseconds.
  465. ;Wait for a bus reset to bring the system alive again.
  466. ;Enable 1-millisecond interrupt only
  467.      mov A, TIMER_ONLY
  468.      mov [interrupt_mask],A
  469.      iowr Global_Interrupt
  470. ;Wait for a bus reset.
  471. WatchdogHandler:
  472.      jmp WatchdogHandler
  473. suspendReset:
  474. ;Return to suspend mode to wait for a USB bus reset.
  475.      mov A, 09h
  476.      iowr Status_Control
  477.      nop
  478.      jmp suspendReset
  479. BusReset:
  480. ;Clear all reset bits.
  481. ;Set bit 0 (the run bit).
  482.      mov A, RunBit
  483.      iowr Status_Control
  484. ;Set up for enumeration (Endpoint 0 and 1-millisecond interrupts enabled)
  485.      mov A, ENUMERATE_MASK
  486.      mov [interrupt_mask],A
  487.      iowr Global_Interrupt
  488. wait:
  489. ;Wait until configured.
  490.      iord USB_EP1_TX_Config
  491.      cmp A, 0
  492. ;Clear the watchdog timer
  493.      iowr Watchdog
  494. ;If not configured, continue to wait.
  495.      jz wait     
  496. ;When configured, initialize loop_temp.
  497. ;Loop_temp adds a delay in the start of transmission of data.
  498. ;The chip will respond to the first IN packet no sooner than 
  499. ;230 milliseconds after enumeration is complete.
  500. ;The delay was included in Cypress' joystick code to prevent problems 
  501. ;that occurred when power cycled off and on or the joystick was plugged
  502. ;in before the host powered up.
  503. ;I've left it in because it does no harm and 
  504. ;other hardware might have similar behavior.
  505. ;During the delay, the chip sends a NAK in response to any IN packet.
  506.      mov A, 0ffh
  507.      mov [loop_temp], A
  508. ;Enable endpoint 1
  509.      iord USB_EP1_TX_Config
  510.      or A, 92h
  511.      iowr USB_EP1_TX_Config
  512. ;======================================================================
  513. ; The main program loop.
  514. ;======================================================================
  515. main:
  516. ;Find out if the loop_temp delay has timed out.
  517. ;Loop_temp =0 if not timed out, FFh if timed out.
  518.      mov A, [loop_temp]
  519.      cmp A, 0Ah
  520. ;If no, don't enable transmitting.
  521.      jnc no_set
  522. ;If yes, enable transmitting.
  523.      mov A, 01h
  524.      mov [start_send], A
  525. no_set:
  526. ;Clear the watchdog timer.
  527. ;This has to be done at least once every 8 milliseconds!
  528.      iowr Watchdog
  529.      iord Port0_Data
  530. nochange:
  531.      jmp main
  532. ;----------------------------------------------------------------------
  533. ;The Endpoint 0 ISR supports the control endpoint.
  534. ;This code enumerates and configures the hardware.
  535. ;It also responds to Set Report requests that receive data from the host.
  536. ;----------------------------------------------------------------------
  537. USB_EP0_ISR:
  538.      push A
  539.      iord USB_EP0_RX_Status
  540. ;Has a Setup packet been received?
  541.      and A, 01h
  542. ;If no, find out if it's an OUT packet.
  543.      jz check_for_out_packet
  544. ;If yes, handle it.
  545. ;Disable Endpoint 0 interrupts.
  546.      mov A,[interrupt_mask]
  547.      and A, 0F7h
  548.      mov [interrupt_mask], A
  549.      iowr Global_Interrupt
  550. ;Find out what the Setup packet contains and handle the request.
  551.       call StageOne
  552. ;Re-enable Endpoint 0 interrupts.
  553.      mov A, [interrupt_mask]
  554.      or A, 08h
  555.      mov [interrupt_mask], A
  556.      jmp done_with_packet
  557. check_for_out_packet:
  558.      iord USB_EP0_RX_Status
  559. ;Is it an OUT packet?
  560.      and A, 02h
  561. ;If no, ignore it.
  562.      jz done_with_packet
  563. ;If yes, process the received data.
  564. ;Disable Endpoint 0 interrupts.
  565.      mov A,[interrupt_mask]
  566.      and A, 0F7h
  567.      mov [interrupt_mask], A
  568.      iowr Global_Interrupt
  569. ;For debugging: set Port 0, bit 1 to show that we're here.
  570. ;    iord Port0_Data
  571. ;    or a, 2
  572. ;    iowr Port0_Data
  573. ;Read the first byte in the buffer
  574.      mov a, [Endpoint_0]
  575. ;For debugging: if the first byte =12h, bring Port 0, bit 0 high
  576. ;      cmp a, 12h
  577. ;      jnz not_a_match
  578. ;      iord Port0_Data
  579. ;      or a, 4
  580. ;      iowr Port0_Data
  581. not_a_match:
  582. ;For debugging, add 1 to each byte read
  583. ;and copy the bytes to RAM.
  584. ;These bytes will be sent back to the host.
  585.       push X
  586.       ;data_count holds the number of bytes left to read.
  587.       ;X holds the index of the address to read
  588.       ;and the index of the address to store the received data.
  589.       ;Initialize the X register.
  590.       mov X, 0
  591.       
  592.       Get_Received_Data:
  593.       ;Find out if there are any bytes to read.
  594.       mov A, 0
  595.       cmp A, [data_count]
  596.       ;Jump if nothing to read.
  597.       jz DoneWithReceivedData
  598.       ;Get a byte.
  599.       mov A, [X + Endpoint_0]
  600.       ;For debugging, increment the received value.
  601.       ;(Endpoint 1 will send it back to the host.)
  602.       ;If the value is 255, reset to 0.
  603.       ;Otherwise increment it.
  604.       cmp A, 255
  605.       jz ResetToZero
  606.       inc A
  607.       jmp NewValueSet
  608.       ResetToZero:
  609.       mov A, 0
  610.       NewValueSet:
  611.       ;Save the value.
  612.       mov [X + Data_Byte0], A
  613.       ;Decrement the number of bytes left to read.
  614.       dec [data_count]
  615.       ;Increment the address to read.
  616.       inc X
  617.       ;Do another
  618.       jmp Get_Received_Data
  619.       DoneWithReceivedData:
  620.       pop X
  621. ;For debugging, set Port 0 to match the value written.
  622. ;     iowr Port0_Data
  623. ;Handshake by sending a 0-byte data packet.
  624. call Send0ByteDataPacket
  625. done_with_packet:
  626. ;Re-enable Endpoint 0 interrupts.
  627.      mov A,[interrupt_mask]
  628.      or A, 08h
  629.      mov [interrupt_mask], A
  630.      ipret Global_Interrupt
  631. ;========================================================================
  632. ;Control transfers
  633. ;========================================================================
  634. ;------------------------------------------------------------------------
  635. ;Control transfer, stage one.
  636. ;Find out whether the request is a standard device or HID-class request,
  637. ;the direction of data transfer, 
  638. ;and whether the request is to a device, interface, or endpoint.
  639. ;(from Table 9.2 in the USB spec)
  640. ;------------------------------------------------------------------------
  641. StageOne:
  642. ;Clear the Setup flag
  643.      mov A, 00h
  644.      iowr USB_EP0_RX_Status
  645. ;Set the StatusOuts bit to cause auto-handshake after receiving a data packet.
  646.      mov A, 8
  647.      iowr USB_Status_Control
  648. ;bmRequestType contains the request.
  649.       mov A, [bmRequestType]
  650. ;Standard device requests. From the USB spec.
  651. ; host to device requests
  652.         cmp A, 00h
  653.         jz RequestType00                 ; bmRequestType = 00000000 device
  654. ;       cmp A, 01h                       *** not required ***  
  655. ;       jz RequestType01                 ; bmRequestType = 00000001 interface
  656.         cmp A, 02h              
  657.         jz RequestType02                 ; bmRequestType = 00000010 endpoint
  658.         cmp A, 80h             
  659. ; device to host requests
  660.         jz RequestType80                 ; bmRequestType = 10000000 device
  661.         cmp A, 81h
  662.         jz RequestType81                 ; bmRequestType = 10000001 interface
  663.         cmp A, 82h
  664.         jz RequestType82                 ; bmRequestType = 10000010 endpoint
  665. ;HID-class device requests. From the HID spec
  666. ; host to device requests
  667.         cmp A, 21h
  668.         jz RequestType21                 ; bmRequestType = 00100001 interface
  669.         cmp A, 22h                       ; *** not in HID spec ***
  670.         jz RequestType22                 ; bmRequestType = 00100010 endpoint
  671. ; device to host requests
  672.         cmp A, A1h
  673.         jz RequestTypeA1                 ; bmRequestType = 10100001 interface
  674. ; Stall unsupported requests
  675. SendStall:
  676.       mov A, A0h
  677.      iowr USB_EP0_TX_Config
  678.       ret
  679. ;----------------------------------------------------------------------
  680. ;Control transfer, stage two
  681. ;Find out which request it is.
  682. ;----------------------------------------------------------------------
  683. ;Host to device with device as recipient
  684. RequestType00:
  685. ;The Remote Wakeup feature is disabled on reset.
  686.      mov A, [bRequest]     ; load bRequest
  687. ; Clear Feature                      bRequest = 1
  688.      cmp A, clear_feature
  689.      jz ClearRemoteWakeup 
  690. ; Set Feature                     bRequest = 3
  691.      cmp A, set_feature
  692.      jz SetRemoteWakeup
  693. ; Set the device address to a non-zero value.
  694. ; Set Address                     bRequest = 5
  695.      cmp A, set_address
  696.      jz SetAddress
  697. ; Set Descriptor is optional.
  698. ; Set Descriptor                bRequest = 7    *** not supported ***
  699. ;If wValue is zero, the device is not configured.
  700. ;The only other legal value for this firmware is 1.
  701. ;Set Configuration           bRequest = 9
  702.     cmp A, set_configuration
  703.     jz SetConfiguration
  704. ;Stall unsupported requests.
  705.     jmp SendStall
  706. ;Host to device with interface as recipient    *** not required ***
  707. ; RequestType01:
  708. ;        mov A, [bRequest]       ; load bRequest
  709. ; There are no interface features defined in the spec.
  710. ; Clear Feature                 bRequest = 1    *** not supported ***
  711. ; Set Feature                   bRequest = 3    *** not supported ***
  712. ; Set Interface is optional.
  713. ; Set Interface                 bRequest = 11   *** not supported ***
  714. ;Stall unsupported requests.
  715. ;        jmp SendStall
  716. ;Host to device with endpoint as recipient
  717. RequestType02:
  718.      mov A, [bRequest]     ; load bRequest
  719. ; The only standard feature defined for an endpoint is endpoint_stalled.
  720. ; Clear Feature               bRequest = 1
  721.      cmp A, clear_feature
  722.      jz ClearEndpointStall
  723. ; Set Feature               bRequest = 3
  724.      cmp A, set_feature
  725.      jz SetEndpointStall
  726.  
  727. ;Stall unsupported functions.
  728.     jmp SendStall
  729. ;Device to host with device as recipient
  730. RequestType80:
  731.      mov A, [bRequest]          ; load bRequest
  732. ; Get Status               bRequest = 0
  733.      cmp A, get_status
  734.      jz GetDeviceStatus
  735. ; Get Descriptor               bRequest = 6
  736.      cmp A, get_descriptor
  737.      jz GetDescriptor
  738. ; Get Configuration          bRequest = 8
  739.      cmp A, get_configuration
  740.      jz GetConfiguration
  741. ;Stall unsupported requests.
  742.      jmp SendStall
  743. ;Device to host with interface as recipient
  744. RequestType81:
  745.      mov A, [bRequest]     ; load bRequest
  746. ; Get Status               bRequest = 0
  747.       cmp A, get_status
  748.       jz GetInterfaceStatus
  749. ; Get Interface returns the selected alternate setting.
  750. ;  This firmware supports no alternate settings.
  751. ; Get Interface                 bRequest = 10   *** not supported ***
  752. ;The HID class defines one more request for bmRequestType=10000001
  753. ; Get Descriptor                bRequest = 6
  754.       cmp A, get_descriptor
  755.       jz GetDescriptor
  756. ;Stall unsupported functions
  757.       jmp SendStall
  758. ;Device to host with endpoint as recipient
  759. RequestType82:
  760.      mov A, [bRequest]          ; load bRequest
  761. ; Get Status               bRequest = 0
  762.      cmp A, get_status
  763.       jz GetEndpointStatus
  764. ; Get Descriptor               bRequest = 6
  765.      cmp A, get_descriptor
  766.      jz GetDescriptor
  767. ; Sync Frame                  bRequest = 12   *** not supported ***
  768. ;Stall unsupported functions.
  769.      jmp SendStall
  770. ;Check for HID class requests
  771. ;Host to device with endpoint as recipient
  772. RequestType21:
  773.       mov A, [bRequest]      ; load bRequest
  774. ; Set Report               bRequest = 9
  775.      cmp A, set_report
  776.      jz SetReport
  777. ; Set Idle                    bRequest = 10
  778.       cmp A, set_idle
  779.       jz SetIdle
  780. ; Set Protocol               bRequest = 11
  781.       cmp A, set_protocol
  782.       jz SetProtocol
  783. ;Stall unsupported requests
  784.      jmp SendStall
  785. RequestType22:
  786.         mov A, [bRequest]      ; load bRequest
  787. ; Set Report               bRequest = 9
  788.      cmp A, set_report     
  789.      jz SetReport
  790. ;Stall unsupported requests
  791.      jmp SendStall
  792. ;Device to host with endpoint as recipient
  793. RequestTypeA1:
  794.         mov A, [bRequest]      ; load bRequest
  795. ; Get Report               bRequest = 1
  796.         cmp A, get_report
  797.         jz GetReport
  798. ; Get Idle                 bRequest = 2
  799.         cmp A, get_idle
  800.         jz GetIdle
  801. ; Get Protocol             bRequest = 3
  802.         cmp A, get_protocol
  803.         jz GetProtocol
  804. ;Stall unsupported requests
  805.         jmp SendStall
  806. ;----------------------------------------------------------------------
  807. ;Control transfer, stage three
  808. ;Process the request.
  809. ;----------------------------------------------------------------------
  810. ;The host controls whether or not a device can request a remote wakeup.
  811. ; Disable the remote wakeup capability.
  812. ClearRemoteWakeup:
  813.         mov A, [wValue]
  814.         cmp A, device_remote_wakeup
  815.         jnz SendStall
  816. ;Handshake by sending a data packet
  817.         call Send0ByteDataPacket
  818.         mov A, DISABLE_REMOTE_WAKEUP
  819.         mov [remote_wakeup_status], A
  820.         ret
  821. ; Enable the remote wakeup capability.
  822. SetRemoteWakeup:
  823.         mov A, [wValue]
  824.         cmp A, device_remote_wakeup
  825. ;If not a match, stall.
  826.         jnz SendStall
  827. ;Handshake by sending a 0-byte data packet
  828.         call Send0ByteDataPacket
  829. ;Perform the request.
  830.         mov A, ENABLE_REMOTE_WAKEUP
  831.         mov [remote_wakeup_status], A
  832.         ret
  833. SetAddress:
  834. ; Set the device address to match wValue in the Setup packet.
  835. ;Complete the requested action after completing the transaction.
  836. ;Handshake by sending a 0-byte data packet.
  837.         call Send0ByteDataPacket
  838. ;Perform the request
  839.         mov A, [wValue]
  840.         iowr USB_Device_Address
  841.         ret
  842. SetConfiguration:
  843. ;Unconfigured: wValue=0, configured: wValue=1.
  844. ;Also clear any stall condition and set Data 0/1 to Data0.
  845. ;Handshake by sending a 0-byte data packet.
  846.       call Send0ByteDataPacket
  847. ;Save the configuration status.
  848.       mov A, [wValue]
  849.       mov [configuration_status], A
  850. ;Clear any stall condtion
  851.       mov A, 0
  852.       mov [endpoint_stall], A
  853. ;Set data 0/1 to Data0
  854.       iord USB_EP1_TX_Config
  855.       and A, ~DataToggle
  856. ;Set the configuration status.
  857.      iowr USB_EP1_TX_Config     
  858.      mov A, [configuration_status]
  859.      cmp A, 0
  860. ;If configured, jump.
  861.      jnz device_configured
  862. ;If unconfigured:
  863. ;Disable Endpoint 1
  864.      iord USB_EP1_TX_Config
  865.      and A, EFh
  866.      iowr USB_EP1_TX_Config
  867. ;Disable Endpoint 1 interrupts.
  868.      mov A, [interrupt_mask]
  869.      and A, EFh
  870.      mov [interrupt_mask], A
  871.      jmp done_configuration
  872. ;If configured:
  873. device_configured:
  874. ;Send NAK in response to IN packets
  875.      iord USB_EP1_TX_Config
  876.      and A,7Fh
  877. ;Enable Endpoint 1
  878.      or A, 10h
  879.      iowr USB_EP1_TX_Config
  880. ;Enable interrupts: Endpoint 1 and GPIO
  881.      mov A, [interrupt_mask]
  882.      or A, 50h
  883.      mov [interrupt_mask], A
  884. ;Send NAK in response to Endpoint 0 OUT packets.
  885.      iord USB_Status_Control
  886.      and A,0EFh
  887.      iowr USB_Status_Control
  888. done_configuration:
  889.         ret
  890. ClearEndpointStall:
  891. ;Clear the stall (halt) condition for Endpoint 1.
  892. ;wValue = 0.
  893.         mov A, [wValue]
  894.         cmp A, endpoint_stalled
  895. ;If endpoint_stalled = 0, the endpoint isn't stalled
  896. ;and there's nothing to clear. Return a Stall for the request.
  897.         jnz SendStall
  898. ;
  899. ;Clear Endpoint 1 stall
  900. ;Handshake by sending a 0-byte data packet
  901.       call Send0ByteDataPacket
  902. ;Clear the stall condition
  903.       mov A,0
  904.       mov [endpoint_stall], A
  905. ;Set Data 0/1 to Data0
  906.       iord USB_EP1_TX_Config
  907.       and A, ~DataToggle
  908.       iowr USB_EP1_TX_Config
  909. ;Send NAK in response to Endpoint 0 OUT packets.
  910.       iord USB_Status_Control
  911.       and A,0EFh
  912.       iowr USB_Status_Control
  913.       ret
  914. ;Stall Endpoint 1
  915. SetEndpointStall:
  916. ;wValue = 0.
  917.         mov A, [wValue]
  918.         cmp A, endpoint_stalled
  919. ;If endpoint_stalled = 1, the endpoint is already stalled,
  920. ;so return a Stall for this request.
  921.         jnz SendStall
  922. ;Handshake by sending a 0-byte data packet.
  923.         call Send0ByteDataPacket
  924. ;Stall the endpoint.
  925.         mov A,1         
  926.         mov [endpoint_stall], A
  927.         mov A, 30h
  928.         iowr USB_EP1_TX_Config
  929.         ret
  930. GetDeviceStatus:
  931. ;Device Status is a 2-byte value.
  932. ;Bit 0 must be 0 (bus-powered).
  933. ;Bit 1 is remote wakeup: 0=disabled, 1=enabled.
  934. ;All other bits are unused.
  935. ;Return to status bytes to the host.
  936.         mov A, 2
  937.         mov [data_count], A
  938. ;control_read_table holds the two possible values for device status.
  939. ;Get the address of the first value.
  940.         mov A, (get_dev_status_table - control_read_table)
  941. ;Add an index value to select the correct value.
  942.         add A, [remote_wakeup_status]
  943. ;Send the value.
  944.         jmp SendDescriptor
  945. GetDescriptor:
  946. ;The high byte of wValue contains the descriptor type.
  947. ;The low byte of wValue contains the descriptor index.
  948.         mov A, [wValueHi]               ; load descriptor type
  949. ;Test for standard descriptor types first.
  950. ;Supported descriptor types are device, configuration, string.
  951. ;Unsupported descriptor types are interface, endpoint.
  952. ; Get Descriptor (device)               wValueHi = 1
  953.      cmp A, device
  954.      jz GetDeviceDescriptor
  955. ; Get Descriptor (configuration)        wValueHi = 2
  956.      cmp A, configuration
  957.      jz GetConfigurationDescriptor
  958. ; Get Descriptor (string)               wValueHi = 3
  959.      cmp A, string
  960.      jz GetStringDescriptor
  961. ; Test for HID-class descriptor types.
  962. ; Get Descriptor (HID)                  wValueHi = 21h
  963.         cmp A, HID
  964.         jz GetHIDDescriptor
  965. ; Get Descriptor (report)               wValueHi = 22h  
  966.      cmp A, report
  967.      jz GetReportDescriptor
  968. ; Get Descriptor (physical)             wValueHi = 23h  *** not supported ***
  969. ;Stall unsupported requests.
  970.      jmp SendStall
  971. GetConfiguration:
  972. ;Send the current device configuration.
  973. ;0 = unconfigured, 1 = configured.
  974. ;Send 1 byte
  975.         mov A, 1
  976.         mov [data_count], A
  977. ;Get the address of the data to send.
  978.         mov A, (get_configuration_status_table - control_read_table)
  979. ;Add an index to point to the correct configuration.
  980.         add A, [configuration_status]
  981. ;Send the data.
  982.         jmp SendDescriptor
  983. GetInterfaceStatus:
  984. ;Interface status is 2 bytes, which are always 0.
  985. ;Send 2 bytes.
  986.         mov A, 2
  987.         mov [data_count], A
  988. ;Get the address of the data to send.
  989.         mov A, (get_interface_status_table - control_read_table)
  990. ;Send the data.
  991.         jmp SendDescriptor
  992. GetEndpointStatus:
  993. ;Endpoint status is 2 bytes.
  994. ;Bit 0 = 0 when the endpoint is not stalled.
  995. ;Bit 0 = 1 when the endpoint is stalled.
  996. ;All other bits are unused.
  997. ;Send 2 bytes.
  998.         mov A, 2
  999.         mov [data_count], A
  1000. ;Get the stall status.
  1001.         mov A, [endpoint_stall]
  1002. ;Shift left to get an index (0 or 2) to point to data
  1003. ;in the endpoint status table
  1004.         asl A
  1005. ;Get the address of the data to send.
  1006.         add A, (get_endpoint_status_table - control_read_table)
  1007. ;Send the data.
  1008.         jmp SendDescriptor
  1009. SetReport:
  1010. ;The CY7C63000 doesn't support interrupt-mode OUT transfers.
  1011. ;So the host uses Control transfers with Set_Report requests
  1012. ;to get data from the device.
  1013. ;Get the report data.
  1014. ;For debugging: set Port 0, bit 0 =1 to show that we're here.
  1015. ;      iord Port0_Data
  1016. ;      or a, 1
  1017. ;      iowr Port0_Data
  1018. ;Find out how many bytes to read. This value is in WLength.
  1019. ;Save the length in data_count.
  1020.      mov A, [wLength]
  1021.      mov [data_count], A
  1022. ;Enable receiving data at Endpoint 0 by setting the EnableOuts bit
  1023. ;The bit clears following any Setup or OUT transaction.
  1024.      iord USB_Status_Control
  1025.      or A, 10h
  1026. ;Clear the StatusOuts bit to disable automatic sending of ACK after
  1027. ;receiving a valid status packet in a Control read (IN) transfer.
  1028. ;Otherwise, the USB engine will respond to a data OUT packet with a Stall.
  1029.      and A, F7h
  1030.      iowr USB_Status_Control
  1031. ;Now we're ready to receive the report data.
  1032. ;An Endpoint 0 OUT interrupt indicates the arrival of the report data.
  1033. ret
  1034. SetIdle:
  1035.         jmp SendStall   ; *** not supported ***
  1036. SetProtocol:
  1037. ;Switches between a boot protocol (wValue=0) and report protocol (wValue=1).
  1038. ;This firmware doesn't distinguish between protocols.
  1039.         mov A, [wValue]
  1040.         mov [protocol_status], A
  1041.         call Send0ByteDataPacket
  1042.         ret
  1043. GetReport:
  1044. ;Sends a report to the host.
  1045. ;The high byte of wValue contains the report type. 
  1046. ;The low byte of wValue contains the report ID.
  1047. ;Not supported (Use interrupt transfers to send data.)
  1048.      jmp SendStall
  1049. GetReportDescriptor:
  1050. ;Save the descriptor length
  1051.      mov A, (end_hid_report_desc_table - hid_report_desc_table)
  1052.      mov [data_count], A
  1053. ;Get the descriptor's starting address.
  1054.      mov A, (hid_report_desc_table - control_read_table)
  1055.      call SendDescriptor
  1056.       ret
  1057. GetIdle:
  1058. ;Not supported
  1059.         jmp SendStall
  1060. GetProtocol:
  1061. ;Send the current protocol status.
  1062. ;Send 1 byte.
  1063.         mov A, 1
  1064.         mov [data_count], A
  1065. ;Get the address of the data to send.
  1066.         mov A, (get_protocol_status_table - control_read_table)
  1067. ;Add an index that points to the correct data.
  1068.         add A, [protocol_status]
  1069. ;Send the data.
  1070.         jmp SendDescriptor
  1071.         
  1072. ; Standard Get Descriptor routines
  1073. ;
  1074. ;Send the device descriptor.
  1075. GetDeviceDescriptor:
  1076. ;Get the length of the descriptor
  1077. ;(stored in the first byte in the device descriptor table).
  1078.         mov A, 0
  1079.        index device_desc_table
  1080.         mov [data_count], A
  1081. ;Get the starting address of the descriptor.
  1082.         mov A, (device_desc_table - control_read_table)
  1083. ;Send the descriptor.
  1084.         jmp SendDescriptor
  1085. GetConfigurationDescriptor:
  1086. ;Send the configuration descriptor.
  1087. ;Get the length of the descriptor.
  1088.      mov A, (end_config_desc_table - config_desc_table)
  1089.       mov [data_count], A
  1090. ;Get the starting address of the descriptor.
  1091.      mov A, (config_desc_table - control_read_table)
  1092. ;Send the descriptor.
  1093.      jmp SendDescriptor
  1094. GetStringDescriptor:
  1095. ;Use the string index to find out which string it is.
  1096.      mov A, [wValue]
  1097.      cmp A, 0h
  1098.      jz LanguageString
  1099.      cmp A, 01h
  1100.      jz ManufacturerString
  1101.      cmp A, 02h
  1102.      jz ProductString
  1103. ;     cmp A, 03h
  1104. ;     jz SerialNumString
  1105. ;     cmp A, 04h
  1106. ;     jz ConfigurationString
  1107. ;     cmp A, 05h
  1108. ;     jz InterfaceString
  1109. ; No other strings supported
  1110.       jmp SendStall
  1111. SendDescriptor:
  1112. ;The starting address of the descriptor is in the accumulator. Save it.
  1113.         mov [data_start], A
  1114. ;Get the descriptor length.
  1115.         call get_descriptor_length
  1116. ;Send the descriptor.
  1117.         call control_read
  1118.         ret
  1119. ;Send the requested string.
  1120. ;For each, store the descriptor length in data_count, then send the descriptor.
  1121. LanguageString:
  1122.      mov A, (USBStringDescription1 - USBStringLanguageDescription)
  1123.       mov [data_count], A
  1124.      mov A, (USBStringLanguageDescription - control_read_table)
  1125.       jmp SendDescriptor
  1126. ManufacturerString:     
  1127.      mov A, ( USBStringDescription2 - USBStringDescription1)
  1128.       mov [data_count], A
  1129.      mov A, (USBStringDescription1 - control_read_table)
  1130.       jmp SendDescriptor
  1131. ProductString:
  1132.      mov A, ( USBStringDescription3 - USBStringDescription2)
  1133.       mov [data_count], A
  1134.      mov A, (USBStringDescription2 - control_read_table)
  1135.       jmp SendDescriptor
  1136. ;SerialNumString:
  1137. ;     mov A, ( USBStringDescription4 - USBStringDescription3)
  1138. ;      mov [data_count], A
  1139. ;     mov A, (USBStringDescription3 - control_read_table)
  1140. ;      jmp SendDescriptor
  1141. ;ConfigurationString:
  1142. ;     mov A, ( USBStringDescription5 - USBStringDescription4)
  1143. ;      mov [data_count], A
  1144. ;     mov A, (USBStringDescription4 - control_read_table)
  1145. ;      jmp SendDescriptor
  1146. ;InterfaceString:
  1147. ;     mov A, ( USBStringEnd - USBStringDescription5)
  1148. ;      mov [data_count], A
  1149. ;     mov A, (USBStringDescription5 - control_read_table)
  1150. ;      jmp SendDescriptor
  1151. ; HID class Get Descriptor routines
  1152. ;
  1153. GetHIDDescriptor:
  1154. ;Send the HID descriptor.
  1155. ;Get the length of the descriptor.
  1156.      mov A, (Endpoint_Descriptor - Class_Descriptor)
  1157.       mov [data_count], A
  1158. ;Get the descriptor's starting address.
  1159.      mov A, ( Class_Descriptor - control_read_table)
  1160. ;Send the descriptor.
  1161.       call SendDescriptor
  1162.       ret
  1163. ;======================================================================
  1164. ;USB support routines
  1165. ;======================================================================
  1166. get_descriptor_length:
  1167. ;The host sometimes lies about the number of bytes it
  1168. ;wants from a descriptor.
  1169. ;A request to get a descriptor should return the smaller of the number 
  1170. ;of bytes requested or the actual length of the descriptor.
  1171. ;Get the requested number of bytes to send
  1172.      mov A, [wLengthHi]
  1173. ;If the requested high byte is >0, 
  1174. ;ignore the high byte and use the firmware's value.
  1175. ;(255 bytes is the maximum allowed.)
  1176.      cmp A, 0
  1177.      jnz use_actual_length
  1178. ;If the low byte =0, use the firmware's value.
  1179.      mov A, [wLength]
  1180.      cmp A, 0
  1181.      jz use_actual_length
  1182. ;If the requested number of bytes => the firmware's value,
  1183. ;use the firmware's value.
  1184.      cmp A, [data_count]
  1185.      jnc use_actual_length
  1186. ;If the requested number of bytes < the firmware's value,
  1187. ;use the requested number of bytes.
  1188.      mov [data_count], A
  1189. use_actual_length:
  1190.         ret
  1191. Send0ByteDataPacket:
  1192. ;Send a data packet with 0 bytes.
  1193. ;Use this handshake after receiving an OUT data packet.
  1194. ;Enable responding to IN packets and set Data 0/1 to Data 1.
  1195.      mov A, C0h
  1196.      iowr USB_EP0_TX_Config
  1197. ;Enable interrupts.
  1198.      mov A, [interrupt_mask]
  1199.      iowr Global_Interrupt
  1200. WaitForDataToTransfer:
  1201. ;Wait for the data to transfer.
  1202. ;Clear the watchdog timer
  1203.      iowr Watchdog
  1204. ;Bit 7 of USB_EP0_TX_Config is cleared when the host acknowledges
  1205. ;receiving the data.
  1206.      iord USB_EP0_TX_Config
  1207.      and A, 80h
  1208.      jnz WaitForDataToTransfer
  1209.      ret
  1210. control_read: 
  1211. ;Do a Control Read transfer.
  1212. ;The device receives a Setup packet in the Setup stage,
  1213. ;sends 1 or more data packets (IN) in the Data stage,
  1214. ;and receives a 0-length data packet (OUT) in the Status stage.
  1215. ;Before calling this routine, the firmware must set 2 values:
  1216. ;data_start is the starting address of the descriptor to send,
  1217. ;expressed as an offset from the control read table.
  1218. ;data_count is the number of bytes in the descriptor.
  1219.      push X
  1220. ;Set the Data 0/1 bit to 0.
  1221.      mov A, 00h
  1222.      mov [endp0_data_toggle], A
  1223. control_read_data_stage:
  1224. ;Initialize count variables.
  1225.      mov X, 00h
  1226.      mov A, 00h
  1227.      mov [loop_counter], A
  1228. ;Clear the Setup bit.
  1229.      iowr USB_EP0_RX_Status
  1230. ;Check the Setup bit.
  1231.      iord USB_EP0_RX_Status
  1232.      and A, 01h
  1233. ;If not cleared, another setup packet has arrived, 
  1234. ;so exit the routine.
  1235.      jnz control_read_status_stage
  1236. ;Set the StatusOuts bit to 1 to cause the device to automatically return
  1237. ;ACK in response to a received OUT packet in the Status stage.
  1238.      mov A, 08h
  1239.      iowr USB_Status_Control
  1240. ;If there is no data to send, prepare a 0-length data packet.
  1241. ;(The host might require a final 0-length packet if the descriptor is 
  1242. ;a multiple of 8 bytes.)
  1243.      mov A, [data_count]
  1244.      cmp A, 00h
  1245.      jz dma_load_done
  1246. dma_load_loop:
  1247. ;Copy up to 8 bytes for transmitting into Endpoint 0's buffer
  1248. ;and increment/decrement the various counting variables.
  1249. ;Place the byte to send in the accumulator:
  1250. ;(control_read_table) + (data_start).
  1251.      mov A, [data_start]
  1252.      index control_read_table
  1253. ;Place the byte in Endpoint 0's buffer.
  1254.      mov [X + Endpoint_0], A
  1255. ;Increment the offset of the data being sent.
  1256.      inc [data_start]
  1257. ;Increment the offset of Endpoint 0's buffer.
  1258.      inc X
  1259. ;Increment the number of bytes stored in the buffer.
  1260.      inc [loop_counter]
  1261. ;Decrement the number of bytes left to send.
  1262.      dec [data_count]
  1263. ;If the count = 0, there's no more data to load.
  1264.      jz dma_load_done
  1265. ;If 8 bytes haven't been loaded into the buffer, get another byte.
  1266. ;If 8 bytes have been loaded, it's the maximum for the transaction,
  1267. ;so send the data.
  1268.      mov A, [loop_counter]
  1269.      cmp A, 08h
  1270.      jnz dma_load_loop
  1271. dma_load_done:
  1272. ;Send the data.
  1273. ;Check the Setup bit.
  1274. ;If it's not 0, another Setup packet has arrived, 
  1275. ;so exit the routine.
  1276.      iord USB_EP0_RX_Status
  1277.      and A, 01h
  1278.      jnz control_read_status_stage
  1279. ;Set the bits in the USB_EP0_TX_Config register.
  1280. ;Toggle the Data 0/1 bit.
  1281.      mov A, [endp0_data_toggle]
  1282.      xor A, 40h
  1283.      mov [endp0_data_toggle], A
  1284. ;Enable responding to IN token packets.
  1285.      or A, 80h
  1286. ;The low 4 bits hold the number of bytes to send.
  1287.      or A, [loop_counter]
  1288.      iowr USB_EP0_TX_Config
  1289. ;Enable interrupts
  1290.      mov A, [interrupt_mask]
  1291.      iowr Global_Interrupt
  1292. wait_control_read:
  1293. ;Clear the watchdog timer
  1294.      iowr Watchdog
  1295. ;Wait for the data to transfer and the host to acknowledge,
  1296. ;indicated by Bit 7 = 0.
  1297.      iord USB_EP0_TX_Config
  1298.      and A, 80h
  1299. ;When all of the transaction's data has transferred, 
  1300. ;find out if there is more data to send in the transfer.
  1301.      jz control_read_data_stage
  1302. ;Find out if the host has sent an OUT packet to acknowledge 
  1303. ;and end the transfer.
  1304.      iord USB_EP0_RX_Status
  1305.      and A, 02h
  1306.      jz wait_control_read
  1307. control_read_status_stage:
  1308. ;The transfer is complete.
  1309.      pop X
  1310.      mov A, [interrupt_mask]
  1311.      iowr Global_Interrupt
  1312.      ret
  1313. ;======================================================================
  1314. ;Lookup Tables
  1315. ;Contain the descriptors and the codes for status indicators.
  1316. ;The firmware accesses the information by referencing a specific
  1317. ;table's address as an offset from the control_read_table.
  1318. ;======================================================================
  1319. control_read_table:
  1320. device_desc_table:
  1321.      db 12h          ; Descriptor length (18 bytes)
  1322.      db 01h          ; Descriptor type (Device)
  1323.      db 10h,01h      ; Complies with USB Spec. Release (0110h = release 1.10)
  1324.      db 00h          ; Class code (0)
  1325.      db 00h          ; Subclass code (0)
  1326.      db 00h          ; Protocol (No specific protocol)
  1327.      db 08h          ; Maximum packet size for Endpoint 0 (8 bytes)
  1328.      db 25h,09h      ; Vendor ID (Lakeview Research, 0925h)
  1329.      db 34h,12h      ; Product ID (1234)
  1330.      db 01h,00h      ; Device release number (0001)
  1331.      db 01h          ; Manufacturer string descriptor index
  1332.      db 02h          ; Product string descriptor index
  1333.      db 00h          ; Serial Number string descriptor index (None)
  1334.      db 01h          ; Number of possible configurations (1)
  1335. end_device_desc_table:
  1336. config_desc_table:
  1337.      db 09h          ; Descriptor length (9 bytes)
  1338.      db 02h          ; Descriptor type (Configuration)
  1339.      db 22h,00h      ; Total data length (34 bytes)
  1340.      db 01h          ; Interface supported (1)
  1341.      db 01h          ; Configuration value (1)
  1342.      db 00h          ; Index of string descriptor (None)
  1343.      db 80h          ; Configuration (Bus powered)
  1344.      db 32h          ; Maximum power consumption (100mA)
  1345. Interface_Descriptor:
  1346.      db 09h          ; Descriptor length (9 bytes)
  1347.      db 04h          ; Descriptor type (Interface)
  1348.      db 00h          ; Number of interface (0) 
  1349.      db 00h          ; Alternate setting (0)
  1350.      db 01h          ; Number of interface endpoint (1)
  1351.      db 03h          ; Class code ()                    
  1352.      db 00h          ; Subclass code ()                 
  1353.      db 00h          ; Protocol code ()
  1354.      db 00h          ; Index of string()       
  1355. Class_Descriptor:
  1356.      db 09h          ; Descriptor length (9 bytes)
  1357.      db 21h          ; Descriptor type (HID)
  1358.      db 00h,01h      ; HID class release number (1.00)
  1359.      db 00h          ; Localized country code (None)
  1360.      db 01h          ; # of HID class dscrptr to follow (1)
  1361.      db 22h          ; Report descriptor type (HID)
  1362.                      ; Total length of report descriptor
  1363.      db (end_hid_report_desc_table - hid_report_desc_table),00h
  1364. Endpoint_Descriptor:
  1365.      db 07h          ; Descriptor length (7 bytes)
  1366.      db 05h          ; Descriptor type (Endpoint)
  1367.      db 81h          ; Encoded address (Respond to IN, 1 endpoint)
  1368.      db 03h          ; Endpoint attribute (Interrupt transfer)
  1369.      db 06h,00h      ; Maximum packet size (6 bytes)
  1370.      db 0Ah          ; Polling interval (10 ms)
  1371.       
  1372. end_config_desc_table:
  1373. ;----------------------------------------------------------------------
  1374. ;The HID-report descriptor table
  1375. ;----------------------------------------------------------------------
  1376. hid_report_desc_table:   
  1377.      db 06h, A0h, FFh      ;         Usage Page (vendor defined) FFA0
  1378.      db 09h, 01h     ;               Usage (vendor defined)
  1379.      db A1h, 01h     ;               Collection (Application)
  1380.      db 09h, 02h     ;               Usage (vendor defined)
  1381.      db A1h, 00h     ;               Collection (Physical)
  1382.      db 06h, A1h, FFh ;              Usage Page (vendor defined) 
  1383. ;The input report
  1384.      db 09h, 03h     ;               usage - vendor defined
  1385.      db 09h, 04h     ;               usage - vendor defined
  1386.      db 15h, 80h     ;               Logical Minimum (-128)
  1387.      db 25h, 7Fh     ;               Logical Maximum (127)
  1388.      db 35h, 00h     ;               Physical Minimum (0)
  1389.      db 45h, FFh;                    Physical Maximum (255)
  1390. ;    db 66h, 00h, 00h;               Unit (None (2 bytes))
  1391.      db 75h, 08h     ;               Report Size (8)  (bits)
  1392.      db 95h, 02h     ;               Report Count (2)  (fields)
  1393.      db 81h, 02h     ;               Input (Data, Variable, Absolute)  
  1394. ;The output report
  1395.      db 09h, 05h     ;               usage - vendor defined
  1396.      db 09h, 06h     ;               usage - vendor defined
  1397.      db 15h, 80h     ;               Logical Minimum (-128)
  1398.      db 25h, 7Fh     ;               Logical Maximum (127)
  1399.      db 35h, 00h     ;               Physical Minimum (0)
  1400.      db 45h, FFh     ;               Physical Maximum (255)
  1401. ;    db 66h, 00h, 00h;               Unit (None (2 bytes))
  1402.      db 75h, 08h     ;               Report Size (8)  (bits)
  1403.      db 95h, 02h     ;               Report Count (2)  (fields)
  1404.      db 91h, 02h     ;               Output (Data, Variable, Absolute)  
  1405.      db C0h          ;               End Collection
  1406.      db C0h          ;               End Collection
  1407. end_hid_report_desc_table:
  1408. ;----------------------------------------------------------------------
  1409. ;String Descriptors
  1410. ;----------------------------------------------------------------------
  1411. ;Define the strings
  1412. ; string 0
  1413. USBStringLanguageDescription:
  1414.     db 04h          ; Length
  1415.     db 03h          ; Type (3=string)
  1416.     db 09h          ; Language:  English
  1417.     db 04h          ; Sub-language: US
  1418. ; string 1
  1419. ;The Length value for each string =
  1420. ;((number of characters) * 2) + 2
  1421. USBStringDescription1:     ; IManufacturerName
  1422.     db 1Ah          ; Length
  1423.     db 03h          ; Type (3=string)
  1424.     dsu "USB Complete" ;
  1425. ; string 2
  1426. USBStringDescription2:     ; IProduct
  1427.     db 16h          ; Length
  1428.     db 03h          ; Type (3=string)
  1429.     dsu "HID Sample"  ;
  1430. ;string 3
  1431. ;If the firmware contains a serial number, it must be unique
  1432. ;for each device or the devices may not enumerate properly.
  1433. USBStringDescription3:     ; serial number
  1434. ; string 4                 
  1435. ;USBStringDescription4:     ; configuration string descriptor
  1436. ;    db 16h          ; Length
  1437. ;    db 03h          ; Type (3=string)
  1438. ;    dsu "Sample HID"  ;
  1439. ;string 5
  1440. ;USBStringDescription5:     ; configuration string descriptor
  1441. ;    db 32h          ; Length
  1442. ;    db 03h          ; Type (3=string)
  1443. ;    dsu "EndPoint1 Interrupt Pipe"  ;
  1444. USBStringEnd:
  1445. ;----------------------------------------------------------------------
  1446. ;Status information.
  1447. ;The status can apply to the device or an interface or endpoint.
  1448. ;An index selects the correct value.
  1449. ;----------------------------------------------------------------------
  1450. get_dev_status_table:
  1451.         db      00h, 00h        ; remote wakeup disabled, bus powered
  1452.         db      02h, 00h        ; remote wakeup enabled, bus powered
  1453. get_interface_status_table:
  1454.         db      00h, 00h        ; always return both bytes zero
  1455. get_endpoint_status_table:
  1456.         db      00h, 00h        ; not stalled
  1457.         db      01h, 00h        ; stalled
  1458. get_configuration_status_table:
  1459.         db      00h             ; not configured
  1460.         db      01h             ; configured
  1461. get_protocol_status_table:
  1462.         db      00h             ; boot protocol
  1463.         db      01h             ; report protocol