Difference Analysis Generated by HtmlDiff on 10/26/2004 1:34 PM  

Base file: C:\CY4632_RDK_1_21\Firmware\Source Code\RDK Bridge\USBcode.asm

Modified file: C:\CY4632_RDK_1_3\Firmware\Source Code\RDK Bridge\USBcode.asm

;****************************************************************************
;
;   file:           USBcode.asm
;   Description:    This file contains all the procedures necessary to interface
;                   with USB
;   External Functions:
;
;   Target:         Cypress CY7C63723/CY7C63743 Encore Chips
;   $Header:
;   Version:        1.3.0000
;
;****************************************************************************
; Copyright (2003), Cypress Semiconductor Corporation
; This software is owned by Cypress Semiconductor Corporation (Cypress) and  is
; protected by United States copyright laws and international treaty provisions.
; Cypress hereby grants to Licensee a personal, non-exclusive, non-transferable
; license to copy, use, modify, create derivative works of, and compile the
; Cypress Source Code and derivative works for the sole purpose of creating
; custom software in support of Licensee product ("Licensee Product") to be used
; only in conjunction with a Cypress integrated circuit. Any reproduction,
; modification, translation, compilation, or representation of this software
; except as specified above is prohibited without the express written permission
; of Cypress.
; Disclaimer: Cypress makes no warranty of any kind, express or implied, with
; regard to this material, including, but not limited to, the implied warranties
; of merchantability and fitness for a particular purpose. Cypress reserves the
; right to make changes without further notice to the materials described herein.
; Cypress does not assume any liability arising out of the application or use of
; any product or circuit described herein. Cypress’ products described herein are
; not authorized for use as components in life-support devices.
; This software is protected by and subject to worldwide patent coverage,
; including U.S. and foreign patents. Use may be limited by and subject to the
; Cypress Software License Agreement.
;
;****************************************************************************

;*******************************************************
;       This file contains all the usb-related code
;       For the WirelessUSB-LS bridge running on the
;       637xx, including the descriptor tables.
;*******************************************************


;*******************************************************
;
;   Interrupt: endpoint0
;   Purpose: Usb control endpoint handler.  This interrupt
;           handler formulates responses to SETUP AND  
;           CONTROL READ, AND  NO-DATA CONTROL transactions. 
;
;   Jump table entry formulation for bmRequestType AND  bRequest
;
;   1. Add high AND  low nibbles of bmRequestType.
;   2. Put result into high nibble of A.
;   3. Mask off bits [6:4].
;   4. Add bRequest to A.
;   5. Double value of A (JMP  is two bytes).
;
;*******************************************************

endpoint0:
    PUSH X
    PUSH A

    IORD ep0_mode
    AND  A, EP0_ACK
    JZ   ep0_done

    IORD ep0_mode
    ASL  A
    JC   ep0_setup_received
    ASL  A
    JC   ep0_in_received
    ASL  A
    JC   ep0_out_received
  ep0_done:
    POP  A
    POP  X
    RET 

    ep0_setup_received:
    MOV  A, NAK_IN_OUT               ; clear setup bit to enable
    IOWR ep0_mode                    ; writes to EP0 DMA buffer

IFDEF DEVICE_RDK_COMBO
    MOV  A, 00h                      ; set state machine state
    MOV  [ep0_in_machine], A
ENDIF

    MOV  A, [bmRequestType]          ; compact bmRequestType into 5 bit field
    AND  A, E3h                      ; clear bits 4-3-2, these unused for our purposes
    PUSH A                           ; store value
    ASR  A                           ; move bits 7-6-5 into 4-3-2's place
    ASR  A
    ASR  A
    MOV  [int_temp], A               ; store shifted value
    POP  A                           ; get original value
    OR   A, [int_temp]               ; OR   the two to get the 5-bit field
    AND  A, 1Fh                      ; clear bits 7-6-5 (ASR  wraps bit7)
    ASL  A                           ; shift to INDEX jumptable
    JACC bmRequestType_jumptable     ; jump to handle bmRequestType

h2d_std_device:
    MOV  A, [bRequest]
    ASL  A
    JACC h2d_std_device_jumptable

h2d_std_interface:  
    MOV  A, [bRequest]
    ASL  A
    JACC h2d_std_interface_jumptable

h2d_std_endpoint:
    MOV  A, [bRequest]
    ASL  A
    JACC h2d_std_endpoint_jumptable

h2d_class_interface:
    MOV  A, [bRequest]
    ASL  A
    JACC h2d_class_interface_jumptable

d2h_std_device:
    MOV  A, [bRequest]
    ASL  A
    JACC d2h_std_device_jumptable

d2h_std_interface:
    MOV  A, [bRequest]
    ASL  A
    JACC d2h_std_interface_jumptable

d2h_std_endpoint:
    MOV  A, [bRequest]
    ASL  A
    JACC d2h_std_endpoint_jumptable

d2h_class_interface:
    MOV  A, [bRequest]
    ASL  A
    JACC d2h_class_interface_jumptable


    ;;************ DEVICE REQUESTS **************
    clear_device_feature:
        MOV     A, [wValuelo]
        CMP     A, DEVICE_REMOTE_WAKEUP
        JNZ     request_not_supported        

        MOV     A, 00h                      ; disable remote wakeup capability
        MOV     [remote_wakeup], A

        MOV      A, NO_CHANGE_PENDING       ; respond with no-data control
        MOV      [ep0_in_flag], A
        JMP      initialize_no_data_control

    set_device_feature:
        MOV     A, [wValuelo]
        CMP     A, DEVICE_REMOTE_WAKEUP
        JNZ     request_not_supported        

        MOV     A, 01h                       ; enable remote wakeup capability
        MOV     [remote_wakeup], A

        MOV      A, NO_CHANGE_PENDING        ; respond with no-data control
        MOV      [ep0_in_flag], A
        JMP      initialize_no_data_control

    set_device_address:                      ; SET ADDRESS
        MOV      A, ADDRESS_CHANGE_PENDING   ; set flag to indicate we
        MOV      [ep0_in_flag], A            ; need to change address on
        MOV      A, [wValuelo]
        MOV      [pending_data], A
        JMP      initialize_no_data_control

    set_device_configuration:                ; SET CONFIGURATION
        MOV      A, [wValuelo]
        CMP      A, 01h
        JZ        configure_device
        unconfigure_device:                  ; set device as unconfigured
            MOV      [configuration], A
            MOV      A, DISABLE              ; disable endpoint 1
            IOWR     ep1_mode
            IOWR     ep2_mode
            MOV      A, EP0_INT              ; turn off endpoint 1 interrupts
            IOWR     endpoint_int
            JMP      set_device_configuration_done
        configure_device:                   ; set device as configured
            MOV      [configuration], A

            MOV      A, NAK_IN_OUT       
            IOWR     ep1_mode
            IOWR     ep2_mode   

            MOV      A, EP0_INT       
            IOWR     endpoint_int

            MOV      A, 00h
            MOV      [ep1_data_toggle], A    ; reset the data toggle
            MOV      [ep2_data_toggle], A    ; reset the data toggle

            MOV      [ep1_dmabuff0], A       ; reset endpoint 1 fifo values
            MOV      [ep1_dmabuff1], A
            MOV      [ep1_dmabuff2], A

            MOV      [ep2_dmabuff0], A       ; reset endpoint 2 fifo values
            MOV      [ep2_dmabuff1], A
            MOV      [ep2_dmabuff2], A
            MOV      [ep2_dmabuff3], A
            MOV      [ep2_dmabuff4], A

            set_device_configuration_done:
            MOV      A, NO_CHANGE_PENDING
            MOV      [ep0_in_flag], A
            JMP      initialize_no_data_control

    get_device_status:                      ; GET STATUS
        MOV      A, DEVICE_STATUS_LENGTH
        MOV      [maximum_data_count], A
        
        MOV     A, [remote_wakeup]          ; test remote wakeup status
        CMP     A, 00h
        JZ       remote_wakeup_disabled

    remote_wakeup_enabled:                  ; send remote wakeup enabled status
        MOV     A, (device_status_wakeup_enabled - control_read_table)
        MOV      [data_start], A
        JMP      initialize_control_read
        
    remote_wakeup_disabled:                 ; send remote wakeup disabled status
        MOV     A, (device_status_wakeup_disabled - control_read_table)
        MOV     [data_start], A
        JMP     initialize_control_read  

    get_device_descriptor:                  ; GET DESCRIPTOR
        MOV     A, [wValuehi]
        ASL     A
        JACC    get_device_descriptor_jumptable

        send_device_descriptor:
            MOV      A, 00h                  ; get device descriptor length
            INDEX    device_desc_table
            MOV      [maximum_data_count], A
            MOV      A, (device_desc_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read

        send_configuration_descriptor:
            MOV      A, 02h
            INDEX    config_desc_table
            MOV      [maximum_data_count], A
IFDEF DEVICE_RDK_COMBO
            MOV      A, [wLengthlo]
            CMP      A, 09h                  ; asking for config_desc_table only
            JZ       set_pc_has_desc
            CMP      A, [maximum_data_count] ; asking for known config_desc
            JZ       set_pc_has_desc
            MOV      A, 00h                  ; PC doesn't have Desc                
            JMP      init_pc_has_desc
        set_pc_has_desc:
            MOV      A, 01h                  
        init_pc_has_desc:
            MOV      [pc_has_desc], A
ENDIF
            MOV      A, (config_desc_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read

        send_string_descriptor:
            MOV      A, [wValuelo]
            ASL      A
            JACC    string_jumptable

            language_string:
                MOV      A, 00h
                INDEX   ilanguage_string
                MOV      [maximum_data_count], A
                MOV      A, (ilanguage_string - control_read_table)
                MOV      [data_start], A
                JMP      initialize_control_read

            manufacturer_string:
                MOV      A, 00h
                INDEX   imanufacturer_string
                MOV      [maximum_data_count], A
                MOV      A, (imanufacturer_string - control_read_table)
                MOV      [data_start], A
                JMP      initialize_control_read

            product_string:
                MOV      A, 00h
                INDEX   iproduct_string
                MOV      [maximum_data_count], A
                MOV      A, (iproduct_string - control_read_table)
                MOV      [data_start], A
                JMP      initialize_control_read

            serial_string:
                MOV      A, 00h
                INDEX   iserialnumber_string
                MOV      [maximum_data_count], A
                MOV      A, (iserialnumber_string - control_read_table)
                MOV      [data_start], A
                JMP      initialize_control_read

            configuration_string:
                MOV      A, 00h
                INDEX   iconfiguration_string
                MOV      [maximum_data_count], A
                MOV      A, (iconfiguration_string - control_read_table)
                MOV      [data_start], A
                JMP      initialize_control_read

        send_interface_descriptor:
IFDEF COMBO_DEVICE
                        MOV      A, [wIndexlo]
                        AND      A, 01h
                        JNZ      send_IF2_desc
ENDIF   ; COMBO_DEVICE
                        
            MOV      A, 00h                  ; get interface descriptor length
            INDEX    interface_desc1_table 
            MOV      [maximum_data_count], A
            MOV      A, (interface_desc1_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read

IFDEF COMBO_DEVICE
        send_IF2_desc:
            MOV      A, 00h                  ; get interface descriptor length
            INDEX   interface_desc2_table 
            MOV      [maximum_data_count], A
            MOV      A, (interface_desc2_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read
ENDIF   ; COMBO_DEVICE

        send_endpoint_descriptor:
IFDEF COMBO_DEVICE
            MOV      A, [wIndexlo]
            AND              A, 01h
            JNZ              send_EP2_desc
ENDIF   ; COMBO_DEVICE
                        
            MOV      A, 00h                  ; get endpoint descriptor length
            INDEX   endpoint_desc1_table
            MOV      [maximum_data_count], A
            MOV      A, (endpoint_desc1_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read

IFDEF COMBO_DEVICE     
           send_EP2_desc:
            MOV      A, 00h                  ; get endpoint descriptor length
            INDEX   endpoint_desc2_table
            MOV      [maximum_data_count], A
            MOV      A, (endpoint_desc2_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read
ENDIF   ; COMBO_DEVICE
        get_device_configuration:           ; GET CONFIGURATION
            MOV      A, DEVICE_CONFIG_LENGTH
            MOV      [maximum_data_count], A
            MOV      A, [configuration]      ; test configuration status
            AND      A, FFh
            JZ        device_unconfigured
            device_configured:              ; send configured status
                MOV      A, (device_configured_table - control_read_table)
                MOV      [data_start], A
                JMP      initialize_control_read
            device_unconfigured:                ; send unconfigured status
                MOV      A, (device_unconfigured_table - control_read_table)
                MOV      [data_start], A
                JMP      initialize_control_read


    ;;************ INTERFACE REQUESTS ***********

    set_interface_interface:                ; SET INTERFACE
        MOV      A, [wValuelo]
        CMP      A, 00h                      ; there are no alternate interfaces
        JZ        alternate_supported         ; for this device
        alternate_not_supported:            ; if the host requests any other
            JMP      request_not_supported   ; alternate than 0, stall.  
        alternate_supported:
            MOV      A, NO_CHANGE_PENDING
            MOV      [ep0_in_flag], A
            JMP      initialize_no_data_control


    get_interface_status:                   ; GET STATUS
        MOV      A, INTERFACE_STATUS_LENGTH
        MOV      [maximum_data_count], A
        MOV      A, (interface_status_table - control_read_table)
        MOV      [data_start], A
        JMP      initialize_control_read
        

    get_interface_interface:                ; GET INTERFACE
        MOV      A, INTERFACE_ALTERNATE_LENGTH
        MOV      [maximum_data_count], A
        MOV      A, (interface_alternate_table - control_read_table)
        MOV      [data_start], A
        JMP      initialize_control_read


    set_interface_report:            
        IFDEF DEVICE_RDK_COMBO             ; Decide which battery value (a or b) to request
          MOV      A, [wIndexlo]           ; Interface # (0=kbd, 1=mouse)
          CMP      A, 01h
          JZ       req_bat_b
        ENDIF

        IFDEF DEVICE_RDK_MOUSE              
          JMP      req_bat_b
        ENDIF

        MOV      A, 01h                      
        MOV      [batt_report_req_a], A
        JMP      set_interface_report_done

        req_bat_b:       
        MOV      A, 01h
        MOV      [batt_report_req_b], A
        
        set_interface_report_done:       
        JMP      initialize_control_write  


    set_interface_idle:                     ; SET IDLE
        MOV      A, [wValuehi]               ; test if new idle time 
        CMP      A, 00h                      ; disables idle timer
        JZ       idle_timer_disable

        MOV      A, [idle_timer]             ; test if less than 4ms left
        CMP      A, 01h
        JZ       set_idle_last_not_expired

        MOV      A, [wValuehi]               ; test if time left less than
        SUB      A, [idle_timer]             ; new idle value
        JNC      set_idle_new_timer_less

        JMP      set_idle_normal

        idle_timer_disable:
            MOV      [idle], A               ; disable idle timer
            JMP      set_idle_done

        set_idle_last_not_expired:
            MOV      A, EVENT_PENDING        ; send report immediately
            MOV      [event_machine], A
            MOV      A, 00h                  ; reset idle prescaler
            MOV      [idle_prescaler], A
            MOV      A, [wValuehi]           ; set new idle value
            MOV      [idle_timer], A
            MOV      [idle], A
            JMP      set_idle_done

        set_idle_new_timer_less:            
            MOV      A, 00h
            MOV      [idle_prescaler], A     ; reset idle prescaler
            MOV      A, [wValuehi]
            MOV      [idle_timer], A         ; update idle time value
            MOV      [idle], A
            JMP      set_idle_done

        set_idle_normal:
            MOV      A, 00h                  ; reset idle prescaler
            MOV      [idle_prescaler], A
            MOV      A, [wValuehi]           ; update idle time value
            MOV      [idle_timer], A
            MOV      [idle], A

        set_idle_done:
            MOV      A, NO_CHANGE_PENDING    ; respond with no-data control
            MOV      [ep0_in_flag], A        ; transaction
            JMP      initialize_no_data_control


    set_interface_protocol:                 ; SET PROTOCOL
        MOV      A, [wValuelo]
        MOV      [protocol], A               ; set protocol value
        MOV      A, NO_CHANGE_PENDING
        MOV      [ep0_in_flag], A            ; respond with no-data control
        JMP      initialize_no_data_control  ; transaction


    get_interface_report:                ; GET HID REPORT 

        IFDEF DEVICE_RDK_COMBO           ; Decide which values (a or b) to send
          MOV      A, [wIndexlo]         ; Interface # (0=kbd, 1=mouse)
          CMP      A, 01h
          JZ       radio_report_b
        ENDIF

        IFDEF DEVICE_RDK_MOUSE           ; Just send the mouse values (xxx_b)
          JMP      radio_report_b
        ENDIF

        radio_report_a:
        MOV      A, [battery_a]          ; KBD Battery level
        MOV      [ep0_dmabuff1],A
        MOV      A, [rssi_a]             ; KBD Signal strengthbad_packets_a_low]
        MOV      [ep0_dmabuff2dmabuff4],A
        MOV      A, [bad_packets_a_high]
        MOV      [ep0_dmabuff5],A
        MOV      A, [good_packets_a_low]
        MOV      [ep0_dmabuff6],A        ; Total Pkts Xferred (Lo byte)
        MOV      A, [good_packets_a_high]
        MOV      [ep0_dmabuff7],A        ; Total Pkts Xferred (Hi byte)

        MOV      A, 0                    
        MOV      [ep0_dmabuff5],A        ; KBD Pkts Xferred (Hi byte)
        MOV      [ep0_dmabuff6],A        ; KBD Pkts Xferred (Lo byte)
        MOV     [bad_packets_a_low], A  
        MOV     [bad_packets_a_high], A 
        MOV     [good_packets_a_low], A    
        MOV     [good_packets_a_high], A

        JMP      send_radio_report

        radio_report_b:
        MOV      A, [battery_b]          ; Mouse Battery level
        MOV      [ep0_dmabuff1],A
        MOV      A, [rssi_b]             ; Mouse Signal strengthbad_packets_b_low]
        MOV      [ep0_dmabuff2dmabuff4],A
        MOV      A, [bad_packets_b_high]
        MOV      [ep0_dmabuff5],A
        MOV      A, [good_packets_b_low]
        MOV      [ep0_dmabuff6],A        ; Total Pkts Xferred (Lo byte)
        MOV      A, [good_packets_b_high]
        MOV      [ep0_dmabuff7],A        ; Total Pkts Xferred (Hi byte)

        MOV      A, 0            
        MOV      [ep0_dmabuff5],A        ; Mouse Pkts Xferred (Hi byte)
        MOV      [ep0_dmabuff6],A        ; Mouse Pkts Xferred (Lo byte)
        MOV     [bad_packets_b_low], A  
        MOV     [bad_packets_b_high], A 
        MOV     [good_packets_b_low], A    
        MOV     [good_packets_b_high], A


        send_radio_report:
        ; common data fields - independent of mouse vs kbd
        MOV      A, 04h                      ; REPORT ID
        MOV      [ep0_dmabuff0], A
        MOV      A, [channel]                ; Channel
        MOV      [ep0_dmabuff3dmabuff2], A
        MOV      A, [pn_code]                ; PN Code
        MOV      [ep0_dmabuff4dmabuff3], A

        MOV      A, TRANS_CONTROL_READ       ; set transaction type to control read
        MOV      [ep0_transtype], A

        MOV      A, DATA_TOGGLE              ; set data toggle to DATA ONE
        MOV      [ep0_data_toggle], A

        MOV      A, NAK_IN_OUT               ; clear setup bit to write to
        IOWR     ep0_mode                    ; endpoint fifo

        MOV      X, 07h                      ; set number of byte to transfer 
        JMP      dmabuffer_load_done         ; jump to finish transfer
    
    
    get_interface_idle:                     ; GET IDLE
        MOV      A, DATA_TOGGLE              ; set data toggle to DATA ONE
        MOV      [ep0_data_toggle], A
        MOV      A, NAK_IN_OUT               ; clear setup bit to write to
        IOWR    ep0_mode                    ; endpoint fifo

        MOV      A, [idle]                   ; copy over idle time
        MOV      [ep0_dmabuff0], A

        MOV      A, CONTROL_READ_DATA        ; set state machine state
        MOV      [ep0_in_machine], A         
        MOV      X, 01h                      ; set number of byte to transfer to 1
        JMP      dmabuffer_load_done         ; jump to finish transfer

    
    get_interface_protocol:                 ; GET PROTOCOL
        MOV      A, INTERFACE_PROTOCOL_LENGTH
        MOV      [maximum_data_count], A     ; get offset of device descriptor table
        MOV      A, [protocol]
        AND      A, 01h
        JZ        boot_protocol
        report_protocol:
            MOV      A, (interface_report_protocol - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read ; get ready to send data
        boot_protocol:
            MOV      A, (interface_boot_protocol - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read ; get ready to send data


    get_interface_hid:
        MOV      A, [wValuehi]
        CMP      A, 21h
        JZ        get_interface_hid_descriptor
        CMP      A, 22h
        JZ        get_interface_hid_report
        JMP      request_not_supported

    get_interface_hid_descriptor:           ; GET HID CLASS DESCRIPTOR
IFDEF COMBO_DEVICE
                MOV      A, [wIndexlo]
                AND              A, 01h
                JNZ              send_HID2_desc
ENDIF   ; COMBO_DEVICE
                
        MOV      A, 00h                      ; get hid decriptor length
        INDEX   hid_desc1_table
        MOV      [maximum_data_count], A     ; get offset of device descriptor table
        MOV      A, (hid_desc1_table - control_read_table)
        MOV      [data_start], A
        JMP      initialize_control_read     ; get ready to send data
IFDEF COMBO_DEVICE        
send_HID2_desc:
        MOV      A, 00h                      ; get hid decriptor length
        INDEX   hid_desc1_table
        MOV      [maximum_data_count], A     ; get offset of device descriptor table
        MOV      A, (hid_desc2_table - control_read_table)
        MOV      [data_start], A
        JMP      initialize_control_read     ; get ready to send data
ENDIF   ; COMBO_DEVICE

IFNDEF DEVICE_RDK_COMBO        
    get_interface_hid_report:               ; GET HID REPORT DESCRIPTOR
IFDEF COMBO_DEVICE        
                MOV      A, [wIndexlo]
                AND              A, 01h
                JNZ              send_report2_desc
ENDIF   ; COMBO_DEVICE
                
        MOV      A, 07h                      ; get hid report descriptor length
        INDEX   hid_desc1_table
        MOV      [maximum_data_count], A     ; get offset of device descriptor table
        MOV      A, (hid_report_desc1_table - control_read_table)
        MOV      [data_start], A
        JMP      initialize_control_read     ; get ready to send data

IFDEF COMBO_DEVICE        
        send_report2_desc:
        MOV      A, 07h                      ; get hid report descriptor length
        INDEX   hid_desc2_table
        MOV      [maximum_data_count], A     ; get offset of device descriptor table
        MOV      A, (hid_report_desc2_table - control_read_table)
        MOV      [data_start], A
        JMP      initialize_control_read     ; get ready to send data
ENDIF   ; COMBO_DEVICE
ENDIF
ENDIF   ; DEVICE_RDK_COMBO


IFDEF DEVICE_RDK_COMBO        
    get_interface_hid_report:               ; GET HID REPORT DESCRIPTOR
        MOV      A, CTRL_READ_HID_RPT_DESC   ; set state machine state
        MOV      [ep0_in_machine], A         
        MOV      A, 01h
        MOV      [pc_has_desc], A
                
        MOV      A, [wIndexlo]
        AND      A, 01h
        JNZ      send_report2_desc
                
        MOV      A, 07h                      ; get hid report descriptor length
        INDEX   hid_desc1_table
        MOV      [maximum_data_count], A
        MOV      A, (hid_report_desc1_table - ctrl_read_hid_rpt_desc_table)
        MOV      [data_start], A
        JMP      initialize_control_read     ; get ready to send data

        send_report2_desc:
        MOV      A, 07h                      ; get hid report descriptor length
        INDEX   hid_desc2_table
        MOV      [maximum_data_count], A
        MOV      A, (hid_report_desc2_table - ctrl_read_hid_rpt_desc_table)
        MOV      [data_start], A
        JMP      initialize_control_read     ; get ready to send data
ENDIF

    ;;************ ENDPOINT REQUESTS ************

    clear_endpoint_feature:                 ; CLEAR FEATURE
        MOV      A, [wValuelo]
        CMP      A, ENDPOINT_STALL
        JNZ      request_not_supported       
        MOV      A, 00h                      ; clear endpoint 1 stall
        MOV      [ep1_stall], A
        MOV      A, NO_CHANGE_PENDING        ; respond with no-data control
        MOV      [ep0_in_flag], A
        JMP      initialize_no_data_control

    set_endpoint_feature:                    ; SET FEATURE
        MOV      A, [wValuelo]
        CMP      A, ENDPOINT_STALL
        JNZ      request_not_supported       
        MOV      A, FFh                      ; stall endpoint 1
        MOV      [ep1_stall], A
        MOV      A, NO_CHANGE_PENDING        ; respond with no-data control
        MOV      [ep0_in_flag], A
        JMP      initialize_no_data_control

    get_endpoint_status:                    ; GET STATUS
        MOV      A, ENDPOINT_STALL_LENGTH
        MOV      [maximum_data_count], A
        MOV      A, [ep1_stall]              ; test if endpoint 1 stalled
        AND      A, FFh
        JNZ      endpoint_stalled
        endpoint_not_stalled:               ; send no-stall status
            MOV      A, (endpoint_nostall_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read
        endpoint_stalled:                   ; send stall status
            MOV      A, (endpoint_stall_table - control_read_table)
            MOV      [data_start], A
            JMP      initialize_control_read
        
;;***************** CONTROL READ TRANSACTION **************

    initialize_control_read:
        MOV      A, TRANS_CONTROL_READ       ; set transaction type to control read
        MOV      [ep0_transtype], A

        MOV      A, DATA_TOGGLE              ; set data toggle to DATA ONE
        MOV      [ep0_data_toggle], A

        ; if wLengthhi == 0
        MOV      A, [wLengthhi]              ; find lesser of requested AND  maximum
        CMP      A, 00h
        JNZ      initialize_control_read_done
        ; AND  wLengthlo < maximum_data_count
        MOV      A, [wLengthlo]              ; find lesser of requested AND  maximum
        CMP      A, [maximum_data_count]     ; response lengths
        JNC      initialize_control_read_done
        ; then maximum_data_count >= wLengthlo
        MOV      A, [wLengthlo]
        MOV      [maximum_data_count], A
        initialize_control_read_done:
        JMP      control_read_data_stage ; send first packet


;;***************** CONTROL WRITE TRANSACTION *************

    initialize_control_write:
        MOV     A, TRANS_CONTROL_WRITE      ; set transaction type to control write
        MOV     [ep0_transtype], A

        MOV     A, DATA_TOGGLE              ; set accepted data toggle
        MOV     [ep0_data_toggle], A

        MOV     A, ACK_OUT_NAK_IN                   
        IOWR    ep0_mode 
                                    
        POP     A
        POP     X
        RET 

;;***************** NO DATA CONTROL TRANSACTION ***********

    initialize_no_data_control:
        MOV      A, TRANS_NO_DATA_CONTROL    ; set transaction type to no data control
        MOV      [ep0_transtype], A

        MOV      A, STATUS_IN_ONLY           ; set SIE for STATUS IN mode
        IOWR    ep0_mode
        POP     A
        POP     X
        RET 


;;***************** UNSUPPORTED TRANSACTION ***************

    request_not_supported:
        IORD    ep0_mode
        MOV  A, STALL_IN_OUT                 ; send A stall to indicate that the request
        IOWR    ep0_mode                    ; is not supported
        POP A
        POP X
        RET 


;**********************************************************

    ;**********************************
    ; IN - CONTROL READ DATA STAGE
    ;    - CONTROL WRITE STATUS STAGE
    ;    - NO DATA CONTROL STATUS STAGE

    ep0_in_received:
    MOV      A, [ep0_transtype]
    JACC    ep0_in_jumptable


    ;**********************************

    control_read_data_stage:
        MOV      X, 00h

        MOV      A, [maximum_data_count]
        CMP      A, 00h                      ; has all been sent
        JZ        dmabuffer_load_done         

        dmabuffer_load:
            MOV      A, X                    ; check if 8 byte ep0 dma
            CMP      A, 08h                  ; buffer is full
            JZ        dmabuffer_load_done

            MOV      A, [data_start]         ; read data from desc. table
            
IFDEF DEVICE_RDK_COMBO
            MOV      A, [ep0_in_machine]
            CMP      A, CTRL_READ_HID_RPT_DESC    ; if get_interface_hid_report
            JNZ      non_hid_read            ; other read types
        hid_read:
            MOV      A, [data_start]
            INDEX   ctrl_read_hid_rpt_desc_table
            JMP      non_hid_read_end
        non_hid_read:
            MOV      A, [data_start]
            INDEX   control_read_table
        non_hid_read_end:
ELSE
            INDEX   control_read_table
ENDIF
            MOV      [X + ep0_dmabuff0], A

            INC      X                       ; increment buffer offset
            INC      [data_start]            ; increment descriptor table pointer
            DEC      [maximum_data_count]    ; decrement number of bytes requested
            JZ        dmabuffer_load_done
            JMP      dmabuffer_load          ; loop to load more data
            dmabuffer_load_done:

.ep0_count:     
        IORD    ep0_count                   ; unlock counter register
        MOV     A, X                        ; find number of bytes loaded
        OR      A, [ep0_data_toggle]        ; OR   data toggle
        MOV     [temp], A
        IOWR    ep0_count                   ; write ep0 count register

        IORD ep0_count
        CMP  A, [temp]
        JNZ  .ep0_count
        
        IORD ep0_mode
        AND  A, (EP0_SETUP | EP0_OUT)
        JNZ  .return
                
        IORD ep0_mode
        MOV      A, ACK_IN_STATUS_OUT        ; set endpoint mode to ack next IN
        IOWR    ep0_mode                    ; OR   STATUS OUT
            
        MOV      A, DATA_TOGGLE              ; toggle data toggle
        XOR      [ep0_data_toggle], A
.return:
        
        POP     A
        POP     X
        RET 


    ;**********************************

    control_write_status_stage:
        MOV     A, STATUS_IN_ONLY
        IOWR    ep0_mode

        MOV     A, TRANS_NONE
        MOV     [ep0_transtype], A

        POP     A
        POP     X
        RET 


    ;**********************************

    no_data_control_status_stage:
        MOV      A, [ep0_in_flag]        ; end of no-data control transaction 
        CMP      A, ADDRESS_CHANGE_PENDING
        JNZ      no_data_status_done

        change_address:
            MOV     A, [pending_data]   ; change the device address if this
            OR      A, ADDRESS_ENABLE   ; data is pending
            IOWR    usb_address

        no_data_status_done:            ; otherwise set to stall in/out until
            MOV     A, STALL_IN_OUT     ; A new setup
            IOWR    ep0_mode

            MOV     A, TRANS_NONE
            MOV     [ep0_transtype], A

            POP     A
            POP     X
            RET 


;**********************************************************

    ;**********************************
    ; OUT - CONTROL READ STATUS STAGE
    ;     - CONTROL WRITE DATA STAGE
    ;     - ERROR DURING NO DATA CONTROL TRANSACTION

    ep0_out_received:
    MOV     A, [ep0_transtype]
    JACC    ep0_out_jumptable

    
    ;**********************************

    control_read_status_stage:
        MOV     A, STATUS_OUT_ONLY
        IOWR    ep0_mode

        MOV      A, TRANS_NONE
        MOV      [ep0_transtype], A

        POP     A
        POP     X
        RET 


    ;**********************************

    control_write_data_stage:
        IORD    ep0_count                   ; check that data is valid
        AND     A, DATA_VALID
        JZ      control_write_data_stage_done

        IORD    ep0_count                   ; check data toggle is 1. If not,
        AND     A, DATA_TOGGLE              ; ignore the transaction. Exit.
        XOR     A, [ep0_data_toggle]
        JNZ     control_write_data_stage_done

        MOV     A, DATA_TOGGLE
        XOR     [ep0_data_toggle], A

        control_write_data_stage_done:
        POP     A
        POP     X
        RET
        
   
    ;**********************************

    no_data_control_error:  
        MOV     A, STALL_IN_OUT
        IOWR    ep0_mode

        MOV     A, TRANS_NONE
        MOV     [ep0_transtype], A

        POP     A
        POP     X
        RET 

    
;**********************************************************
;   JUMP TABLES
;**********************************************************

XPAGEOFF
ORG     1500h

        ; bmRequestTypes commented out are not used for this device,
        ; but may be used for your device.  They are kept here as
        ; an example of how to use this jumptable.

        bmRequestType_jumptable:
            JMP      h2d_std_device          ; 00
            JMP      h2d_std_interface       ; 01    
            JMP      h2d_std_endpoint        ; 02    
            JMP      request_not_supported   ; h2d_std_other         03  
            JMP      request_not_supported   ; h2d_class_device      04  
            JMP      h2d_class_interface     ; h2d_class_interface   05  
            JMP      request_not_supported   ; h2d_class_endpoint    06  
            JMP      request_not_supported   ; h2d_class_other       07  
            JMP      request_not_supported   ; h2d_vendor_device     08  
            JMP      request_not_supported   ; h2d_vendor_interface  09  
            JMP      request_not_supported   ; h2d_vendor_endpoint   0A  
            JMP      request_not_supported   ; h2d_vendor_other      0B  
            JMP      request_not_supported   ; 0C    
            JMP      request_not_supported   ; 0D    
            JMP      request_not_supported   ; 0E    
            JMP      request_not_supported   ; 0F    
            JMP      d2h_std_device          ; 10    
            JMP      d2h_std_interface       ; 11    
            JMP      d2h_std_endpoint        ; 12    
            JMP      request_not_supported   ; d2h_std_other         13  
            JMP      request_not_supported   ; d2h_class_device      14  
            JMP      d2h_class_interface     ; d2h_class_interface   15  
            JMP      request_not_supported   ; d2h_class_endpoint    16  
            JMP      request_not_supported   ; d2h_class_other       17  
            JMP      request_not_supported   ; d2h_vendor_device     18  
            JMP      request_not_supported   ; d2h_vendor_interface  19  
            JMP      request_not_supported   ; d2h_vendor_endpoint   1A  
            JMP      request_not_supported   ; d2h_vendor_other      1B  
            JMP      request_not_supported   ; 1C    
            JMP      request_not_supported   ; 1D    
            JMP      request_not_supported   ; 1E    
            JMP      request_not_supported   ; 1F    

        h2d_std_device_jumptable:
            JMP      request_not_supported   ; 00
            JMP      clear_device_feature    ; 01 Clear Feature (Clear Remote Wakeup)
            JMP      request_not_supported   ; 02 Reserved
            JMP      set_device_feature      ; 03 Set Feature (Set Remote Wakeup)
            JMP      request_not_supported   ; 04
            JMP      set_device_address      ; 05
            JMP      request_not_supported   ; 06
            JMP      request_not_supported   ; set_device_descriptor     07
            JMP      request_not_supported   ; 08
            JMP      set_device_configuration; 09

        h2d_std_interface_jumptable:
            JMP      request_not_supported   ; 00
            JMP      request_not_supported   ; clear_interface_feature 01
            JMP      request_not_supported   ; 02
            JMP      request_not_supported   ; set_interface_feature  03
            JMP      request_not_supported   ; 04
            JMP      request_not_supported   ; 05
            JMP      request_not_supported   ; 06
            JMP      request_not_supported   ; 07
            JMP      request_not_supported   ; 08
            JMP      request_not_supported   ; 09
            JMP      request_not_supported   ; 0A
            JMP      set_interface_interface ; 0B

        h2d_std_endpoint_jumptable:
            JMP      request_not_supported   ; 00
            JMP      clear_endpoint_feature  ; 01
            JMP      request_not_supported   ; 02
            JMP      set_endpoint_feature    ; 03
                                    
        ;Host-to-device HID-specific requests
        h2d_class_interface_jumptable:
            JMP      request_not_supported           ; 00
            JMP      request_not_supported           ; 01
            JMP      request_not_supported           ; 02
            JMP      request_not_supported           ; 03
            JMP      request_not_supported           ; 04
            JMP      request_not_supported           ; 05
            JMP      request_not_supported           ; 06
            JMP      request_not_supported           ; 07
            JMP      request_not_supported           ; 08
            JMP      set_interface_report            ; 09 set_report - (Output or  Feature)
            JMP      set_interface_idle              ; 0A set_idle    
            JMP      set_interface_protocol          ; 0B set_protocol        
                                    
        d2h_std_device_jumptable:
            JMP      get_device_status       ; 00
            JMP      request_not_supported   ; 01
            JMP      request_not_supported   ; 02
            JMP      request_not_supported   ; 03
            JMP      request_not_supported   ; 04
            JMP      request_not_supported   ; 05
            JMP      get_device_descriptor   ; 06
            JMP      request_not_supported   ; 07
            JMP      get_device_configuration; 08

        d2h_std_interface_jumptable:
            JMP      get_interface_status    ; 00
            JMP      request_not_supported   ; 01
            JMP      request_not_supported   ; 02
            JMP      request_not_supported   ; 03
            JMP      request_not_supported   ; 04
            JMP      request_not_supported   ; 05
            JMP      get_interface_hid       ; 06
            JMP      request_not_supported   ; 07
            JMP      request_not_supported   ; 08
            JMP      request_not_supported   ; 09
            JMP      get_interface_interface ; 0A
    
        d2h_std_endpoint_jumptable:
            JMP      get_endpoint_status     ; 00
            JMP      request_not_supported   ; 01
            JMP      request_not_supported   ; 02
            JMP      request_not_supported   ; 03
            JMP      request_not_supported   ; 04
            JMP      request_not_supported   ; 05
            JMP      request_not_supported   ; 06
            JMP      request_not_supported   ; 07
            JMP      request_not_supported   ; 08
            JMP      request_not_supported   ; 09
            JMP      request_not_supported   ; 0A
            JMP      request_not_supported   ; 0B
            JMP      request_not_supported   ; synch frame 0C
    
        ;Device-to-host HID-specific requests
        d2h_class_interface_jumptable:
            JMP      request_not_supported           ; 00
            JMP      get_interface_report            ; 01 get_report 
            JMP      get_interface_idle              ; 02 get_idle 
            JMP      get_interface_protocol          ; 03 get_protocol               

        ep0_in_jumptable:
            JMP      request_not_supported
            JMP      control_read_data_stage
            JMP      control_write_status_stage
            JMP      no_data_control_status_stage        

        ep0_out_jumptable:
            JMP      request_not_supported
            JMP      control_read_status_stage
            JMP      control_write_data_stage
            JMP      no_data_control_error


        get_device_descriptor_jumptable:
            JMP      request_not_supported
            JMP      send_device_descriptor
            JMP      send_configuration_descriptor
            JMP      send_string_descriptor
            JMP      send_interface_descriptor
            JMP      send_endpoint_descriptor

        string_jumptable:
            JMP      language_string
            JMP      manufacturer_string
            JMP      product_string
            JMP      serial_string
            JMP      configuration_string


;*********************************************************
;                   rom lookup tables
;*********************************************************

XPAGEOFF
ORG     1600h

IFDEF DEVICE_MOUSE
    INCLUDE "mouse desc.inc"    
ENDIF                

IFDEF DEVICE_GAMEPAD
    INCLUDE "gamepad desc.inc"     
ENDIF               

IFDEF DEVICE_KEYBOARD
    INCLUDE "kb desc.inc"     
ENDIF               

IFDEF DEVICE_KB_MOUSE_COMBO
    INCLUDE "kbm desc.inc"
ENDIF

IFDEF DEVICE_PERT  
    INCLUDE "kb desc.inc"
ENDIF

IFDEF DEVICE_RDK_MOUSE
    INCLUDE "mouse desc.inc"    
ENDIF                

IFDEF DEVICE_RDK_KEYBOARD
    INCLUDE "rdk kb desc.inc"     
ENDIF               

IFDEF DEVICE_RDK_COMBO
    INCLUDE "rdk kbm desc.inc"
ENDIF

XPAGEON