/********************************************/
/*USB Code                                  */
/*PIC32MX795F512L-80I/PF                    */
/*PIC32MX695F512L-80I/PF                    */
/********************************************/
/*XC32 version                              */
/********************************************/

#ifndef _USB_H_
#define _USB_H_

#include <xc.h>
#include <limits.h>
#include <stdbool.h>

//#include "GenericTypeDefs.h"
#define __EXTENSION


#define ConvertToPhysicalAddress(a) ((uint32_t)KVA_TO_PA(a))
#define CTRL_TRF_SETUP_ADDR_TAG
#define CTRL_TRF_DATA_ADDR_TAG


void ProcessIO(void);
void USB_Init(void);
void USBEnableEndpoint(uint8_t ep, uint8_t options);
void* USBTransferOnePacket(uint8_t ep,uint8_t dir,uint8_t* data,uint8_t len);
void USBCheckVendorRequest(void);
void USBDeviceAttach(void);
void DisplayUSBData(void);

typedef union
{
    struct
    {
        unsigned char ping_pong_state :1;
        unsigned char transfer_terminated :1;
    } bits;
    uint8_t Val;
}EP_STATUS;

typedef union
{
    uint8_t    bitmap;
    struct
    {
        uint8_t ep_num:    4;
        uint8_t zero_pkt:  1;
        uint8_t dts:       1;
        uint8_t force_dts: 1;
        uint8_t direction: 1;
    }field;

} TRANSFER_FLAGS;

typedef enum
{
    // No event occured (NULL event)
    EVENT_NONE = 0,

    EVENT_DEVICE_STACK_BASE = 1,

    EVENT_HOST_STACK_BASE = 100,

    // A USB hub has been attached.  Hub support is not currently available.
    EVENT_HUB_ATTACH,           
    
    // A stall has occured.  This event is not used by the Host stack.
    EVENT_STALL,                  
    
    // VBus SRP Pulse, (VBus > 2.0v),  Data: BYTE Port Number (For future support)
    EVENT_VBUS_SES_REQUEST,     
    
    // The voltage on Vbus has dropped below 4.4V/4.7V.  The application is 
    // responsible for monitoring Vbus and calling USBHostVbusEvent() with this
    // event.  This event is not generated by the stack.
    EVENT_VBUS_OVERCURRENT,     
    
    // An enumerating device is requesting power.  The data associated with this
    // event is of the data type USB_VBUS_POWER_EVENT_DATA.  Note that 
    // the requested current is specified in 2mA units, identical to the power
    // specification in a device's Configuration Descriptor.
    EVENT_VBUS_REQUEST_POWER,   
    
    // Release power from a detaching device. The data associated with this
    // event is of the data type USB_VBUS_POWER_EVENT_DATA.  The current value
    // specified in the data can be ignored.
    EVENT_VBUS_RELEASE_POWER,   
    
    // The voltage on Vbus is good, and the USB OTG module can be powered on.  
    // The application is responsible for monitoring Vbus and calling 
    // USBHostVbusEvent() with this event.  This event is not generated by the 
    // stack.  If the application issues an EVENT_VBUS_OVERCURRENT, then no
    // power will be applied to that port, and no device can attach to that
    // port, until the application issues the EVENT_VBUS_POWER_AVAILABLE for
    // the port.
    EVENT_VBUS_POWER_AVAILABLE, 
    
    // The attached device is not supported by the application.  The attached
    // device is not allowed to enumerate.
    EVENT_UNSUPPORTED_DEVICE,   
    
    // Cannot enumerate the attached device.  This is generated if communication
    // errors prevent the device from enumerating.
    EVENT_CANNOT_ENUMERATE,     
    
    // The client driver cannot initialize the the attached device.  The 
    // attached is not allowed to enumerate.
    EVENT_CLIENT_INIT_ERROR,    
    
    // Unspecified host error. (This error should not occur).
    EVENT_UNSPECIFIED_ERROR,     
             
    // USB cable has been detached.  The data associated with this event is the
    // address of detached device, a single BYTE.
    EVENT_DETACH, 
     
    // A USB transfer has completed.  
    EVENT_TRANSFER,
    
    // A USB Start of Frame token has been received.
    EVENT_SOF,                  
    
    // Device-mode resume received.  This event is not used by the Host stack.
    EVENT_RESUME,
    
    // Device-mode suspend/idle event received.  This event is not used by the
    // Host stack.
    EVENT_SUSPEND,
                  
    // Device-mode bus reset received.  This event is not used by the Host 
    // stack.                  
    EVENT_RESET,  
    
    // Class-defined event offsets start here:
    EVENT_GENERIC_BASE  = 400,      // Offset for Generic class events

    EVENT_MSD_BASE      = 500,      // Offset for Mass Storage Device class events

    EVENT_HID_BASE      = 600,      // Offset for Human Interface Device class events

    EVENT_PRINTER_BASE  = 700,      // Offset for Printer class events
    
    EVENT_CDC_BASE      = 800,      // Offset for CDC class events

    EVENT_CHARGER_BASE  = 900,      // Offset for Charger client driver events.

    EVENT_AUDIO_BASE    = 1000,      // Offset for Audio client driver events.
        
	EVENT_USER_BASE     = 10000,    // Add integral values to this event number
                                    // to create user-defined events.

    // There was a transfer error on the USB.  The data associated with this
    // event is of data type HOST_TRANSFER_DATA.
    EVENT_BUS_ERROR     = INT_MAX  

} USB_EVENT;

//MS OS descriptor stuff for WinUSB
#define MICROSOFT_OS_DESCRIPTOR_INDEX   (unsigned char)0xEE //Magic string index number for the Microsoft OS descriptor
#define GET_MS_DESCRIPTOR               (unsigned char)0xEE //(arbitarily assigned, but should not clobber/overlap normal bRequests)
#define EXTENDED_COMPAT_ID              (uint16_t)0x0004
#define EXTENDED_PROPERTIES             (uint16_t)0x0005

typedef struct __attribute__ ((packed)) _MS_OS_DESCRIPTOR
{
    uint8_t bLength;
    uint8_t bDscType;
    uint16_t string[7];
    uint8_t vendorCode;
    uint8_t bPad;
}MS_OS_DESCRIPTOR;

typedef struct __attribute__ ((packed)) _MS_COMPAT_ID_FEATURE_DESC
{
    uint32_t dwLength;
    uint16_t bcdVersion;
    uint16_t wIndex;
    uint8_t bCount;
    uint8_t Reserved[7];
    uint8_t bFirstInterfaceNumber;
    uint8_t Reserved1;
    uint8_t compatID[8];
    uint8_t subCompatID[8];
    uint8_t Reserved2[6];
} MS_COMPAT_ID_FEATURE_DESC;

typedef struct __attribute__ ((packed)) _MS_EXT_PROPERTY_FEATURE_DESC
{
    uint32_t dwLength;
    uint16_t bcdVersion;
    uint16_t wIndex;
    uint16_t wCount;
    uint32_t dwSize;
    uint32_t dwPropertyDataType;uint16_t wPropertyNameLength;
    uint16_t bPropertyName[20];
    uint32_t dwPropertyDataLength;
    uint16_t bPropertyData[39];
}MS_EXT_PROPERTY_FEATURE_DESC;

extern const MS_OS_DESCRIPTOR MSOSDescriptor;
extern const MS_COMPAT_ID_FEATURE_DESC CompatIDFeatureDescriptor;
extern const MS_EXT_PROPERTY_FEATURE_DESC ExtPropertyFeatureDescriptor;

#define USB_DESCRIPTOR_DEVICE           0x01    // bDescriptorType for a Device Descriptor.
#define USB_DESCRIPTOR_CONFIGURATION    0x02    // bDescriptorType for a Configuration Descriptor.
#define USB_DESCRIPTOR_STRING           0x03    // bDescriptorType for a String Descriptor.
#define USB_DESCRIPTOR_INTERFACE        0x04    // bDescriptorType for an Interface Descriptor.
#define USB_DESCRIPTOR_ENDPOINT         0x05    // bDescriptorType for an Endpoint Descriptor.
#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06    // bDescriptorType for a Device Qualifier.
#define USB_DESCRIPTOR_OTHER_SPEED      0x07    // bDescriptorType for a Other Speed Configuration.
#define USB_DESCRIPTOR_INTERFACE_POWER  0x08    // bDescriptorType for Interface Power.
#define USB_DESCRIPTOR_OTG              0x09    // bDescriptorType for an OTG Descriptor.

typedef struct __attribute__ ((packed)) _USB_DEVICE_DESCRIPTOR
{
    uint8_t bLength;               // Length of this descriptor.
    uint8_t bDescriptorType;       // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
    uint16_t bcdUSB;                // USB Spec Release Number (BCD).
    uint8_t bDeviceClass;          // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
    uint8_t bDeviceSubClass;       // Subclass code (assigned by the USB-IF).
    uint8_t bDeviceProtocol;       // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
    uint8_t bMaxPacketSize0;       // Maximum packet size for endpoint 0.
    uint16_t idVendor;              // Vendor ID (assigned by the USB-IF).
    uint16_t idProduct;             // Product ID (assigned by the manufacturer).
    uint16_t bcdDevice;             // Device release number (BCD).
    uint8_t iManufacturer;         // Index of String Descriptor describing the manufacturer.
    uint8_t iProduct;              // Index of String Descriptor describing the product.
    uint8_t iSerialNumber;         // Index of String Descriptor with the device's serial number.
    uint8_t bNumConfigurations;    // Number of possible configurations.
} USB_DEVICE_DESCRIPTOR;


typedef struct __attribute__ ((packed)) _USB_CONFIGURATION_DESCRIPTOR
{
    uint8_t bLength;               // Length of this descriptor.
    uint8_t bDescriptorType;       // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
    uint16_t wTotalLength;          // Total length of all descriptors for this configuration.
    uint8_t bNumInterfaces;        // Number of interfaces in this configuration.
    uint8_t bConfigurationValue;   // Value of this configuration (1 based).
    uint8_t iConfiguration;        // Index of String Descriptor describing the configuration.
    uint8_t bmAttributes;          // Configuration characteristics.
    uint8_t bMaxPower;             // Maximum power consumed by this configuration.
} USB_CONFIGURATION_DESCRIPTOR;

typedef struct __attribute__ ((packed)) _USB_INTERFACE_DESCRIPTOR
{
    uint8_t bLength;               // Length of this descriptor.
    uint8_t bDescriptorType;       // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
    uint8_t bInterfaceNumber;      // Number of this interface (0 based).
    uint8_t bAlternateSetting;     // Value of this alternate interface setting.
    uint8_t bNumEndpoints;         // Number of endpoints in this interface.
    uint8_t bInterfaceClass;       // Class code (assigned by the USB-IF).  0xFF-Vendor specific.
    uint8_t bInterfaceSubClass;    // Subclass code (assigned by the USB-IF).
    uint8_t bInterfaceProtocol;    // Protocol code (assigned by the USB-IF).  0xFF-Vendor specific.
    uint8_t iInterface;            // Index of String Descriptor describing the interface.
} USB_INTERFACE_DESCRIPTOR;

typedef struct __attribute__ ((packed)) _USB_ENDPOINT_DESCRIPTOR
{
    uint8_t bLength;               // Length of this descriptor.
    uint8_t bDescriptorType;       // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
    uint8_t bEndpointAddress;      // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
    uint8_t bmAttributes;          // Endpoint transfer type.
    uint16_t wMaxPacketSize;        // Maximum packet size.
    uint8_t bInterval;             // Polling interval in frames.
} USB_ENDPOINT_DESCRIPTOR;

typedef struct
{
    uint8_t    index;
    uint8_t    type;
    uint16_t  language_id;

} DESCRIPTOR_ID;

// ******************************************************************
// Section: USB Setup Packet Structure
// ******************************************************************
// This structure describes the data contained in a USB standard device
// request's setup packet.  It is the data packet sent from the host to
// the device to control and configure the device.
//
// Note: Refer to the USB 2.0 specification for additional details on the
// usage of the setup packet and standard device requests.
typedef union
{
    uint8_t Val;
    struct __PACKED
    {
        __EXTENSION uint8_t b0:1;
        __EXTENSION uint8_t b1:1;
        __EXTENSION uint8_t b2:1;
        __EXTENSION uint8_t b3:1;
        __EXTENSION uint8_t b4:1;
        __EXTENSION uint8_t b5:1;
        __EXTENSION uint8_t b6:1;
        __EXTENSION uint8_t b7:1;
    } bits;
} BYTE_VAL, BYTE_BITS;


typedef union __attribute__ ((packed))
{
    /** Standard Device Requests ***********************************/
    struct __attribute__ ((packed))
    {
        uint8_t bmRequestType; //from table 9-2 of USB2.0 spec
        uint8_t bRequest; //from table 9-2 of USB2.0 spec
        uint16_t wValue; //from table 9-2 of USB2.0 spec
        uint16_t wIndex; //from table 9-2 of USB2.0 spec
        uint16_t wLength; //from table 9-2 of USB2.0 spec
    };

    struct __attribute__ ((packed))
    {
        unsigned Recipient:5;   //Device,Interface,Endpoint,Other
        unsigned RequestType:2; //Standard,Class,Vendor,Reserved
        unsigned DataDir:1;     //Host-to-device,Device-to-host
        unsigned :8;
        uint8_t bFeature;          //DEVICE_REMOTE_WAKEUP,ENDPOINT_HALT
        unsigned :8;
        unsigned :8;
        unsigned :8;
        unsigned :8;
        unsigned :8;
    };

    struct __attribute__ ((packed))
    {
        unsigned :8;
        unsigned :8;
        uint8_t bDscIndex;         //For Configuration and String DSC Only
        uint8_t bDescriptorType;          //Device,Configuration,String
        uint16_t wLangID;           //Language ID
        unsigned :8;
        unsigned :8;
    };
    struct __attribute__ ((packed))
    {
        unsigned :8;
        unsigned :8;
        BYTE_VAL bDevADR;       //Device Address 0-127
        uint8_t bDevADRH;          //Must equal zero
        unsigned :8;
        unsigned :8;
        unsigned :8;
        unsigned :8;
    };
    struct __attribute__ ((packed))
    {
        unsigned :8;
        unsigned :8;
        uint8_t bConfigurationValue;         //Configuration Value 0-255
        uint8_t bCfgRSD;           //Must equal zero (Reserved)
        unsigned :8;
        unsigned :8;
        unsigned :8;
        unsigned :8;
    };
    struct __attribute__ ((packed))
    {
        unsigned :8;
        unsigned :8;
        uint8_t bAltID;            //Alternate Setting Value 0-255
        uint8_t bAltID_H;          //Must equal zero
        uint8_t bIntfID;           //Interface Number Value 0-255
        uint8_t bIntfID_H;         //Must equal zero
        unsigned :8;
        unsigned :8;
    };
    struct __attribute__ ((packed))
    {
        unsigned :8;
        unsigned :8;
        unsigned :8;
        unsigned :8;
        unsigned EPNum:4;       //Endpoint Number 0-15
        unsigned :3;
        unsigned EPDir:1;       //Endpoint Direction: 0-OUT, 1-IN
        unsigned :8;
        unsigned :8;
        unsigned :8;
    };
} CTRL_TRF_SETUP, SETUP_PKT, *PSETUP_PKT;


// ******************************************************************
// ******************************************************************
// Section: USB Specification Constants
// ******************************************************************
// ******************************************************************

#define USB_REQUEST_GET_STATUS                  0       // Standard Device Request - GET STATUS
#define USB_REQUEST_CLEAR_FEATURE               1       // Standard Device Request - CLEAR FEATURE
#define USB_REQUEST_SET_FEATURE                 3       // Standard Device Request - SET FEATURE
#define USB_REQUEST_SET_ADDRESS                 5       // Standard Device Request - SET ADDRESS
#define USB_REQUEST_GET_DESCRIPTOR              6       // Standard Device Request - GET DESCRIPTOR
#define USB_REQUEST_SET_DESCRIPTOR              7       // Standard Device Request - SET DESCRIPTOR
#define USB_REQUEST_GET_CONFIGURATION           8       // Standard Device Request - GET CONFIGURATION
#define USB_REQUEST_SET_CONFIGURATION           9       // Standard Device Request - SET CONFIGURATION
#define USB_REQUEST_GET_INTERFACE               10      // Standard Device Request - GET INTERFACE
#define USB_REQUEST_SET_INTERFACE               11      // Standard Device Request - SET INTERFACE
#define USB_REQUEST_SYNCH_FRAME                 12      // Standard Device Request - SYNCH FRAME

#define USB_SETUP_HOST_TO_DEVICE                0x00    // Device Request bmRequestType transfer direction - host to device transfer
#define USB_SETUP_DEVICE_TO_HOST                0x80    // Device Request bmRequestType transfer direction - device to host transfer
#define USB_SETUP_TYPE_STANDARD                 0x00    // Device Request bmRequestType type - standard
#define USB_SETUP_TYPE_CLASS                    0x20    // Device Request bmRequestType type - class
#define USB_SETUP_TYPE_VENDOR                   0x40    // Device Request bmRequestType type - vendor
#define USB_SETUP_RECIPIENT_DEVICE              0x00    // Device Request bmRequestType recipient - device
#define USB_SETUP_RECIPIENT_INTERFACE           0x01    // Device Request bmRequestType recipient - interface
#define USB_SETUP_RECIPIENT_ENDPOINT            0x02    // Device Request bmRequestType recipient - endpoint
#define USB_SETUP_RECIPIENT_OTHER               0x03    // Device Request bmRequestType recipient - other

#define USB_SETUP_HOST_TO_DEVICE_BITFIELD       (USB_SETUP_HOST_TO_DEVICE>>7)       // Device Request bmRequestType transfer direction - host to device transfer - bit definition
#define USB_SETUP_DEVICE_TO_HOST_BITFIELD       (USB_SETUP_DEVICE_TO_HOST>>7)       // Device Request bmRequestType transfer direction - device to host transfer - bit definition
#define USB_SETUP_TYPE_STANDARD_BITFIELD        (USB_SETUP_TYPE_STANDARD>>5)        // Device Request bmRequestType type - standard
#define USB_SETUP_TYPE_CLASS_BITFIELD           (USB_SETUP_TYPE_CLASS>>5)           // Device Request bmRequestType type - class
#define USB_SETUP_TYPE_VENDOR_BITFIELD          (USB_SETUP_TYPE_VENDOR>>5)          // Device Request bmRequestType type - vendor
#define USB_SETUP_RECIPIENT_DEVICE_BITFIELD     (USB_SETUP_RECIPIENT_DEVICE)        // Device Request bmRequestType recipient - device
#define USB_SETUP_RECIPIENT_INTERFACE_BITFIELD  (USB_SETUP_RECIPIENT_INTERFACE)     // Device Request bmRequestType recipient - interface
#define USB_SETUP_RECIPIENT_ENDPOINT_BITFIELD   (USB_SETUP_RECIPIENT_ENDPOINT)      // Device Request bmRequestType recipient - endpoint
#define USB_SETUP_RECIPIENT_OTHER_BITFIELD      (USB_SETUP_RECIPIENT_OTHER)         // Device Request bmRequestType recipient - other

/********************************************************************
USB Endpoint Definitions
USB Standard EP Address Format: DIR:X:X:X:EP3:EP2:EP1:EP0
This is used in the descriptors. 
********************************************************************/
#define _EP_IN      0x80
#define _EP_OUT     0x00
#define _EP01_OUT   0x01
#define _EP01_IN    0x81

/* Configuration Attributes */
#define _DEFAULT    (0x01<<7)       //Default Value (Bit 7 is set)
#define _SELF       (0x01<<6)       //Self-powered (Supports if set)
#define _RWU        (0x01<<5)       //Remote Wakeup (Supports if set)
#define _HNP	    (0x01 << 1)     //HNP (Supports if set)
#define _SRP	  	(0x01)		    //SRP (Supports if set)

/* Endpoint Transfer Type */
#define _CTRL       0x00            //Control Transfer
#define _ISO        0x01            //Isochronous Transfer
#define _BULK       0x02            //Bulk Transfer

//These are the directional indicators used for the USBTransferOnePacket() function.
#define OUT_FROM_HOST 0
#define IN_TO_HOST 1

#define USB_EP0_ROM            0x00     //Data comes from RAM
#define USB_EP0_RAM            0x01     //Data comes from const
#define USB_EP0_BUSY           0x80     //The PIPE is busy
#define USB_EP0_INCLUDE_ZERO   0x40     //include a trailing zero packet
#define USB_EP0_NO_DATA        0x00     //no data to send
#define USB_EP0_NO_OPTIONS     0x00     //no options set

/********************************************************************
 * Standard Request Codes
 * USB 2.0 Spec Ref Table 9-4
 *******************************************************************/

/* USB Device States as returned by USBGetDeviceState().  Only the defintions
   for these states should be used.  The actual value for each state should
   not be relied upon as constant and may change based on the implementation. */
typedef enum
{
    /* Detached is the state in which the device is not attached to the bus.  When
    in the detached state a device should not have any pull-ups attached to either
    the D+ or D- line.  */
    DETACHED_STATE 
    /*DOM-IGNORE-BEGIN*/    = 0x00                         /*DOM-IGNORE-END*/,
    /* Attached is the state in which the device is attached ot the bus but the
    hub/port that it is attached to is not yet configured. */
    ATTACHED_STATE
    /*DOM-IGNORE-BEGIN*/    = 0x01                         /*DOM-IGNORE-END*/,
    /* Powered is the state in which the device is attached to the bus and the 
    hub/port that it is attached to is configured. */
    POWERED_STATE
    /*DOM-IGNORE-BEGIN*/    = 0x02                         /*DOM-IGNORE-END*/,
    /* Default state is the state after the device receives a RESET command from
    the host. */
    DEFAULT_STATE
    /*DOM-IGNORE-BEGIN*/    = 0x04                         /*DOM-IGNORE-END*/,
    /* Address pending state is not an official state of the USB defined states.
    This state is internally used to indicate that the device has received a 
    SET_ADDRESS command but has not received the STATUS stage of the transfer yet.
    The device is should not switch addresses until after the STATUS stage is
    complete.  */
    ADR_PENDING_STATE
    /*DOM-IGNORE-BEGIN*/    = 0x08                         /*DOM-IGNORE-END*/,
    /* Address is the state in which the device has its own specific address on the
    bus. */
    ADDRESS_STATE
    /*DOM-IGNORE-BEGIN*/    = 0x10                         /*DOM-IGNORE-END*/,
    /* Configured is the state where the device has been fully enumerated and is
    operating on the bus.  The device is now allowed to excute its application
    specific tasks.  It is also allowed to increase its current consumption to the
    value specified in the configuration descriptor of the current configuration.
    */
    CONFIGURED_STATE
    /*DOM-IGNORE-BEGIN*/    = 0x20                        /*DOM-IGNORE-END*/
} USB_DEVICE_STATE;


/* USB device stack events description here - DWF */
typedef enum
{
    // Notification that a SET_CONFIGURATION() command was received (device)
    EVENT_CONFIGURED
    /*DOM-IGNORE-BEGIN*/    = EVENT_DEVICE_STACK_BASE        /*DOM-IGNORE-END*/,

    // A SET_DESCRIPTOR request was received (device)
    EVENT_SET_DESCRIPTOR,

    // An endpoint 0 request was received that the stack did not know how to
    // handle.  This is most often a request for one of the class drivers.  
    // Please refer to the class driver documenation for information related
    // to what to do if this request is received. (device)
    EVENT_EP0_REQUEST,

//    // A USB transfer has completed.  The data associated with this event is of
//    // the data type HOST_TRANSFER_DATA if the event is generated from the host
//    // stack.
//    EVENT_TRANSFER,
//    
//    // A USB Start of Frame token has been received.  This event is not
//    // used by the Host stack.
//    EVENT_SOF,                  
//    
//    // Device-mode resume received.  This event is not used by the Host stack.
//    EVENT_RESUME,
//    
//    // Device-mode suspend/idle event received.  This event is not used by the
//    // Host stack.
//    EVENT_SUSPEND,
//                  
//    // Device-mode bus reset received.  This event is not used by the Host 
//    // stack.                  
//    EVENT_RESET,                
    
//    // Device Mode: A setup packet received (data: SETUP_PKT).  This event is
//    // not used by the Host stack.
//    EVENT_SETUP,

    // Device-mode USB cable has been attached.  This event is not used by the
    // Host stack.  The client driver may provide an application event when a
    // device attaches.
    EVENT_ATTACH,

    // A user transfer was terminated by the stack.  This event will pass back
    // the value of the handle that was terminated.  Compare this value against
    // the current valid handles to determine which transfer was terminated.
    EVENT_TRANSFER_TERMINATED

} USB_DEVICE_STACK_EVENTS;

typedef union __attribute__ ((packed))
{
    uint16_t Val;
    uint8_t v[2];
    struct __attribute__ ((packed))
    {
        uint8_t LB;
        uint8_t HB;
    } byte;
    struct __attribute__ ((packed))
    {
        __EXTENSION uint8_t b0:1;
        __EXTENSION uint8_t b1:1;
        __EXTENSION uint8_t b2:1;
        __EXTENSION uint8_t b3:1;
        __EXTENSION uint8_t b4:1;
        __EXTENSION uint8_t b5:1;
        __EXTENSION uint8_t b6:1;
        __EXTENSION uint8_t b7:1;
        __EXTENSION uint8_t b8:1;
        __EXTENSION uint8_t b9:1;
        __EXTENSION uint8_t b10:1;
        __EXTENSION uint8_t b11:1;
        __EXTENSION uint8_t b12:1;
        __EXTENSION uint8_t b13:1;
        __EXTENSION uint8_t b14:1;
        __EXTENSION uint8_t b15:1;
    } bits;
} WORD_VAL, WORD_BITS;

typedef struct __attribute__ ((packed))
{
    union __attribute__ ((packed))
    {
        //Various options of pointers that are available to
        // get the data from
        uint8_t *bRam;
        const uint8_t *bRom;
        uint16_t *wRam;
        const uint16_t *wRom;
    }pSrc;
    union __attribute__ ((packed))
    {
        struct __attribute__ ((packed))
        {
            //is this transfer from RAM or const?
            uint8_t ctrl_trf_mem          :1;
            uint8_t reserved              :5;
            //include a zero length packet after
            //data is done if data_size%ep_size = 0?
            uint8_t includeZero           :1;
            //is this PIPE currently in use
            uint8_t busy                  :1;
        }bits;
        uint8_t Val;
    }info;
    WORD_VAL __attribute__((aligned)) wCount;
}IN_PIPE;

typedef struct __attribute__ ((packed))
{
    union __attribute__ ((packed))
    {
        //Various options of pointers that are available to
        // get the data from
        uint8_t *bRam;
        uint16_t *wRam;
    }pDst;
    union __attribute__ ((packed))
    {
        struct __attribute__ ((packed))
        {
            uint8_t reserved              :7;
            //is this PIPE currently in use
            uint8_t busy                  :1;
        }bits;
        uint8_t Val;
    }info;
    WORD_VAL wCount;
    void (*pFunc)(void);
}OUT_PIPE;

extern volatile bool RemoteWakeup;
extern volatile bool USBBusIsSuspended;
extern volatile int USBDeviceState;

// Buffer Descriptor Status Register layout.
typedef union __attribute__ ((packed)) _BD_STAT 
{
    struct __attribute__ ((packed)){
        unsigned            :2;
        unsigned    BSTALL  :1;     //Buffer Stall Enable
        unsigned    DTSEN   :1;     //Data Toggle Synch Enable
        unsigned            :2;     //Reserved - write as 00
        unsigned    DTS     :1;     //Data Toggle Synch Value
        unsigned    UOWN    :1;     //USB Ownership
    };
    struct __attribute__ ((packed)){
        unsigned            :2;
        unsigned    PID0    :1;
        unsigned    PID1    :1;
        unsigned    PID2    :1;
        unsigned    PID3    :1;

    };
    struct __attribute__ ((packed)){
        unsigned            :2;
        unsigned    PID     :4;         //Packet Identifier
    };
    uint16_t           Val;
} BD_STAT;

// BDT Entry Layout
typedef union __attribute__ ((packed))__BDT
{
    struct __attribute__ ((packed))
    {
        BD_STAT         STAT;
        uint16_t        CNT:10;
        //Buffer Address
        uint32_t        ADR;                     
    };
    struct __attribute__ ((packed))
    {
        uint32_t        res  :16;
        uint32_t        count:10;
    };
    uint32_t            w[2];
    uint16_t            v[4];
    uint64_t               Val;
} BDT_ENTRY;

// USTAT Register Layout
typedef union __USTAT
{
    struct
    {
        unsigned char filler1           :2;
        unsigned char ping_pong         :1;
        unsigned char direction         :1;
        unsigned char endpoint_number   :4;
    };
    uint8_t Val;
} USTAT_FIELDS;

extern volatile IN_PIPE inPipes[1];
extern volatile OUT_PIPE outPipes[1];
extern volatile BDT_ENTRY* pBDTEntryOut[2];
extern volatile BDT_ENTRY* pBDTEntryIn[2];	

bool USBHALStallPipe( TRANSFER_FLAGS pipe );
bool USBHALUnstallPipe( TRANSFER_FLAGS pipe );
bool USBHALFlushPipe( TRANSFER_FLAGS pipe );
bool USBHALTransferData ( TRANSFER_FLAGS flags, void *buffer, unsigned int size);

#endif // _USB_H_

