/*++

Copyright (c) Microsoft Corporation.  All rights reserved.

Module Name:

    usbd.h

    Generated from usb.x

Abstract:

    Private Header for USBD internal modules

Environment:

    Xbox
    C++ Only

--*/

#ifndef __USB_X__
#define __USB_X__

#ifndef __cplusplus
#error "usb.h may only be included by C++ modules"
#endif

#define EXTERNUSB extern "C"

//
//	USB drivers, and XAPI code modules that rely on USB all go into 
//	the XPP section.
//
#pragma code_seg(".XPPCODE")
#pragma data_seg(".XPP$Data")
#pragma const_seg(".XPPRDATA")

#include <usb100.h>

//
// XBOX platform USB device classes
//

#define XBOX_DEVICE_CLASS_INPUT_DEVICE              0x58
#define XBOX_DEVICE_CLASS_XDCS                      0x59
#define XBOX_DEVICE_CLASS_AUDIO_DEVICE              0x78

//
// USBD status codes
//
//  Status values are 32 bit values layed out as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +---+---------------------------+-------------------------------+
//  | S |               Status Code                                 |
//  +---+---------------------------+-------------------------------+
//
//  where
//
//      S - is the state code
//
//          00 - completed with success
//          01 - request is pending
//          10 - completed with error, endpoint not stalled
//          11 - completed with error, endpoint stalled
//
//
//      Code - is the status code
//

typedef LONG USBD_STATUS;

//
// Generic test for success on any status value (non-negative numbers
// indicate success).
//

#define USBD_SUCCESS(Status) ((USBD_STATUS)(Status) >= 0)

//
// Generic test for pending status value.
//

#define USBD_PENDING(Status) ((ULONG)(Status) >> 30 == 1)

//
// Generic test for error on any status value.
//

#define USBD_ERROR(Status) ((USBD_STATUS)(Status) < 0)

//
//  Macro to ensure that error bit is set.
//
#define SET_USBD_ERROR(err)  ((err) | USBD_STATUS_ERROR)


//
// Generic test for stall on any status value.
//

#define USBD_HALTED(Status) ((ULONG)(Status) >> 30 == 3)

#define USBD_STATUS_SUCCESS                  ((USBD_STATUS)0x00000000L)
#define USBD_STATUS_PENDING                  ((USBD_STATUS)0x40000000L)
#define USBD_STATUS_HALTED                   ((USBD_STATUS)0xC0000000L)
#define USBD_STATUS_ERROR                    ((USBD_STATUS)0x80000000L)

//
// HC status codes
// Note: these status codes have both the error and the stall bit set.
//
#define USBD_STATUS_CRC                      ((USBD_STATUS)0xC0000001L)
#define USBD_STATUS_BTSTUFF                  ((USBD_STATUS)0xC0000002L)
#define USBD_STATUS_DATA_TOGGLE_MISMATCH     ((USBD_STATUS)0xC0000003L)
#define USBD_STATUS_STALL_PID                ((USBD_STATUS)0xC0000004L)
#define USBD_STATUS_DEV_NOT_RESPONDING       ((USBD_STATUS)0xC0000005L)
#define USBD_STATUS_PID_CHECK_FAILURE        ((USBD_STATUS)0xC0000006L)
#define USBD_STATUS_UNEXPECTED_PID           ((USBD_STATUS)0xC0000007L)
#define USBD_STATUS_DATA_OVERRUN             ((USBD_STATUS)0xC0000008L)
#define USBD_STATUS_DATA_UNDERRUN            ((USBD_STATUS)0xC0000009L)
#define USBD_STATUS_RESERVED1                ((USBD_STATUS)0xC000000AL)
#define USBD_STATUS_RESERVED2                ((USBD_STATUS)0xC000000BL)
#define USBD_STATUS_BUFFER_OVERRUN           ((USBD_STATUS)0xC000000CL)
#define USBD_STATUS_BUFFER_UNDERRUN          ((USBD_STATUS)0xC000000DL)
#define USBD_STATUS_NOT_ACCESSED             ((USBD_STATUS)0xC000000EL)
#define USBD_STATUS_FIFO                     ((USBD_STATUS)0xC0000010L)

//
// HC status codes
// Note: these status codes have the error bit and not the stall bit set.
//
#define USBD_ISOCH_STATUS_CRC                      (1)
#define USBD_ISOCH_STATUS_BTSTUFF                  (2)
#define USBD_ISOCH_STATUS_DATA_TOGGLE_MISMATCH     (3)
#define USBD_ISOCH_STATUS_STALL_PID                (4)
#define USBD_ISOCH_STATUS_DEV_NOT_RESPONDING       (5)
#define USBD_ISOCH_STATUS_PID_CHECK_FAILURE        (6)
#define USBD_ISOCH_STATUS_UNEXPECTED_PID           (7)
#define USBD_ISOCH_STATUS_DATA_OVERRUN             (8)
#define USBD_ISOCH_STATUS_DATA_UNDERRUN            (9)
#define USBD_ISOCH_STATUS_RESERVED1                (A)
#define USBD_ISOCH_STATUS_RESERVED2                (B)
#define USBD_ISOCH_STATUS_BUFFER_OVERRUN           (C)
#define USBD_ISOCH_STATUS_BUFFER_UNDERRUN          (D)
#define USBD_ISOCH_STATUS_NOT_ACCESSED             (E)

//
// returned by HCD if a transfer is submitted to an endpoint that is 
// stalled
//
#define USBD_STATUS_ENDPOINT_HALTED         ((USBD_STATUS)0xC0000030L)

//
// Software status codes
// Note: the following status codes have only the error bit set
//
#define USBD_STATUS_NO_MEMORY                ((USBD_STATUS)0x80000100L)
#define USBD_STATUS_INVALID_URB_FUNCTION     ((USBD_STATUS)0x80000200L)
#define USBD_STATUS_INVALID_PARAMETER        ((USBD_STATUS)0x80000300L)
#define USBD_STATUS_UNSUPPORTED_DEVICE       ((USBD_STATUS)0x80000400L)
#define USBD_STATUS_TRANSFER_TOO_LONG        ((USBD_STATUS)0x80000500L)

//
// returned by USBD if it cannot complete a URB request, typically this 
// will be returned in the URB status field when the Irp is completed
// with a more specific NT error code in the irp.status field.
//
#define USBD_STATUS_REQUEST_FAILED           ((USBD_STATUS)0x80000600L)

#define USBD_STATUS_NO_DEVICE                ((USBD_STATUS)0x80000700L)

// returned when there is not enough bandwidth avialable
// to open a requested endpoint
#define USBD_STATUS_NO_BANDWIDTH             ((USBD_STATUS)0x80000800L)
//
// generic HC error
// 
#define USBD_STATUS_INTERNAL_HC_ERROR        ((USBD_STATUS)0x80000900L)
//
// returned when a short packet terminates the transfer
// ie USBD_SHORT_TRANSFER_OK bit not set
// 
#define USBD_STATUS_ERROR_SHORT_TRANSFER     ((USBD_STATUS)0x80000A00L)


// 
// returned if the requested start frame is not within
// USBD_ISOCH_START_FRAME_RANGE of the current USB frame, 
// note that the stall bit is set
// 
#define USBD_STATUS_BAD_START_FRAME          ((USBD_STATUS)0xC0000B00L)
//
// returned by HCD if all packets in an iso transfer complete with an error 
//
#define USBD_STATUS_ISOCH_REQUEST_FAILED     ((USBD_STATUS)0xC0000C00L)
//
// returned by HCD if an attempt is made to attach more isoch
// buffers to an endpoint than specified as the maximum when opening
// the endpoint.
//
#define USBD_STATUS_ISOCH_TOO_MANY_BUFFERS   ((USBD_STATUS)0xC0000D00L)
//
// returned by HCD if an attempt is made to start an endpoint which is
// already started.
//
#define USBD_STATUS_ISOCH_ALREADY_STARTED    ((USBD_STATUS)0xC0000E00L)
//
// returned by HCD if an attempt is made to stop an endpoint which is
// not already started.
//
#define USBD_STATUS_ISOCH_NOT_STARTED        ((USBD_STATUS)0xC0000F00L)
//
// returned by HCD if an attempt is made to start an endpoint setup for
// circular DMA with fewer than MaxAttachedBuffers,
//
#define USBD_STATUS_ISOCH_ATTACH_MORE_BUFFERS ((USBD_STATUS)0xC0001000L)
//
// This build of the usb driver does not support isochronous requests.
//
#define USBD_STATUS_ISOCH_NOT_SUPPORTED      ((USBD_STATUS)0xC0002000L)
//
// set when a transfers is completed due to an AbortPipe request from
// the client driver
//
#define USBD_STATUS_CANCELED                 ((USBD_STATUS)0xC000000FL)
#define USBD_STATUS_CANCELING                ((USBD_STATUS)0x40020000L)

//
//	Status returned by hub, when a reset completes successfully and the
//	device is low-speed.
//
#define USBD_STATUS_LOWSPEED				 ((USBD_STATUS)0x01000000L)

extern "C" {

//------------------------------------------------------------------------------------
// URB Function Codes   - High bit indicates that USBD (pre-)processes URB
//------------------------------------------------------------------------------------
//-- special bit in URB_FUNCTION codes -----------------
#define URB_FUNCTION_USBD_PROCESSED                 0x80    
#define URB_FUNCTION_ASYNCHRONOUS                   0x40
//------------------------------------------------------
#define URB_FUNCTION_CONTROL_TRANSFER               (0x00 | URB_FUNCTION_ASYNCHRONOUS)
#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER     (0x01 | URB_FUNCTION_ASYNCHRONOUS)
#define URB_FUNCTION_OPEN_ENDPOINT                  0x02
#define URB_FUNCTION_CLOSE_ENDPOINT                 (0x03 | URB_FUNCTION_ASYNCHRONOUS)
#define URB_FUNCTION_GET_ENDPOINT_STATE             0x04
#define URB_FUNCTION_SET_ENDPOINT_STATE             0x05
#define URB_FUNCTION_ABORT_ENDPOINT                 (0x06 | URB_FUNCTION_ASYNCHRONOUS)
#define URB_FUNCTION_GET_FRAME_NUMBER               0x07
#define URB_FUNCTION_OPEN_DEFAULT_ENDPOINT          (URB_FUNCTION_USBD_PROCESSED | URB_FUNCTION_OPEN_ENDPOINT)
#define URB_FUNCTION_CLOSE_DEFAULT_ENDPOINT         (URB_FUNCTION_USBD_PROCESSED | URB_FUNCTION_CLOSE_ENDPOINT)
#define URB_FUNCTION_RESET_PORT                     (URB_FUNCTION_USBD_PROCESSED | 0x08)
#define URB_FUNCTION_ISOCH_OPEN_ENDPOINT            0x09
#define URB_FUNCTION_ISOCH_CLOSE_ENDPOINT           (0x0A | URB_FUNCTION_ASYNCHRONOUS)
#define URB_FUNCTION_ISOCH_ATTACH_BUFFER            0x0B
#define URB_FUNCTION_ISOCH_START_TRANSFER           0x0C
#define URB_FUNCTION_ISOCH_STOP_TRANSFER            0x0D

//------------------------------------------------------------------------------------
//  Values for the transfer directions
//------------------------------------------------------------------------------------
#define USB_TRANSFER_DIRECTION_OUT              0x01
#define USB_TRANSFER_DIRECTION_IN               0x02

//----------------------------------------------------------------------------------------------------------------------
// Flags for URB_FUNCTION_GET_ENDPOINT_STATE
//----------------------------------------------------------------------------------------------------------------------
#define USB_ENDPOINT_STATE_HALTED              	0x01    //Set on return if endpoint is halted.
#define USB_ENDPOINT_STATE_TRANSFERS_QUEUED     0x02    //Set on return if one or more transfers are queued to endpoint.

//----------------------------------------------------------------------------------------------------------------------
// Flags for URB_FUNCTION_SET_ENDPOINT_STATE
//----------------------------------------------------------------------------------------------------------------------
#define USB_ENDPOINT_STATE_CLEAR_HALT		    0x00    //Clear endpoint halt.
#define USB_ENDPOINT_STATE_KEEP_HALT		    0x01    //Do not clear enddpoint halt
#define USB_ENDPOINT_STATE_DATA_TOGGLE_RESET    0x04    //Reset data toggle. (i.e. DATA0)
#define USB_ENDPOINT_STATE_DATA_TOGGLE_SET      0x08    //Set data toggle. (i.e. DATA1), provided for testing.
//There is no USB_ENDPOINT_STATE_SET_HALT, since only the hardware may set it.

//----------------------------------------------------------------------------------------------------------------------
// Macros for the InterruptDelay variable in transfer and attach buffer URBs - this is really an OpenHCI thing,
// but gives more control to class drivers.  These are the same as OHCI_TD_DELAY_INTERRUPT_XXX
// DUE TO BUG 9512 IT IS ONLY SAFE TO USE USBD_DELAY_INTERRUPT_0_MS.  OTHERWISE, YOU MAY EXPERIENCE PROBLEMS
// WHEN CLOSING THE ENDPOINT.  SEE BUG 9512 FOR MORE DETAILS.
//----------------------------------------------------------------------------------------------------------------------
#define USBD_DELAY_INTERRUPT_0_MS        0   // Interrupt at end of frame TD is completed
#define USBD_DELAY_INTERRUPT_1_MS        1   // Interrupt within 1 frame of TD compeletion
#define USBD_DELAY_INTERRUPT_2_MS        2   // Interrupt within 2 frames of TD compeletion
#define USBD_DELAY_INTERRUPT_3_MS        3   // Interrupt within 3 frame of TD compeletion
#define USBD_DELAY_INTERRUPT_4_MS        4   // Interrupt within 4 frame of TD compeletion
#define USBD_DELAY_INTERRUPT_5_MS        5   // Interrupt within 5 frame of TD compeletion
#define USBD_DELAY_INTERRUPT_6_MS        6   // Interrupt within  frame of TD compeletion
#define USBD_DELAY_INTERRUPT_NONE        7   // Do not Interrupt upon completion of TD

//------------------------------------------------------------------------------------
// USBD Structures for class drivers
//------------------------------------------------------------------------------------
typedef union _URB *PURB;
typedef VOID (*PURB_COMPLETE_PROC)(PURB Urb, PVOID Context);

//
//  See approptate HCD header file for
//  for flags.
//
struct _URB_HCD_AREA
{
    union
    {
        USHORT  HcdTDCount;
        USHORT  HcdOriginalLength;  //While programed contains the original length
    
	};
    USHORT  HcdUrbFlags;
	PURB    HcdUrbLink;     //Used while the URB is pending
};

struct _URB_HEADER
{
    UCHAR               Length;
    UCHAR               Function;
    USBD_STATUS         Status;
    PURB_COMPLETE_PROC  CompleteProc;       // A completetion routine if the URB is not associated with an Irp
    PVOID               CompleteContext;    // Context to pass into the completion routine.
};

typedef struct _USB_CONTROL_SETUP_PACKET
{
    UCHAR   bmRequestType;
    UCHAR   bRequest;
    USHORT  wValue;
    USHORT  wIndex;
    USHORT  wLength;
} USB_CONTROL_SETUP_PACKET;

typedef struct _URB_CONTROL_TRANSFER
{
    struct _URB_HEADER          Hdr;                    
    PVOID                       EndpointHandle;
    ULONG                       TransferBufferLength;
    PVOID                       TransferBuffer;
    UCHAR                       TransferDirection;
    BOOLEAN                     ShortTransferOK;
    UCHAR                       InterruptDelay;
    UCHAR                       Padding;
    struct _URB_HCD_AREA        Hca;
    USB_CONTROL_SETUP_PACKET    SetupPacket;
} URB_CONTROL_TRANSFER, *PURB_CONTROL_TRANSFER;

typedef struct _URB_BULK_OR_INTERRUPT_TRANSFER
{
    struct _URB_HEADER      Hdr;
    PVOID                   EndpointHandle;
    ULONG                   TransferBufferLength;
    PVOID                   TransferBuffer;
    UCHAR                   TransferDirection;
    BOOLEAN                 ShortTransferOK;
    UCHAR                   InterruptDelay;
    UCHAR                   Padding;
    struct _URB_HCD_AREA    Hca;   // fields for HCD use
} URB_BULK_OR_INTERRUPT_TRANSFER, *PURB_BULK_OR_INTERRUPT_TRANSFER;


typedef struct _URB_OPEN_ENDPOINT
{
    struct _URB_HEADER          Hdr;
    PVOID                       EndpointHandle;
    UCHAR                       FunctionAddress;
    UCHAR                       EndpointAddress;
    UCHAR                       EndpointType;
    UCHAR                       Interval;
    PULONG                      DataToggleBits; // Filled out by USBD
    USHORT                      MaxPacketSize;
    BOOLEAN                     LowSpeed;   //Temporary - filled out by USBD
} URB_OPEN_ENDPOINT, *PURB_OPEN_ENDPOINT;

typedef struct _URB_CLOSE_ENDPOINT
{
    struct _URB_HEADER     Hdr;
    PVOID                  EndpointHandle;
    PURB                   HcdNextClose;   // An extra pointer which Hcd can use to link pending closes.
    PULONG                 DataToggleBits; // Filled out by USBD
} URB_CLOSE_ENDPOINT, *PURB_CLOSE_ENDPOINT;

typedef struct _URB_GET_SET_ENDPOINT_STATE
{
    struct _URB_HEADER      Hdr;
    PVOID                   EndpointHandle;
    ULONG                   EndpointState;
} URB_GET_SET_ENDPOINT_STATE, *PURB_GET_SET_ENDPOINT_STATE;

typedef struct _URB_ABORT_ENDPOINT
{
    struct _URB_HEADER      Hdr;
    PVOID                   EndpointHandle;
    PURB                    HcdNextAbort;   // An extra pointer which Hcd can use to link pending aborts.
} URB_ABORT_ENDPOINT, *PURB_ABORT_ENDPOINT;

typedef struct _URB_RESET_PORT
{
    struct _URB_HEADER  Hdr;
    UCHAR               DeviceNode;
    UCHAR               PortNumber;
} URB_RESET_PORT, *PURB_RESET_PORT;

typedef struct _URB_GET_FRAME_NUMBER
{
    struct _URB_HEADER  Hdr;
    UCHAR               DeviceNode;
    ULONG               FrameNumber;
} URB_GET_FRAME_NUMBER, *PURB_GET_FRAME_NUMBER;


//------------------------------------------------
// Isoch related URBs and related structures
//------------------------------------------------
typedef struct _USBD_ISOCH_PACKET_STATUS_WORD
{
    USHORT BytesRead:12;
    USHORT ConditionCode:4;
} USBD_ISOCH_PACKET_STATUS_WORD, *PUSBD_ISOCH_PACKET_STATUS_WORD;

typedef struct _USBD_ISOCH_TRANSFER_STATUS
{
    USBD_STATUS                     Status;
    ULONG                           FrameCount;
    USBD_ISOCH_PACKET_STATUS_WORD   PacketStatus[8];
} USBD_ISOCH_TRANSFER_STATUS, *PUSBD_ISOCH_TRANSFER_STATUS;

typedef VOID (*PFNUSBD_ISOCH_TRANSFER_COMPLETE)(PUSBD_ISOCH_TRANSFER_STATUS Status, PVOID Context);

typedef struct _USBD_ISOCH_BUFFER_DESCRIPTOR
{
    ULONG                               FrameCount;
    PVOID                               TransferBuffer;
    USHORT                              Pattern[8];
    PFNUSBD_ISOCH_TRANSFER_COMPLETE     TransferComplete;
    PVOID                               Context;
} USBD_ISOCH_BUFFER_DESCRIPTOR, *PUSBD_ISOCH_BUFFER_DESCRIPTOR;

typedef struct _URB_ISOCH_ATTACH_BUFFER
{
    struct _URB_HEADER            Hdr;
    PVOID                         EndpointHandle;
    UCHAR                         InterruptDelay;
    PUSBD_ISOCH_BUFFER_DESCRIPTOR BufferDescriptor;
} URB_ISOCH_ATTACH_BUFFER, *PURB_ISOCH_ATTACH_BUFFER;

typedef struct _URB_ISOCH_START_TRANSFER
{
    struct _URB_HEADER     Hdr;
    PVOID                  EndpointHandle;
    ULONG                  FrameNumber;
    ULONG                  Flags;
} URB_ISOCH_START_TRANSFER, *PURB_ISOCH_START_TRANSFER;
#define URB_FLAG_ISOCH_START_ASAP 0x0001
#define USBD_ISOCH_START_FRAME_RANGE 1024

typedef struct _URB_ISOCH_STOP_TRANSFER
{
    struct _URB_HEADER     Hdr;
    PVOID                  EndpointHandle;
} URB_ISOCH_STOP_TRANSFER, *PURB_ISOCH_STOP_TRANSFER;

typedef struct _URB_ISOCH_OPEN_ENDPOINT
{
    struct _URB_HEADER              Hdr;
    PVOID                           EndpointHandle;
    UCHAR                           FunctionAddress;
    UCHAR                           EndpointAddress;
    USHORT                          MaxPacketSize;
    USHORT                          Flags;
    USHORT                          Pad;
} URB_ISOCH_OPEN_ENDPOINT, *PURB_ISOCH_OPEN_ENDPOINT;
#define URB_FLAG_ISOCH_CIRCULAR_DMA 0x0001

typedef struct _URB_CLOSE_ENDPOINT URB_ISOCH_CLOSE_ENDPOINT, *PURB_ISOCH_CLOSE_ENDPOINT;

//------------------------------------------------
// Union of all URBs
//------------------------------------------------
typedef union _URB
{
    struct _URB_HEADER              Header;
    URB_CONTROL_TRANSFER            ControlTransfer;
    URB_BULK_OR_INTERRUPT_TRANSFER  BulkOrInterruptTransfer;
    URB_BULK_OR_INTERRUPT_TRANSFER  CommonTransfer;
    URB_OPEN_ENDPOINT               OpenEndpoint;
    URB_CLOSE_ENDPOINT              CloseEndpoint;
    URB_GET_SET_ENDPOINT_STATE      GetSetEndpointState;
    URB_ABORT_ENDPOINT              AbortEndpoint;
    URB_RESET_PORT                  ResetPort;
    URB_GET_FRAME_NUMBER            GetFrame;
    URB_ISOCH_ATTACH_BUFFER         IsochAttachBuffer;
    URB_ISOCH_START_TRANSFER        IsochStartTransfer;
    URB_ISOCH_STOP_TRANSFER         IsochStopTransfer;
    URB_ISOCH_OPEN_ENDPOINT         IsochOpenEndpoint;
    URB_ISOCH_CLOSE_ENDPOINT        IsochCloseEndpoint;
} URB;

//------------------------------------------------------------------------------------
// Macros to build USB Request Blocks
//------------------------------------------------------------------------------------
#define USB_BUILD_CONTROL_TRANSFER(\
                        _UrbControlTransfer_,\
                        _EndpointHandle_,\
                        _TransferBuffer_,\
                        _TransferBufferLength_,\
                        _TransferDirection_,\
                        _CompleteProc_,\
                        _CompleteContext_,\
                        _ShortTransferOK_,\
                        _bmRequestType_,\
                        _bRequest_,\
                        _wValue_,\
                        _wIndex_,\
                        _wLength_\
    )\
    {\
        (_UrbControlTransfer_)->Hdr.Length                  =   sizeof(URB_CONTROL_TRANSFER);\
        (_UrbControlTransfer_)->Hdr.Function                =   URB_FUNCTION_CONTROL_TRANSFER;\
        (_UrbControlTransfer_)->Hdr.CompleteProc            =   (_CompleteProc_);\
        (_UrbControlTransfer_)->Hdr.CompleteContext         =   (_CompleteContext_);\
        (_UrbControlTransfer_)->EndpointHandle              =   (_EndpointHandle_);\
        (_UrbControlTransfer_)->TransferBuffer              =   (_TransferBuffer_);\
        (_UrbControlTransfer_)->TransferBufferLength        =   (_TransferBufferLength_);\
        (_UrbControlTransfer_)->TransferDirection           =   (_TransferDirection_);\
        (_UrbControlTransfer_)->ShortTransferOK             =   (_ShortTransferOK_);\
        (_UrbControlTransfer_)->InterruptDelay              =   USBD_DELAY_INTERRUPT_0_MS;\
        (_UrbControlTransfer_)->SetupPacket.bmRequestType   =   (_bmRequestType_);\
        (_UrbControlTransfer_)->SetupPacket.bRequest        =   (_bRequest_);\
        (_UrbControlTransfer_)->SetupPacket.wValue          =   (_wValue_);\
        (_UrbControlTransfer_)->SetupPacket.wIndex          =   (_wIndex_);\
        (_UrbControlTransfer_)->SetupPacket.wLength         =   (_wLength_);\
    }


#define USB_BUILD_BULK_OR_INTERRUPT_TRANSFER(\
                        _UrbBulkOrInterruptTransfer_,\
                        _EndpointHandle_,\
                        _TransferBuffer_,\
                        _TransferBufferLength_,\
                        _TransferDirection_,\
                        _CompleteProc_,\
                        _CompleteContext_,\
                        _ShortTransferOK_\
    )\
    {\
        (_UrbBulkOrInterruptTransfer_)->Hdr.Length          =   sizeof(URB_BULK_OR_INTERRUPT_TRANSFER);\
        (_UrbBulkOrInterruptTransfer_)->Hdr.Function        =   URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;\
        (_UrbBulkOrInterruptTransfer_)->Hdr.CompleteProc    =   (_CompleteProc_);\
        (_UrbBulkOrInterruptTransfer_)->Hdr.CompleteContext =   (_CompleteContext_);\
        (_UrbBulkOrInterruptTransfer_)->EndpointHandle      =   (_EndpointHandle_);\
        (_UrbBulkOrInterruptTransfer_)->TransferBuffer      =   (_TransferBuffer_);\
        (_UrbBulkOrInterruptTransfer_)->TransferBufferLength=   (_TransferBufferLength_);\
        (_UrbBulkOrInterruptTransfer_)->TransferDirection   =   (_TransferDirection_);\
        (_UrbBulkOrInterruptTransfer_)->ShortTransferOK     =   (_ShortTransferOK_);\
        (_UrbBulkOrInterruptTransfer_)->InterruptDelay      =   USBD_DELAY_INTERRUPT_0_MS;\
    }

//
// Isoch requests
//

#define USB_BUILD_ISOCH_OPEN_ENDPOINT(\
                        _UrbIsochOpenEndpoint_,\
                        _EndpointAddress_,\
                        _MaxPacketSize_,\
                        _Flags_\
    )\
    {\
        (_UrbIsochOpenEndpoint_)->Hdr.Length         =   sizeof(URB_ISOCH_OPEN_ENDPOINT);\
        (_UrbIsochOpenEndpoint_)->Hdr.Function       =   URB_FUNCTION_ISOCH_OPEN_ENDPOINT;\
        (_UrbIsochOpenEndpoint_)->Hdr.CompleteProc   =   NULL;\
        (_UrbIsochOpenEndpoint_)->Hdr.CompleteContext=   NULL;\
        (_UrbIsochOpenEndpoint_)->EndpointAddress    =   (_EndpointAddress_);\
        (_UrbIsochOpenEndpoint_)->MaxPacketSize      =   (_MaxPacketSize_);\
        (_UrbIsochOpenEndpoint_)->Flags              =   (_Flags_);\
    }

#define USB_BUILD_ISOCH_CLOSE_ENDPOINT(\
                        _UrbIsochCloseEndpoint_,\
                        _EndpointHandle_,\
						_CompleteProc_,\
						_CompleteContext_\
    )\
    {\
        (_UrbIsochCloseEndpoint_)->Hdr.Length           =   sizeof(URB_ISOCH_CLOSE_ENDPOINT);\
        (_UrbIsochCloseEndpoint_)->Hdr.Function         =   URB_FUNCTION_ISOCH_CLOSE_ENDPOINT;\
        (_UrbIsochCloseEndpoint_)->Hdr.CompleteProc     =   (_CompleteProc_);\
        (_UrbIsochCloseEndpoint_)->Hdr.CompleteContext  =   (_CompleteContext_);\
        (_UrbIsochCloseEndpoint_)->EndpointHandle       =   (_EndpointHandle_);\
    }

#define USB_BUILD_ISOCH_START_TRANSFER(\
                        _UrbIsochStartTransfer_,\
                        _EndpointHandle_,\
                        _FrameNumber_,\
                        _Flags_\
    )\
    {\
        (_UrbIsochStartTransfer_)->Hdr.Length           =   sizeof(URB_ISOCH_START_TRANSFER);\
        (_UrbIsochStartTransfer_)->Hdr.Function         =   URB_FUNCTION_ISOCH_START_TRANSFER;\
        (_UrbIsochStartTransfer_)->Hdr.CompleteProc     =   NULL;\
        (_UrbIsochStartTransfer_)->Hdr.CompleteContext  =   NULL;\
        (_UrbIsochStartTransfer_)->EndpointHandle       =   (_EndpointHandle_);\
        (_UrbIsochStartTransfer_)->FrameNumber          =   (_FrameNumber_);\
        (_UrbIsochStartTransfer_)->Flags                =   (_Flags_);\
    }

#define USB_BUILD_ISOCH_STOP_TRANSFER(\
                        _UrbIsochStopTransfer_,\
                        _EndpointHandle_\
    )\
    {\
        (_UrbIsochStopTransfer_)->Hdr.Length           =   sizeof(URB_ISOCH_STOP_TRANSFER);\
        (_UrbIsochStopTransfer_)->Hdr.Function         =   URB_FUNCTION_ISOCH_STOP_TRANSFER;\
        (_UrbIsochStopTransfer_)->Hdr.CompleteProc     =   NULL;\
        (_UrbIsochStopTransfer_)->Hdr.CompleteContext  =   NULL;\
        (_UrbIsochStopTransfer_)->EndpointHandle       =   (_EndpointHandle_);\
    }


#define USB_BUILD_ISOCH_ATTACH_BUFFER(\
                        _UrbIsochAttachBuffer_,\
                        _EndpointHandle_,\
                        _InterruptDelay_,\
                        _BufferDescriptor_\
    )\
    {\
        (_UrbIsochAttachBuffer_)->Hdr.Length            =   sizeof(URB_ISOCH_ATTACH_BUFFER);\
        (_UrbIsochAttachBuffer_)->Hdr.Function          =   URB_FUNCTION_ISOCH_ATTACH_BUFFER;\
        (_UrbIsochAttachBuffer_)->Hdr.CompleteProc      =   NULL;\
        (_UrbIsochAttachBuffer_)->Hdr.CompleteContext   =   NULL;\
        (_UrbIsochAttachBuffer_)->EndpointHandle       =   (_EndpointHandle_);\
        (_UrbIsochAttachBuffer_)->InterruptDelay       =   (_InterruptDelay_);\
        (_UrbIsochAttachBuffer_)->BufferDescriptor     =   (_BufferDescriptor_);\
    }

//
// Bulk or Interrupt requests
//

#define USB_BUILD_OPEN_ENDPOINT(\
                        _UrbOpenEndpoint_,\
                        _EndpointAddress_,\
                        _EndpointType_,\
                        _MaxPacketSize_,\
                        _Interval_\
    )\
    {\
        (_UrbOpenEndpoint_)->Hdr.Length         =   sizeof(URB_OPEN_ENDPOINT);\
        (_UrbOpenEndpoint_)->Hdr.Function       =   URB_FUNCTION_OPEN_ENDPOINT;\
        (_UrbOpenEndpoint_)->Hdr.CompleteProc   =   NULL;\
        (_UrbOpenEndpoint_)->EndpointAddress    =   (_EndpointAddress_);\
        (_UrbOpenEndpoint_)->EndpointType       =   (_EndpointType_);\
        (_UrbOpenEndpoint_)->Interval           =   (_Interval_);\
        (_UrbOpenEndpoint_)->MaxPacketSize      =   (_MaxPacketSize_);\
    }

#define USB_BUILD_CLOSE_ENDPOINT(\
                        _UrbCloseEndpoint_,\
                        _EndpointHandle_,\
                        _CompleteProc_,\
                        _CompleteContext_\
    )\
    {\
        (_UrbCloseEndpoint_)->Hdr.Length        =   sizeof(URB_CLOSE_ENDPOINT);\
        (_UrbCloseEndpoint_)->Hdr.Function      =   URB_FUNCTION_CLOSE_ENDPOINT;\
        (_UrbCloseEndpoint_)->Hdr.CompleteProc  =   (_CompleteProc_);\
        (_UrbCloseEndpoint_)->Hdr.CompleteContext = (_CompleteContext_);\
        (_UrbCloseEndpoint_)->EndpointHandle    =   (_EndpointHandle_);\
    }

#define USB_BUILD_OPEN_DEFAULT_ENDPOINT(\
                            _UrbOpenEndpoint_\
    )\
    {\
        (_UrbOpenEndpoint_)->Hdr.Length         =   sizeof(URB_OPEN_ENDPOINT);\
        (_UrbOpenEndpoint_)->Hdr.Function       =   URB_FUNCTION_OPEN_DEFAULT_ENDPOINT;\
        (_UrbOpenEndpoint_)->Hdr.CompleteProc   =   NULL;\
    }

#define USB_BUILD_CLOSE_DEFAULT_ENDPOINT(_UrbCloseEndpoint_, _CompleteProc_, _CompleteContext_)\
    {\
        (_UrbCloseEndpoint_)->Hdr.Length        =   sizeof(URB_CLOSE_ENDPOINT);\
        (_UrbCloseEndpoint_)->Hdr.Function      =   URB_FUNCTION_CLOSE_DEFAULT_ENDPOINT;\
        (_UrbCloseEndpoint_)->Hdr.CompleteProc  =   (_CompleteProc_);\
        (_UrbCloseEndpoint_)->Hdr.CompleteContext = (_CompleteContext_);\
    }

#define USB_BUILD_GET_ENDPOINT_STATE(_UrbGetSetEndpointState_, _EndpointHandle_)\
{\
    (_UrbGetSetEndpointState_)->Hdr.Length          =   sizeof(URB_GET_SET_ENDPOINT_STATE);\
    (_UrbGetSetEndpointState_)->Hdr.Function        =   URB_FUNCTION_GET_ENDPOINT_STATE;\
    (_UrbGetSetEndpointState_)->Hdr.CompleteProc    =   NULL;\
    (_UrbGetSetEndpointState_)->EndpointHandle      =   (_EndpointHandle_);\
}

#define USB_BUILD_SET_ENDPOINT_STATE(_UrbGetSetEndpointState_, _EndpointHandle_, _StateFlags_)\
{\
    (_UrbGetSetEndpointState_)->Hdr.Length          =   sizeof(URB_GET_SET_ENDPOINT_STATE);\
    (_UrbGetSetEndpointState_)->Hdr.Function        =   URB_FUNCTION_SET_ENDPOINT_STATE;\
    (_UrbGetSetEndpointState_)->Hdr.CompleteProc    =   NULL;\
    (_UrbGetSetEndpointState_)->EndpointHandle      =   (_EndpointHandle_);\
    (_UrbGetSetEndpointState_)->EndpointState       =   (_StateFlags_);\
}

#define USB_BUILD_ABORT_ENDPOINT(_UrbAbortEndpoint_, _EndpointHandle_, _CompleteProc_, _CompleteContext_)\
{\
    (_UrbAbortEndpoint_)->Hdr.Length          =   sizeof(URB_ABORT_ENDPOINT);\
    (_UrbAbortEndpoint_)->Hdr.Function        =   URB_FUNCTION_ABORT_ENDPOINT;\
    (_UrbAbortEndpoint_)->Hdr.CompleteProc    =   (_CompleteProc_);\
	(_UrbAbortEndpoint_)->Hdr.CompleteContext =   (_CompleteContext_);\
    (_UrbAbortEndpoint_)->EndpointHandle      =   (_EndpointHandle_);\
}

#define USB_BUILD_RESET_PORT(_UrbResetPort_)\
{\
    (_UrbResetPort_)->Hdr.Length        =   sizeof(URB_RESET_PORT);\
    (_UrbResetPort_)->Hdr.Function      =   URB_FUNCTION_RESET_PORT;\
    (_UrbResetPort_)->Hdr.CompleteProc  =   NULL;\
}

#define USB_BUILD_GET_FRAME(_UrbGetFrame_)\
{\
    (_UrbResetPort_)->Hdr.Length        =   sizeof(URB_GET_FRAME);\
    (_UrbResetPort_)->Hdr.Function      =   URB_FUNCTION_GET_FRAME;\
    (_UrbResetPort_)->Hdr.CompleteProc  =   NULL;\
}

//------------------------------------------------------------------------------------
// Macros to build standard USB Command Request Blocks
//------------------------------------------------------------------------------------
#define USB_BUILD_CLEAR_FEATURE(\
                _UrbControlTransfer_,\
                _Recipient_,\
                _FeatureSelect_,\
                _Index_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = NULL;\
    (_UrbControlTransfer_)->TransferBufferLength        = 0;\
    (_UrbControlTransfer_)->TransferDirection           = 0;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = (_Recipient_);\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_CLEAR_FEATURE;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = (_FeatureSelect_);\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = (_Index_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 0;\
}

#define USB_BUILD_SET_FEATURE(\
                _UrbControlTransfer_,\
                _Recipient_,\
                _FeatureSelect_,\
                _Index_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = NULL;\
    (_UrbControlTransfer_)->TransferBufferLength        = 0;\
    (_UrbControlTransfer_)->TransferDirection           = 0;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = (_Recipient_);\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_SET_FEATURE;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = (_FeatureSelect_);\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = (_Index_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 0;\
}

#define USB_BUILD_GET_CONFIGURATION(\
                _UrbControlTransfer_,\
                _Configuration_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = (_Configuration_);\
    (_UrbControlTransfer_)->TransferBufferLength        = sizeof(UCHAR);\
    (_UrbControlTransfer_)->TransferDirection           = USB_TRANSFER_DIRECTION_IN;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = USB_DEVICE_TO_HOST;\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_GET_CONFIGURATION;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = 0;\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = 0;\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 1;\
}

#define USB_BUILD_SET_CONFIGURATION(\
                _UrbControlTransfer_,\
                _Configuration_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = 0;\
    (_UrbControlTransfer_)->TransferBufferLength        = 0;\
    (_UrbControlTransfer_)->TransferDirection           = 0;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = USB_HOST_TO_DEVICE;\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_SET_CONFIGURATION;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = (_Configuration_);\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = 0;\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 0;\
}


#define USB_BUILD_GET_DESCRIPTOR(\
                _UrbControlTransfer_,\
                _DescriptorType_,\
                _DescriptorIndex_,\
                _LanguageID_,\
                _DescriptorBuffer_,\
                _DescriptorBufferLength_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = (_DescriptorBuffer_);\
    (_UrbControlTransfer_)->TransferBufferLength        = (_DescriptorBufferLength_);\
    (_UrbControlTransfer_)->TransferDirection           = USB_TRANSFER_DIRECTION_IN;\
    (_UrbControlTransfer_)->ShortTransferOK             = TRUE;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = USB_DEVICE_TO_HOST;\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_GET_DESCRIPTOR;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = ((_DescriptorType_)<<8)|(_DescriptorIndex_);\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = (_LanguageID_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = (_DescriptorBufferLength_);\
}

#define USB_BUILD_SET_DESCRIPTOR(\
                _UrbControlTransfer_,\
                _DescriptorType_,\
                _DescriptorIndex_,\
                _LanguageID_,\
                _DescriptorBuffer_,\
                _DescriptorBufferLength_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = (_DescriptorBuffer_);\
    (_UrbControlTransfer_)->TransferBufferLength        = (_DescriptorBufferLength_);\
    (_UrbControlTransfer_)->TransferDirection           = USB_TRANSFER_DIRECTION_OUT;\
    (_UrbControlTransfer_)->ShortTransferOK             = FALSE;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = USB_HOST_TO_DEVICE;\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_SET_DESCRIPTOR;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = ((_DescriptorType_)<<8)|(_DescriptorIndex_);\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = (_LanguageID_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = (_DescriptorBufferLength_);\
}


#define USB_BUILD_GET_INTERFACE(\
                _UrbControlTransfer_,\
                _Interface_,\
                _AlternateSetting_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = (_AlternateSetting_);\
    (_UrbControlTransfer_)->TransferBufferLength        = sizeof(UCHAR);\
    (_UrbControlTransfer_)->TransferDirection           = USB_TRANSFER_DIRECTION_IN;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = USB_DEVICE_TO_HOST;\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_GET_INTERFACE;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = 0\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = (_Interface_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 1;\
}

#define USB_BUILD_SET_INTERFACE(\
                _UrbControlTransfer_,\
                _Interface_,\
                _AlternateSetting_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = 0;\
    (_UrbControlTransfer_)->TransferBufferLength        = 0;\
    (_UrbControlTransfer_)->TransferDirection           = 0;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = USB_HOST_TO_DEVICE;\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_SET_INTERFACE;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = (_AlternateSetting_);\
    (_UrbControlTransfer_)->SetupPacket.wIndex          = (_Interface_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 0;\
}


#define USB_BUILD_GET_STATUS(\
                _UrbControlTransfer_,\
                _Recipient_,\
                _Index_,\
                _Status_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = (_Status_);\
    (_UrbControlTransfer_)->TransferBufferLength        = size(WORD);\
    (_UrbControlTransfer_)->TransferDirection           = USB_TRANSFER_DIRECTION_IN;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = (USB_DEVICE_TO_HOST|(_Recipient_));\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_GET_STATUS;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = 0;\
    (_UrbControlTransfer_)->SetupPacket.wIndex          =(_Index_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 2;\
}

#define USB_BUILD_SYNC_FRAME(\
                _UrbControlTransfer_,\
                _Endpoint_,\
                _Frame_,\
                _CompleteProc_,\
                _CompleteContext_\
                )\
{\
    (_UrbControlTransfer_)->Hdr.Length                  = sizeof(URB_CONTROL_TRANSFER);\
    (_UrbControlTransfer_)->Hdr.Function                = URB_FUNCTION_CONTROL_TRANSFER;\
    (_UrbControlTransfer_)->Hdr.CompleteProc            = (_CompleteProc_);\
    (_UrbControlTransfer_)->Hdr.CompleteContext         = (_CompleteContext_);\
    (_UrbControlTransfer_)->EndpointHandle              = NULL;\
    (_UrbControlTransfer_)->TransferBuffer              = (_Frame_);\
    (_UrbControlTransfer_)->TransferBufferLength        = size(WORD);\
    (_UrbControlTransfer_)->TransferDirection           = USB_TRANSFER_DIRECTION_IN;\
    (_UrbControlTransfer_)->ShortTransferOK             = 0;\
    (_UrbControlTransfer_)->InterruptDelay              = USBD_DELAY_INTERRUPT_0_MS;\
    (_UrbControlTransfer_)->SetupPacket.bmRequestType   = (USB_DEVICE_TO_HOST|USB_COMMAND_TO_ENDPOINT);\
    (_UrbControlTransfer_)->SetupPacket.bRequest        = USB_REQUEST_SYNC_FRAME;\
    (_UrbControlTransfer_)->SetupPacket.wValue          = 0;\
    (_UrbControlTransfer_)->SetupPacket.wIndex          =(_Endpoint_);\
    (_UrbControlTransfer_)->SetupPacket.wLength         = 2;\
}

//-------------------------------------------------------------------------------------------------------------
// Get the USB status code
//-------------------------------------------------------------------------------------------------------------
#define URB_STATUS(urb) ((urb)->Header.Status)
} //end of 'extern "C"'
//------------------------------------------------------------------------------------
// bmRequestType values for commands over control pipes, belongs in usb100.h
//------------------------------------------------------------------------------------

//  Data Direction
#define USB_HOST_TO_DEVICE              0x00    
#define USB_DEVICE_TO_HOST              0x80

//  Type
#define USB_STANDARD_COMMAND            0x00
#define USB_CLASS_COMMAND               0x20
#define USB_VENDOR_COMMAND              0x40

//  Recipient
#define USB_COMMAND_TO_DEVICE           0x00
#define USB_COMMAND_TO_INTERFACE        0x01
#define USB_COMMAND_TO_ENDPOINT         0x02
#define USB_COMMAND_TO_OTHER            0x03

//------------------------------------------------------------------------------------
// The enumerator only provides the first eight bytes of the device descriptor
//------------------------------------------------------------------------------------
typedef struct _USB_DEVICE_DESCRIPTOR8 {
    UCHAR bLength;
    UCHAR bDescriptorType;
    USHORT bcdUSB;
    UCHAR bDeviceClass;
    UCHAR bDeviceSubClass;
    UCHAR bDeviceProtocol;
    UCHAR bMaxPacketSize0;
} USB_DEVICE_DESCRIPTOR8, *PUSB_DEVICE_DESCRIPTOR8;
//---------------------------------------------------------------------------------------------------------------
// USB_HOST_CONTROLLER - Host Controller Configuration Selection
//---------------------------------------------------------------------------------------------------------------
#define USB_SINGLE_HOST_CONTROLLER 1
#define USB_DUAL_HOST_CONTROLLER_XDK 2
//  Select which configuragtion to use.

#ifndef USB_HOST_CONTROLLER_CONFIGURATION
#ifdef SILVER
#define USB_HOST_CONTROLLER_CONFIGURATION USB_DUAL_HOST_CONTROLLER_XDK
#else  //!SILVER
#define USB_HOST_CONTROLLER_CONFIGURATION USB_SINGLE_HOST_CONTROLLER
#endif ////!SILVER
#endif  USB_HOST_CONTROLLER_CONFIGURATION


#
//------------------------------------------------------------------------------------
//  Forward declaration of classes
//------------------------------------------------------------------------------------
class IUsbDevice;
class CDeviceTree;

//---------------------------------------------------------------------------------------------------------------
// USBD_HOST_CONTROLLER - Context of USBD by host controller.  Instead of a DEVICE_OBJECT
//---------------------------------------------------------------------------------------------------------------
#pragma warning(disable : 4200) //Turn off zero length array warning
typedef struct _USBD_HOST_CONTROLLER
{
    ULONG           ControllerNumber;   //Number of this controller.
    IUsbDevice      *RootHub;           //Root Hub
    ULONG           AddressList[4];     //128 bit bitfield of used USB addresses.
    ULONG           HcdExtension[0];    //The Host controllers extension starts here.
} USBD_HOST_CONTROLLER, *PUSBD_HOST_CONTROLLER;
#pragma warning(default : 4200) //Turn zero length array warning back on

//
//  Stuff related to the Host Controller Driver, its endpoint size and its extension
//
extern ULONG GLOBAL_HostControllerExtensionSize;
#define USBD_GetHCDExtension(_UsbdHostController_) ((PVOID)(_UsbdHostController_->HcdExtension))
#define USBD_HostControllerFromHCDExtension(_HCDExtension_)  CONTAINING_RECORD(_HCDExtension_, USBD_HOST_CONTROLLER, HcdExtension)

//---------------------------------------------------------------------------------------------------------------
//  Types of USB Device Nodes.
//      UDN_TYPE_HUB                - represents a hub device.
//      UDN_TYPE_FUNCTION           - a USB function for which bDeviceClass != 0.
//      UDN_TYPE_INTERFACE_FUNCTION - a USB function where bDeviceClass is 0, but there is only one interface.
//      UDN_TYPE_COMPOSITE_FUNCTION - a USB function where bDeviceClass is 0, and there are multiple interfaces.
//                                    a COMPOSITE_FUNCTION always has one INTERFACE child be interface.   
//      UDN_TYPE_INTERFACE          - represents an INTERFACE on a COMPOSITE_FUNCTION.
//===============================================================================================================
//  Special types not signifying a device
//      UDN_TYPE_UNUSED             - Not currently representing a device.  Node should be on the free list.
//      UDN_TYPE_PENDING_ENUM       - Device has been detected, but is in the list of nodes awaiting enumeration.
//      UDN_TYPE_ENUMERATING        - Device is currently being enumerated, but has not reached a stage of enumeration
//                                    yet where the node type is known.
//---------------------------------------------------------------------------------------------------------------
#define UDN_TYPE_ROOT_HUB           0
#define UDN_TYPE_HUB                1
#define UDN_TYPE_FUNCTION           2
#define UDN_TYPE_INTERFACE_FUNCTION 3
#define UDN_TYPE_COMPOSITE_FUNCTION 4
#define UDN_TYPE_INTERFACE          5
#define UDN_TYPE_UNUSED             0xFF    
#define UDN_TYPE_PENDING_ENUM       0xFE
#define UDN_TYPE_ENUMERATING        0xFD

//---------------------------------------------------------------------------------------------------------------
//  Device node constants
//---------------------------------------------------------------------------------------------------------------
#define UDN_INVALID_NODE_INDEX      128   // Indicates that index does not point to a valid node.

#define UDN_LOWSPEED_PORT           0x80
#define UDN_NO_CLASS_DRIVER_SUPPORT 0xFF
#define UDN_HUB_TYPE_EXTERNAL       0x01

//--------------------------------------------------------------------------------
//  Resource structure shared between USBD and OHCD
//--------------------------------------------------------------------------------
extern "C" {
#define HCD_INTERRUPT_TD_QUOTA 3
typedef struct _HCD_RESOURCE_REQUIREMENTS
{
    ULONG EndpointCount;
    ULONG IsochEndpointCount;
    ULONG TDCount;
    UCHAR ControlTDQuota;
    UCHAR BulkTDQuota;
    UCHAR IsochMaxBuffers;
} HCD_RESOURCE_REQUIREMENTS, *PHCD_RESOURCE_REQUIREMENTS;

} //end 'extern "C"'

//--------------------------------------------------------------------------------------------------------------
// Resource Requirements Structure
//--------------------------------------------------------------------------------------------------------------
typedef struct _USB_RESOURCE_REQUIREMENTS
{
    UCHAR ConnectorType;
    UCHAR MaxDevices;
    UCHAR MaxCompositeInterfaces;
    UCHAR MaxControlEndpoints;
    UCHAR MaxBulkEndpoints;
    UCHAR MaxInterruptEndpoints;
    UCHAR MaxControlTDperTransfer;
    UCHAR MaxBulkTDperTransfer;
    //Isoch
    UCHAR MaxIsochEndpoints;
    UCHAR MaxIsochMaxBuffers;
} USB_RESOURCE_REQUIREMENTS, *PUSB_RESOURCE_REQUIREMENTS;
//-------------------------------------------------------------------------------------------------
// This class is used to assist initialization.
//-------------------------------------------------------------------------------------------------
class IUsbInit
{
  public:
    ULONG GetMaxDeviceTypeCount(PXPP_DEVICE_TYPE XppDeviceType);
    VOID  RegisterResources(PUSB_RESOURCE_REQUIREMENTS pResourceRequirements);
    BOOL  UseDefaultCount();
    //c'tor
    IUsbInit(ULONG NumDeviceTypes, PXDEVICE_PREALLOC_TYPE DeviceTypes) :
      m_NumDeviceTypes(NumDeviceTypes), m_pDeviceTypes(DeviceTypes),
      m_NodeCount(0), m_MaxCompositeInterfaces(0)
      {
        RtlZeroMemory(m_Direct, sizeof(m_Direct));
        RtlZeroMemory(m_TopSlots, sizeof(m_TopSlots));
        RtlZeroMemory(m_BottomSlots, sizeof(m_BottomSlots));
        RtlZeroMemory(&m_HcdResources, sizeof(m_HcdResources));
      }

    //services for usbd to retrieve information
    void Process();
    inline UCHAR GetNodeCount() {return m_NodeCount;}
    inline UCHAR GetMaxCompositeInterfaces() {return m_MaxCompositeInterfaces;}
    inline PHCD_RESOURCE_REQUIREMENTS GetHcdResourcePtr() {return &m_HcdResources;}
  private:
    USB_RESOURCE_REQUIREMENTS m_Direct[5];
    USB_RESOURCE_REQUIREMENTS m_TopSlots[5];
    USB_RESOURCE_REQUIREMENTS m_BottomSlots[5];
    ULONG                     m_NumDeviceTypes;
    PXDEVICE_PREALLOC_TYPE    m_pDeviceTypes;
    // Fields valid after process
    UCHAR                     m_NodeCount;
    UCHAR                     m_MaxCompositeInterfaces;
    HCD_RESOURCE_REQUIREMENTS m_HcdResources;
};
//--------------------------------------------------------------------------------------------------------------
// Class Driver Static Registration 
//--------------------------------------------------------------------------------------------------------------
typedef union _PNP_CLASS_ID
{
    LONG AsLong;
    struct
    {
        UCHAR bClassSpecificType;
        UCHAR bClass;
        UCHAR bSubClass;
        UCHAR bProtocol;
    } USB;
} PNP_CLASS_ID, *PPNP_CLASS_ID;

// The high-bit of bClassSpecificType is set
// if the class driver has not indicated a class
// specific type.  Prior to calling AddDevice
// this is used to track whether this is a 
// device level or interface level class.
// 
// USB_CLASS_DRIVER_DECLARATION assumes PNP_INTERFACE_LEVEL_CLASS
// 
#define PNP_CLASS_SPECIFIC_TYPE_NOT_SET(bClassSpecificType) (bClassSpecificType&0x80)
#define PNP_DEVICE_LEVEL_CLASS    0x81
#define PNP_INTERFACE_LEVEL_CLASS 0x82

typedef
VOID
 (*PFNINIT_USB_DRIVER)(IUsbInit *UsbInit);

typedef
VOID
 (*PFNADD_USB_DEVICE)(
    IN IUsbDevice *Device
    );

typedef
VOID
 (*PFNREMOVE_USB_DEVICE)(
    IN IUsbDevice *Device
    );


typedef struct _USB_DEVICE_TYPE_DESCRIPTION
{
    PXPP_DEVICE_TYPE XppDeviceType;
} USB_DEVICE_TYPE_DESCRIPTION, *PUSB_DEVICE_TYPE_DESCRIPTION;

#define USB_CONNECTOR_TYPE_DIRECT     0  //Plugs directly into the front of xbox (or a hub port)
#define USB_CONNECTOR_TYPE_HIGH_POWER 1  //Plugs into a high power slot in gamepad
#define USB_CONNECTOR_TYPE_LOW_POWER  2  //Plugs into a high power or low power slot in gamepad

typedef struct _USB_CLASS_DRIVER_DESCRIPTION
{
    PNP_CLASS_ID                 ClassId;
    PFNINIT_USB_DRIVER           Init;
    PFNADD_USB_DEVICE            AddDevice;
    PFNREMOVE_USB_DEVICE         RemoveDevice;
    ULONG                        DeviceTypeCount;
    PXPP_DEVICE_TYPE             *DeviceTypes;
} USB_CLASS_DRIVER_DESCRIPTION, *PUSB_CLASS_DRIVER_DESCRIPTION;

#define DECLARE_XPP_TYPE(XppTypeName)\
EXTERNUSB XPP_DEVICE_TYPE XppTypeName##_TABLE = {0,0,0};

#define USB_DEVICE_TYPE_TABLE_BEGIN(ClassName)\
EXTERNUSB PXPP_DEVICE_TYPE ClassName##Types[]={

#define USB_DEVICE_TYPE_TABLE_ENTRY(XppDeviceType)\
                 (XppDeviceType)

#define USB_DEVICE_TYPE_TABLE_END() };

#define USB_CLASS_DRIVER_DECLARATION(ClassName, bClass, bSubClass, bProtocol)\
               EXTERNUSB VOID ClassName##Init(IUsbInit *UsbInit);\
               EXTERNUSB VOID ClassName##AddDevice(IUsbDevice *Device);\
               EXTERNUSB VOID ClassName##RemoveDevice(IUsbDevice *Device);\
               EXTERNUSB USB_CLASS_DRIVER_DESCRIPTION ClassName##Description = {\
                    PNP_INTERFACE_LEVEL_CLASS + ((bClass << 8) + (bSubClass << 16) + (bProtocol << 24)),\
                    ClassName##Init,\
                    ClassName##AddDevice,\
                    ClassName##RemoveDevice,\
                    sizeof(ClassName##Types)/sizeof(USB_DEVICE_TYPE_DESCRIPTION),\
                    ClassName##Types\
                   };

#define USB_CLASS_DRIVER_DECLARATION_DUPLICATE(ClassName, DuplicateNumber, bClass, bSubClass, bProtocol)\
               EXTERNUSB USB_CLASS_DRIVER_DESCRIPTION ClassName##DuplicateNumber##Description = {\
                    PNP_INTERFACE_LEVEL_CLASS + ((bClass << 8) + (bSubClass << 16) + (bProtocol << 24)),\
                    ClassName##Init,\
                    ClassName##AddDevice,\
                    ClassName##RemoveDevice,\
                    sizeof(ClassName##Types)/sizeof(USB_DEVICE_TYPE_DESCRIPTION),\
                    ClassName##Types\
                   };

#define USB_CLASS_DRIVER_DECLARATION_DEVICE_LEVEL(ClassName, bClass, bSubClass, bProtocol)\
               EXTERNUSB VOID ClassName##Init(IUsbInit *UsbInit);\
               EXTERNUSB VOID ClassName##AddDevice(IUsbDevice *Device);\
               EXTERNUSB VOID ClassName##RemoveDevice(IUsbDevice *Device);\
               EXTERNUSB USB_CLASS_DRIVER_DESCRIPTION ClassName##Description = {\
                    PNP_DEVICE_LEVEL_CLASS + ((bClass << 8) + (bSubClass << 16) + (bProtocol << 24)),\
                    ClassName##Init,\
                    ClassName##AddDevice,\
                    ClassName##RemoveDevice,\
                    sizeof(ClassName##Types)/sizeof(USB_DEVICE_TYPE_DESCRIPTION),\
                    ClassName##Types\
                   };

#define USB_CLASS_DECLARATION_POINTER(ClassName)\
                EXTERNUSB USB_CLASS_DRIVER_DESCRIPTION *ClassName##DescriptionPointer=&ClassName##Description;
#define USB_CLASS_DECLARATION_POINTER_DUPLICATE(ClassName, DuplicateNumber)\
                EXTERNUSB USB_CLASS_DRIVER_DESCRIPTION *ClassName##DuplicateNumber##DescriptionPointer=\
                &ClassName##DuplicateNumber##Description;

#define REFERENCE_CLASS(ClassName)\
    EXTERNUSB USB_CLASS_DRIVER_DESCRIPTION ClassName##Description;\
    static USB_CLASS_DRIVER_DESCRIPTION *classMU = &(ClassName##Description);

//---------------------------------------------------------------------------------------------------------------
//  IUsbDevice is the main interface to the core driver
//---------------------------------------------------------------------------------------------------------------
class IUsbDevice
{
    public:
    /*  IUsbDevice methods calleable at any time by class driver*/
    USBD_STATUS SubmitRequest(PURB Urb);
    USBD_STATUS CancelRequest(PURB Urb);
    BOOLEAN IsHardwareConnected() const;
    PVOID GetExtension() const;
    PVOID SetExtension(PVOID Extension);
    UCHAR GetInterfaceNumber() const;
	void SetClassSpecificType(UCHAR ClassSpecificType);
    ULONG GetPort() const;

    /*  IUsbDevice methods related to device enumeration*/
    void AddComplete(USBD_STATUS UsbdStatus);
    void RemoveComplete();
    void DeviceNotResponding();

    /*  IUsbDevice methods calleable only at enum time*/
    const USB_DEVICE_DESCRIPTOR8 *GetDeviceDescriptor() const;
    const USB_CONFIGURATION_DESCRIPTOR *GetConfigurationDescriptor() const;
    const USB_INTERFACE_DESCRIPTOR *GetInterfaceDescriptor() const;
    const USB_ENDPOINT_DESCRIPTOR *GetEndpointDescriptor(UCHAR EndpointType, BOOLEAN Direction, UCHAR Index) const;
    
	/*  IUsbDevice methods used only by hubs */
    void DeviceConnected(UCHAR PortNumber, UCHAR RetryCount);
    void DeviceDisconnected(UCHAR PortNumber);
    void ResetComplete(USBD_STATUS UsbdStatus, PVOID Context);
    void DisableComplete(USBD_STATUS UsbdStatus, PVOID Context);

    /* static IUsbDevice methods */
    static ULONG Win32FromUsbdStatus(USBD_STATUS UsbdStatus);
	static NTSTATUS NtStatusFromUsbdStatus(USBD_STATUS UsbdStatus);
    /*  c'tor */
    IUsbDevice::IUsbDevice() : 
        m_Type(UDN_TYPE_UNUSED), m_NextFree(UDN_INVALID_NODE_INDEX),
        m_FirstChild(UDN_INVALID_NODE_INDEX), m_Sibling(UDN_INVALID_NODE_INDEX){}

    /* IUsbDevice short and sweet methods used in USBD, these are inline, but defined below due to declaration order */
    UCHAR			GetIndex() const;
    BOOLEAN			GetLowSpeed() const;
    UCHAR			GetHubPort() const;
    IUsbDevice		*GetParent() const;
    IUsbDevice		*GetFirstChild() const;
    IUsbDevice		*GetSibling() const;
    IUsbDevice		*FindChild(UCHAR PortNumber) const;
    void			InsertChild(IUsbDevice *child);
    BOOLEAN			RemoveChild(IUsbDevice *child);
    BOOLEAN			IsEnumTime() const;
    PNP_CLASS_ID    GetClassId() const;
    /* public helper function*/
    void            SetExternalPort();
	#ifndef SILVER
	void            SetExternalPortWithHub(IUsbDevice **pParentArray, UINT DeviceIndex);
	void            SetExternalPortWithoutHub(IUsbDevice **pParentArray, UINT DeviceIndex);
	#endif

    //
    //  These are not declared private as most of the code is already coded in C
    //  and manipulates this class directly.
    //
    UCHAR   m_Type;
    union
    {
        UCHAR   m_Parent;
        UCHAR   m_NextFree;
    };
    union
    {
        UCHAR   m_FirstChild;
        UCHAR   m_bInterfaceNumber;
    };
    UCHAR           m_Sibling;

    UCHAR           m_PortNumber;
    union
    {
        UCHAR   m_Address;        
        UCHAR   m_RetryCount;
    };
    UCHAR           m_MaxPacket0;
    UCHAR           m_ClassSpecificType;

    PVOID           m_DefaultEndpoint;
    PUSBD_HOST_CONTROLLER m_HostController;

    union
    {
        PUSB_CLASS_DRIVER_DESCRIPTION   m_ClassDriver;
        IUsbDevice                      *m_NextPending;
    };
    LONG            m_ExternalPort;
    union
    {
        LARGE_INTEGER  m_EarliestEnumTime;
        struct
        {
            ULONG           m_DataToggleBits;
            PVOID			m_ClassDriverExtension;
        };
    };
    
    /* IUsbDevice helpers, these are only called internally so can be private */
    private:
    USBD_STATUS OpenDefaultEndpoint(PURB Urb);
    USBD_STATUS CloseDefaultEndpoint(PURB Urb);
};
//--------------------------------------------------------------------------------
//  Hub driver must implement this method
//--------------------------------------------------------------------------------
extern VOID USBHUB_DisableResetPort(
	                    IN IUsbDevice *HubDevice,
	                    IN UCHAR PortNumber,
	                    IN PVOID Context,
                        IN BOOLEAN Disable
	                    );
//--------------------------------------------------------------------------------
//  Enum Stages, mostly for debugging really
//--------------------------------------------------------------------------------
#define USBD_ENUM_DEVICE_CONNECTED 0x80
#define USBD_ENUM_STAGE_0 0
#define USBD_ENUM_STAGE_PRE1 0x81
#define USBD_ENUM_STAGE_1 1
#define USBD_ENUM_STAGE_2 2
#define USBD_ENUM_STAGE_3 3
#define USBD_ENUM_STAGE_PRE4 0x84
#define USBD_ENUM_STAGE_4 4
#define USBD_ENUM_STAGE_5 5
#define USBD_ENUM_STAGE_6 6
#define USBD_ENUM_STAGE_ADD_COMPLETE 7
#define USBD_ENUM_STAGE_ABORT1 8
#define USBD_ENUM_STAGE_DISABLE_COMPLETE 9
#define USBD_ENUM_STAGE_ABORT2 10

//--------------------------------------------------------------------------------
//  CDeviceTree keeps track of all the devices
//--------------------------------------------------------------------------------
#define USBD_MAX_CONFIG_DESC_SIZE     80
#define USBD_DEFAULT_MAXPACKET0       8
#define USBD_CONTROL_TD_QUOTA         (USBD_MAX_CONFIG_DESC_SIZE/USBD_DEFAULT_MAXPACKET0) + 3 //the three is for SETUP, SETUP's data and STATUS
#define USBD_BASE_NODES_PER_PORT      4

class CDeviceTree
{
    public:

    //
    //  There is no defined c'tor, because there is no way
    //  to make sure that it gets called.
    //

    void Init(ULONG NodeCount, ULONG MaxCompositeInterfaces);
    IUsbDevice *AllocDevice() { 
            UCHAR nodeIndex = m_FirstFree;
            ASSERT(UDN_INVALID_NODE_INDEX != nodeIndex);
            m_FirstFree = m_Devices[nodeIndex].m_NextFree;
            m_Devices[nodeIndex].m_Parent = UDN_INVALID_NODE_INDEX;
            m_Devices[nodeIndex].m_FirstChild = UDN_INVALID_NODE_INDEX;
            m_Devices[nodeIndex].m_Sibling = UDN_INVALID_NODE_INDEX;
            m_Devices[nodeIndex].m_ClassDriverExtension = NULL;
            m_Devices[nodeIndex].m_ClassSpecificType = 0xFF;
            return m_Devices + nodeIndex;
            }
    VOID FreeDevice(IUsbDevice *usbDevice) { 
            ASSERT(usbDevice >= m_Devices);
            UCHAR nodeIndex = usbDevice - m_Devices;
            ASSERT(UDN_INVALID_NODE_INDEX > nodeIndex);
            m_Devices[nodeIndex].m_Type = UDN_TYPE_UNUSED;
            m_Devices[nodeIndex].m_NextFree = m_FirstFree;
            m_FirstFree = nodeIndex;
            }
    
    BOOLEAN                     m_InProgress;
    BOOLEAN                     m_DeviceRemoved;
    BOOLEAN                     m_RetryCount;
    UCHAR                       m_EnumStage;
    URB                         m_EnumUrb;
    KDPC                        m_EnumDpc;
    KTIMER                      m_EnumTimer;
    UCHAR                       m_TimerReason;
    UCHAR                       m_FirstFree;
    UCHAR                       m_NodeCount;
    UCHAR                       m_MaxCompositeInterfaces;
    IUsbDevice                  *m_FirstPendingEnum;
    IUsbDevice                  *m_CurrentEnum;
    USB_DEVICE_DESCRIPTOR8      m_DeviceDescriptor;
    UCHAR                       m_ConfigurationDescriptorBuffer[USBD_MAX_CONFIG_DESC_SIZE];
    PUSB_INTERFACE_DESCRIPTOR   m_InterfaceDescriptor;
    IUsbDevice                  *m_Devices;
};
extern CDeviceTree g_DeviceTree;
#define USBD_TIMER_REASON_STAGE0            0
#define USBD_TIMER_REASON_WATCHDOG          1
#define USBD_TIMER_REASON_CONTINUE_STAGE1   2
#define USBD_TIMER_REASON_CONTINUE_STAGE4   3
/**************************************************
***  Implementation of IUsbDevice inline functions
*********/
inline UCHAR
IUsbDevice::GetIndex() const
/*++
    Gets the index of this device in the global static tree.
--*/
{return (UCHAR)(this - g_DeviceTree.m_Devices);}

inline BOOLEAN
IUsbDevice::GetLowSpeed() const
/*++
    Returns true if the device is lowspeed.
    THIS WILL BE REMOVED WHEN SUPPORT FOR LOWSPEED IS DROPPED.
--*/
{return m_PortNumber & UDN_LOWSPEED_PORT ? TRUE : FALSE;}

inline UCHAR
IUsbDevice::GetHubPort() const
/*++
    Get the portnumber regardless of lowspeed or not.
--*/
{return m_PortNumber & ~UDN_LOWSPEED_PORT;}

inline IUsbDevice *
IUsbDevice::GetParent() const
/*++
    Returns a pointer to the parent.  NULL if there is no parent.
--*/
{return (UDN_INVALID_NODE_INDEX != m_Parent) ? (g_DeviceTree.m_Devices + m_Parent) : NULL;}

inline IUsbDevice *
IUsbDevice::GetFirstChild() const
/*++
    Returns a pointer to the first child.  NULL if there are no children.
--*/
{return (UDN_INVALID_NODE_INDEX != m_FirstChild) ? (g_DeviceTree.m_Devices + m_FirstChild) : NULL;}

inline IUsbDevice *
IUsbDevice::GetSibling() const
/*++
    Returns a pointer to the next sibling.  NULL if this is the last sibling.
--*/
{return (UDN_INVALID_NODE_INDEX != m_Sibling) ? (g_DeviceTree.m_Devices + m_Sibling) : NULL;}
   
//------------------------------------------------------------------------
//  Methods used across modules
//------------------------------------------------------------------------
PUSB_CLASS_DRIVER_DESCRIPTION 
USBD_FindClassDriver(
	IN PNP_CLASS_ID ClassId
	);

//------------------------------------------------
//  Needed in ISBD_Init were we initialize the
//  the DPC for timing when to start enumeration.
//------------------------------------------------
void    
USBD_DeviceEnumTimerProc(
    IN PKDPC Dpc,
    IN PVOID Unused1,
    IN PVOID Unused2,
    IN PVOID Unused3
    );

//------------------------------------------------
//  Entry Point XAPI must call
//------------------------------------------------
EXTERNUSB VOID USBD_Init(DWORD NumDeviceTypes, PXDEVICE_PREALLOC_TYPE DeviceTypes);
//--------------------------------------------------------------------------------
//  Interface between the host controller driver and usbd
//--------------------------------------------------------------------------------
extern "C" {

//
// HCD specific URBs
//
#define USBD_EP_FLAG_LOWSPEED                0x0001
#define USBD_EP_FLAG_NEVERHALT               0x0002

//
// Common transfer request definition, all transfer
// requests passed to the HCD will be mapped to this
// format.  The HCD will can use this structure to
// reference fields that are common to all transfers
// as well as fields specific to isochronous and
// control transfers.

//
// bandwidth related definitions
//

// overhead in bytes/ms

#define USB_ISO_OVERHEAD_BYTES              9
#define USB_INTERRUPT_OVERHEAD_BYTES        13

  
//-------------------------------------------------------------
// Utility procedures supported by USB System Driver
//-------------------------------------------------------------
VOID
USBD_CompleteRequest(
    IN  PURB Urb
    );

USHORT
USBD_CalculateUsbBandwidth(
    IN USHORT   MaxPacketSize,
    IN UCHAR    EndpointType,
    IN BOOLEAN  LowSpeed
    );

VOID
USBD_DeviceConnected(
    IN  PVOID    HcdExtension,
    IN  UCHAR    PortNumber
    );

VOID
USBD_DeviceDisconnected(
    IN  PVOID HcdExtension,
    IN  UCHAR PortNumber
    );

VOID
USBD_NewHostController(
    IN PPCI_DEVICE_DESCRIPTOR PciDevice,
	IN ULONG HcdDeviceExtensionSize
    );

//-------------------------------------------------------------
// Procedures which must be exported by Host Controller Driver
//-------------------------------------------------------------
VOID
HCD_DriverEntry(
    PHCD_RESOURCE_REQUIREMENTS ResourceRequirements
    );

VOID
HCD_EnumHardware();

NTSTATUS
HCD_NewHostController(
    IN PVOID  HcdExtension,
    IN UCHAR  HostControllerNumber,
    IN PPCI_DEVICE_DESCRIPTOR PciDevice
    );

USBD_STATUS
HCD_SubmitRequest(
    IN PVOID HcdExtension,
    IN PURB Urb
    );

USBD_STATUS
HCD_CancelRequest(
    IN PVOID HcdExtension,
    IN PURB  Urb
    );

typedef
VOID
(*PFNHCD_RESET_COMPLETE)(
    IN USBD_STATUS  Status,
    IN PVOID        Context
    );

VOID
HCD_ResetRootHubPort(
    IN PVOID                    HcdExtension,
    IN ULONG                    PortNumber,
    IN PFNHCD_RESET_COMPLETE    ResetCompleteProc,
    IN PVOID                    CompleteContext
    );

VOID
HCD_DisableRootHubPort(
    IN PVOID                    HcdExtension,
    IN ULONG                    PortNumber
    );

} //end 'extern "C"'

#endif //__USB_X__


