/*
 *  Copyright (c) 1996-2007 Digi International Inc., All Rights Reserved
 *
 *  This software contains proprietary and confidential information of Digi
 *  International Inc.  By accepting transfer of this copy, Recipient agrees
 *  to retain this software in confidence, to prevent disclosure to others,
 *  and to make no use of this software other than that for which it was
 *  delivered.  This is an unpublished copyrighted work of Digi International
 *  Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 *  prohibited.
 *
 *  Restricted Rights Legend
 *
 *  Use, duplication, or disclosure by the Government is subject to
 *  restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 *  Technical Data and Computer Software clause at DFARS 252.227-7031 or
 *  subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 *  Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 *  Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
 *
 * usbHostApi.h - Public API for USB Host controller driver.
 *
 */

#ifndef __USB_HOST_H
#define __USB_HOST_H

#ifdef __cplusplus
extern "C" {
#endif

#include "bele.h"


/*ad*
 * This is the data structure used to maintain linked lists.
 *
 * This struct definition is used inside the definition of LIST_ENTRY
 * to declare self-referential pointers.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
*ad*/
struct  _LIST_ENTRY;

#ifdef AUTODOC_VERSION
/*ad*
 * This is the list processing structure for USB.  This data structure is used to maintain
 * linked lists.
 *
 * @param next Pointer to the next element in the list.
 *
 * @param prev Pointer to the previous element in the list.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
*ad*/
typedef struct _LIST_ENTRY
{
    struct _LIST_ENTRY  * next;
    struct _LIST_ENTRY  * prev;
} LIST_ENTRY;
#endif

#ifdef  LIST_ENTRY
#define LIST_ENTRY _0_
#error
#endif
#ifndef LIST_ENTRY_DEFINED_
#define LIST_ENTRY_DEFINED_
typedef struct _LIST_ENTRY
{
#ifdef NDS_SPECIFIC
    // Since WDM code needs next/prev to be called Flink/Blink, define
    // an unnamed union so either name may be used
    union {
        struct {
    struct _LIST_ENTRY  * next;
    struct _LIST_ENTRY  * prev;
        };
        struct {
            struct _LIST_ENTRY *Flink;
            struct _LIST_ENTRY *Blink;
        };
    };
#else
    struct _LIST_ENTRY  * next;
    struct _LIST_ENTRY  * prev;
#endif
} LIST_ENTRY;
#endif

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    LIST_ENTRY name = LIST_HEAD_INIT(name)

#define INIT_LIST_HEAD(ptr) do { \
     (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

#define list_entry(ptr, type, member) \
     ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

void    InsertHeadList(LIST_ENTRY *head, LIST_ENTRY *ptrItem);
void    InsertTailList(LIST_ENTRY *head, LIST_ENTRY *ptrItem);
void    RemoveEntryList(LIST_ENTRY *entry);
int     CheckForEmptyList(LIST_ENTRY *head);

/* Standard USB device request */
#ifdef NETOS_GNU_TOOLS
typedef struct
{
  unsigned char  requesttype;
  unsigned char  request;
  unsigned short value;
  unsigned short index;
  unsigned short length;
} __attribute__ ((packed)) devrequest;
#else
#pragma pack (1)
/*ad*
 * Device request data structure,
 *
 * @param requesttype Type of request.
 *
 * @param request The actual request
 *
 * @param value The value of the request.
 *
 * @param index  Value to put into index field.
 *
 * @param length Length of the request.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.2
*ad*/
typedef struct
{
  unsigned char  requesttype;
  unsigned char  request;
  unsigned short value;
  unsigned short index;
  unsigned short length;
} devrequest;
#endif


// FORMAT_SETUP_REQUEST
//  Endian-safe way to format USB 1.1 device requests

#define FORMAT_USB_DEVICE_REQUEST(devreq, req_type, req, val, ix, len)                   \
    do                                                                              \
    {                                                                               \
        (devreq)->requesttype       = req_type;                                     \
        (devreq)->request           = req;                                          \
        (devreq)->value             = TO_LE16(val);                                 \
        (devreq)->index             = TO_LE16(ix);                                  \
        (devreq)->length            = TO_LE16(len);                                 \
    } while (0)

typedef struct _usb_descriptor_header
{
    unsigned char   bLength;
    unsigned char   bDescrType;
} usb_descriptor_header, *pusb_descriptor_header;

#define NEXT_USB_DESCRIPTOR(this_descr)     \
    (pusb_descriptor_header)(((unsigned char *)this_descr) + this_descr->bLength)

#define USB_DESCRIPTOR_LEN(buf)              \
    (((pusb_descriptor_header)(buf))->bLength)

#define USB_DESCRIPTOR_TYPE(buf)             \
    (((pusb_descriptor_header)(buf))->bDescrType)

#define USB_DESCRIPTOR_TOTAL_LEN(buf)        \
    FROM_LE16((((usbConfigDescriptor *)(buf))->wTotalLength))





/*
 * Class codes
 */
#define USB_CLASS_HUB           9

/*
 * Descriptor types
 */
#define USB_DT_DEVICE           0x01
#define USB_DT_CONFIG           0x02
#define USB_DT_STRING           0x03
#define USB_DT_INTERFACE        0x04
#define USB_DT_ENDPOINT         0x05
#define USB_DT_QUALIFIER        0x06

#define USB_DT_HUB              0x29
#define USB_DT_HID              0x21

/*
 * Standard request defines
 */
#define USB_REQ_GET_STATUS          0x00
#define USB_REQ_CLEAR_FEATURE       0x01
/* 0x02 is reserved */
#define USB_REQ_SET_FEATURE         0x03
/* 0x04 is reserved */
#define USB_REQ_SET_ADDRESS         0x05
#define USB_REQ_GET_DESCRIPTOR      0x06
#define USB_REQ_SET_DESCRIPTOR      0x07
#define USB_REQ_GET_CONFIGURATION   0x08
#define USB_REQ_SET_CONFIGURATION   0x09
#define USB_REQ_GET_INTERFACE       0x0A
#define USB_REQ_SET_INTERFACE       0x0B
#define USB_REQ_SYNCH_FRAME         0x0C

/*Feature*/
#define USB_FEATURE_ENDPOINT_HALT 0
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1
/*
 * HIDD requests
 */
#define USB_REQ_GET_REPORT      0x01
#define USB_REQ_GET_IDLE        0x02
#define USB_REQ_GET_PROTOCOL    0x03
#define USB_REQ_SET_REPORT      0x09
#define USB_REQ_SET_IDLE        0x0A
#define USB_REQ_SET_PROTOCOL    0x0B

#define USB_TYPE_STANDARD       (0x00 << 5)
#define USB_TYPE_CLASS          (0x01 << 5)
#define USB_TYPE_VENDOR         (0x02 << 5)
#define USB_TYPE_RESERVED       (0x03 << 5)

#define USB_RECIP_DEVICE        0x00
#define USB_RECIP_INTERFACE     0x01
#define USB_RECIP_ENDPOINT      0x02
#define USB_RECIP_OTHER         0x03

/*
 * Request target types.
 */
#define USB_RT_DEVICE           0x00
#define USB_RT_INTERFACE        0x01
#define USB_RT_ENDPOINT         0x02

#define USB_RT_HUB              (USB_TYPE_CLASS | USB_RECIP_DEVICE)
#define USB_RT_PORT             (USB_TYPE_CLASS | USB_RECIP_OTHER)
#define USB_RT_HIDD             (USB_TYPE_CLASS | USB_RECIP_INTERFACE)

// These are the possible options for the Report Type field
// (High byte of wValue) for the HID Get/Set Report Request
#define USB_HID_REPORT_TYPE_INPUT   0x01
#define USB_HID_REPORT_TYPE_OUTPUT  0x02
#define USB_HID_REPORT_TYPE_FEATURE 0x03


#define USB_HID_REPORT_ID_UNUSED    0x00

#define USB_DEVICE_TO_HOST_REQ  0x80


/*ad*
 * This is the USB device number allocation bitmap. There's one bitmap
 * per USB tree.
 *
 * @param  devicemap Device map array.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
*ad*/
struct usb_devmap
{
    unsigned long devicemap[128 / (8*sizeof(unsigned long))];
};

/*
 * This is a USB device descriptor.
 *
 * USB device information
 *
 * Make this MUCH dynamic, right now
 * it contains enough information for
 * a USB floppy controller, and nothing
 * else.
 *
 * I'm not proud. I just want this dang
 * thing to start working.
 */
#define USB_MAXCONFIG       2
#define USB_MAXINTERFACES   5
#define USB_MAXENDPOINTS    8


#ifdef NETOS_GNU_TOOLS
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short bcdUSB;
    unsigned char  bDeviceClass;
    unsigned char  bDeviceSubClass;
    unsigned char  bDeviceProtocol;
    unsigned char  bMaxPacketSize0;
    unsigned short idVendor;
    unsigned short idProduct;
    unsigned short bcdDevice;
    unsigned char  iManufacturer;
    unsigned char  iProduct;
    unsigned char  iSerialNumber;
    unsigned char  bNumConfigurations;
}__attribute__ ((packed)) usbDeviceDescriptor;
#else
#pragma pack (1)
/*ad*
 * The usbDeviceDescriptor is the structure that corresponds to the
 * "standard device descriptor" described in section 9.6.1 of the
 * "Universal Serial Bus Specification Revision 2.0"; for more details,
 * see this document. The descriptor for a device is filled in when the
 * device first attaches to the bus and is updated by calling the
 * usbGetDeviceDescriptor routine.
 *
 * @param  bLength Descriptor length in bytes.
 *
 * @param bDescriptorType DEVICE Descriptor Type.
 *
 * @param bcdUSB USB Specification Release Number in
 * Binary-Coded Decimal (that is, 2.10 is 210H).
 * This field identifies the release of the USB
 * Specification with which the device and its
 * descriptors are compliant.
 *
 * @param bDeviceClass Class code (assigned by the USB-IF).
 * If this field is reset to zero, each interface
 * within a configuration specifies its own
 * class information and the various interfaces operate independently.
 * If this field is set to a value between 1 and
 * FEH, the device supports different class specifications on different
 * interfaces and the interfaces may not operate
 * independently. This value identifies the class definition used
 * for the aggregate interfaces. If this field is set to FFH, the device class
 * is vendor-specific.
 *
 * @param bDeviceSubClass Subclass code (assigned by the USB-IF).
 * These codes are qualified by the value of the bDeviceClass field.
 * If the bDeviceClass field is reset to zero, this field must also be
 * reset to zero. If the bDeviceClass field is not set to FFH,
 * all values are reserved for assignment by the USB-IF.
 *
 * @param bDeviceProtocol Protocol code (assigned by the USB-IF).
 * These codes are qualified by the value of
 * the bDeviceClass and the bDeviceSubClass fields. If a device
 * supports class-specific protocols on a device basis as opposed to an interface
 * basis, this code identifies the protocols that the device uses as defined by the
 * specification of the device class. If this field is reset to zero, the device
 * does not use class-specific protocols on a device basis. However, it may use class-specific
 * protocols on an interface basis. If this field is set to FFH, the device uses a
 * vendor-specific protocol on a device basis.
 *
 * @param bMaxPacketSize0 Maximum packet size for endpoint zero
 * (only 8, 16, 32, or 64 are valid)
 *
 * @param idVendor Vendor ID
 *
 * @param idProduct Product ID
 *
 * @param bcdDevice Device release number
 *
 * @param iManufacturer Manufacturer string index
 *
 * @param iProduct Product string index
 *
 * @param iSerialNumber Serial string index
 *
 * @param bNumConfigurations Number of possible configurations
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 * @see @link usb_get_device_descriptor
 * @see @link usbDevice
*ad*/
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short bcdUSB;
    unsigned char  bDeviceClass;
    unsigned char  bDeviceSubClass;
    unsigned char  bDeviceProtocol;
    unsigned char  bMaxPacketSize0;
    unsigned short idVendor;
    unsigned short idProduct;
    unsigned short bcdDevice;
    unsigned char  iManufacturer;
    unsigned char  iProduct;
    unsigned char  iSerialNumber;
    unsigned char  bNumConfigurations;
} usbDeviceDescriptor;
#endif


/* Due to packing issues... */
#define SIZEOF_DEVICE_DESCRIPTOR 18

#ifdef NETOS_GNU_TOOLS
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bEndpointAddress;
    unsigned char  bmAttributes;
    unsigned short wMaxPacketSize;
    unsigned char  bInterval;
} __attribute__ ((packed)) usbEndpointDescriptor;
#else
#pragma pack (1)
/*ad*
 * The usbEndpoint Descriptor is the structure that corresponds to the
 * "standard endpoint descriptor" described in section 9.6.6 of the
 * "Universal Serial Bus Specification Revision 2.0"; for more details,
 * see this document.
 *
 * @param bLength  Size of this descriptor in bytes.
 *
 * @param bDescriptorType Endpoint descriptor type.
 *
 * @param bEndpointAddress  The address of the endpoint on the USB device
 * described by this descriptor. The address is encoded as follows:
 *
 * <list type="unordered">
 * <item>Bit 3...0: The endpoint number</item>
 * <item>Bit 6...4: Reserved, reset to zero</item>
 * <item>Bit 7: Direction, ignored for control endpoints</item>
 * <item>0 = OUT endpoint</item>
 * <item>1 = IN endpoint</item>
 * </list>
 *
 * @param bmAttributes This field describes the endpoints attributes when it is
 * configured using the bConfigurationValue.
 *
 * <list type="unordered">
 * <item>Bits 1..0: Transfer Type</item>
 * <item>00 = Control</item>
 * <item>01 = Isochronous</item>
 * <item>10 = Bulk</item>
 * <item>11 = Interrupt</item>
 * </list>
 *
 * If not an isochronous endpoint, bits 5..2 are reserved
 * and must be set to zero. If isochronous, they are
 * defined as follows:
 * Bits 3..2: Synchronization Type
 * <list type="unordered">
 * <item>00 = No Synchronization</item>
 * <item>01 = Asynchronous</item>
 * <item>10 = Adaptive</item>
 * <item>11 = Synchronous</item>
 * </list>
 *
 * Bits 5..4: Usage Type
 * <list type="unordered">
 * <item>00 = Data endpoint</item>
 * <item>01 = Feedback endpoint</item>
 * <item>10 = Implicit feedback Data endpoint</item>
 * <item>11 = Reserved</item>
 * </list>
 *
 * All other bits are reserved and must be reset to zero.
 * Reserved bits must be ignored by the host.
 *
 * @param wMaxPacketSize Maximum packet size this endpoint is capable of
 * sending or receiving when this configuration is selected.
 * For isochronous endpoints, this value is used to
 * reserve the bus time in the schedule, required for the
 * per-(micro)frame data payloads. The pipe may, on an
 * ongoing basis, actually use less bandwidth than that
 * reserved. The device reports, if necessary, the actual
 * bandwidth used via its normal, non-USB defined
 * mechanisms.  For all endpoints, bits 10..0 specify the maximum
 * packet size (in bytes).  For high-speed isochronous and interrupt endpoints:
 * Bits 12..11 specify the number of additional transaction
 * opportunities per microframe:
 * <list type="unordered">
 * <item>00 = None (1 transaction per microframe)</item>
 * <item>01 = 1 additional (2 per microframe)</item>
 * <item>10 = 2 additional (3 per microframe)</item>
 * <item>11 = Reserved</item>
 * </list>
 * Bits 15..13 are reserved and must be set to zero.
 *
 * @param bInterval
 * Interval for polling endpoint for data transfers.
 * Expressed in frames or microframes depending on the
 * device operating speed (that is, either 1 millisecond or
 * 125 micro seconds units). For full-/high-speed isochronous endpoints, this value
 * must be in the range from 1 to 16. The bInterval value
 * is used as the exponent for a 2
 * bInterval-1  value; for example, a bInterval of 4 means a period of 8.
 * For full-/low-speed interrupt endpoints, the value of
 * this field may be from 1 to 255. For high-speed interrupt endpoints, the bInterval value
 * is used as the exponent for a 2  bInterval-1
 * value; for example, a bInterval of 4 means a period of 8 (24-1). This value
 * must be from 1 to 16. For high-speed bulk/control OUT endpoints, the
 * bInterval must specify the maximum NAK rate of the endpoint. A value of
 * 0 indicates the endpoint never NAKs. Other values indicate at most 1
 * NAK each bInterval number of microframes. This value must be
 * in the range from 0 to 255.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
*ad*/
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bEndpointAddress;
    unsigned char  bmAttributes;
    unsigned short wMaxPacketSize;
    unsigned char  bInterval;
} usbEndpointDescriptor;
#endif


#ifdef NETOS_GNU_TOOLS
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bInterfaceNumber;
    unsigned char  bAlternateSetting;
    unsigned char  bNumEndpoints;
    unsigned char  bInterfaceClass;
    unsigned char  bInterfaceSubClass;
    unsigned char  bInterfaceProtocol;
    unsigned char  iInterface;

    usbEndpointDescriptor endpoint[USB_MAXENDPOINTS];
} __attribute__ ((packed)) usbInterfaceDescriptor;
#else
#pragma pack (1)
/*ad*
 * The usb Interface Descriptor is the structure that corresponds to the
 * "standard interface descriptor" described in section 9.6.5 of the
 * "Universal Serial Bus Specification Revision 2.0"; for more details,
 * see this document.
 *
 * @param bLength  Size of this descriptor in bytes.
 *
 * @param bDescriptorType INTERFACE Descriptor Type.
 *
 * @param bInterfaceNumber Number of this interface. Zero-based
 * value identifying the index in the array of concurrent interfaces
 * supported by this configuration.
 *
 * @param bAlternateSetting Value used to select this alternate setting
 * for the interface identified in the prior field.
 *
 * @param bNumEndpoints Number of endpoints used by this
 * interface (excluding endpoint zero). If this value is zero, this
 * interface only uses the Default Control Pipe.
 *
 * @param bInterfaceClass Class code (assigned by the USB-IF).
 * A value of zero is reserved for future standardization.
 * If this field is set to FFH, the interface class is vendor-specific.
 * All other values are reserved for assignment by the USB-IF.
 *
 * @param bInterfaceSubClass  Subclass code (assigned by the USB-IF).
 * These codes are qualified by the value of the bInterfaceClass field.
 * If the bInterfaceClass field is reset to zero, this field must also be
 * reset to zero. If the bInterfaceClass field is not set to
 * FFH, all values are reserved for assignment by the USB-IF.
 *
 * @param bInterfaceProtocol Protocol code (assigned by the USB).
 * These codes are qualified by the value of the bInterfaceClass and the
 * bInterfaceSubClass fields. If an interface supports class-specific requests,
 * this code identifies the protocols that the device uses as defined by the
 * specification of the device class. If this field is reset to zero,
 * the device does not use a class-specific protocol on
 * this interface.  If this field is set to FFH, the device uses
 * a vendor-specific protocol for this interface.
 *
 * @param iInterface Index of string descriptor describing this
 * interface.
 *
 * @param endpoint All the endpoint descriptors for this device.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 * @see @link usbEndpointDescriptor
*ad*/
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bInterfaceNumber;
    unsigned char  bAlternateSetting;
    unsigned char  bNumEndpoints;
    unsigned char  bInterfaceClass;
    unsigned char  bInterfaceSubClass;
    unsigned char  bInterfaceProtocol;
    unsigned char  iInterface;

    usbEndpointDescriptor endpoint[USB_MAXENDPOINTS];
} usbInterfaceDescriptor;
#endif

#ifdef NETOS_GNU_TOOLS
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short wTotalLength;
    unsigned char  bNumInterfaces;
    unsigned char  bConfigurationValue;
    unsigned char  iConfiguration;
    unsigned char  bmAttributes;
    unsigned char  MaxPower;

    usbInterfaceDescriptor interface[USB_MAXINTERFACES] __attribute__ ((aligned(4)));
} __attribute__ ((packed)) usbConfigDescriptor;
#else
#pragma pack (1)
/*ad*
 * The usbConfigDescriptor is the structure that corresponds to the
 * "standard configuration descriptor" described in section 9.6.3 of the
 * "Universal Serial Bus Specification Revision 2.0"; for more details,
 * see this document.
 *
 * @param bLength  Size of this descriptor in bytes.
 *
 * @param bDescriptorType INTERFACE Descriptor Type.
 *
 * @param wTotalLength Total length of data returned for this
 * configuration. Includes the combined length of all descriptors
 * (configuration, interface, endpoint, and class- or vendor-specific)
 * returned for this configuration.
 *
 * @param bNumInterfaces Number of interfaces supported by this
 * configuration.
 *
 * @param bConfigurationValue  Value to use as an argument to the
 * SetConfiguration request to select this configuration.
 *
 * @param iConfiguration Index of string descriptor describing this
 * configuration.
 *
 * @param bmAttributes Configuration characteristics includes:
 * <list type="unordered">
 * <item>D7: Reserved (set to one)</item>
 * <item>D6: Self-powered</item>
 * <item>D5: Remote Wakeup</item>
 * <item>D4...0: Reserved (reset to zero)</item>
 * <item>D7 is reserved and must be set to one for historical reasons.</item>
 * </list>
 * A device configuration that uses power from the bus and a local source
 * reports a non-zero value in bMaxPower to indicate the amount of
 * bus power required and sets D6. The actual power source at runtime may
 * be determined using the GetStatus(DEVICE) request (see
 * Section 9.4.5 of the USB spec). If a device configuration supports remote
 * wakeup, D5 is set to one.
 *
 * @param MaxPower Maximum power consumption of the USB
 * device from the bus in this specific
 * configuration when the device is fully
 * operational. Expressed in 2 mA units
 * (that is, 50 = 100 mA).
 * Note: A device configuration reports whether
 * the configuration is bus-powered or self-powered.
 * Device status reports whether the
 * device is currently self-powered. If a device is
 * disconnected from its external power source, it
 * updates device status to indicate that it is no
 * longer self-powered.
 * A device may not increase its power draw
 * from the bus, when it loses its external power
 * source, beyond the amount reported by its
 * configuration.
 * If a device can continue to operate when
 * disconnected from its external power source, it
 * continues to do so. If the device cannot
 * continue to operate, it fails operations that it can
 * no longer support. The USB System Software
 * may determine the cause of the failure by
 * checking the status and noting the loss of the
 * device's power source.
 *
 * @param interface The list of interface descriptors for this
 * device.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 * @see @link usb_get_configuration
 * @see @link usb_get_status
*ad*/
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short wTotalLength;
    unsigned char  bNumInterfaces;
    unsigned char  bConfigurationValue;
    unsigned char  iConfiguration;
    unsigned char  bmAttributes;
    unsigned char  MaxPower;

    usbInterfaceDescriptor interface[USB_MAXINTERFACES];
} usbConfigDescriptor;
#endif


/* String descriptor */
struct usb_string_descriptor
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
};

/* Hub descriptor */
#ifdef NETOS_GNU_TOOLS
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bNbrPorts;
    unsigned short wHubCharacteristics;
    unsigned char  bPwrOn2PwrGood;
    unsigned char  bHubContrCurrent;
    /* DeviceRemovable and PortPwrCtrlMask want to be variable-length
       bitmaps that hold max 256 entries, but for now they're ignored */
    unsigned char  filler;
} __attribute__ ((packed)) usbHubDescriptor;
#else
#pragma pack (1)
typedef struct
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bNbrPorts;
    unsigned short wHubCharacteristics;
    unsigned char  bPwrOn2PwrGood;
    unsigned char  bHubContrCurrent;
    /* DeviceRemovable and PortPwrCtrlMask want to be variable-length
       bitmaps that hold max 256 entries, but for now they're ignored */
    unsigned char  filler;
} usbHubDescriptor;
#endif


/*ad*
 * This is the data structure used to represent USB devices; for a complete
 * description, see the usbDevice link below.
 *
 *
 * @see @link usbDevice
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
*ad*/
struct usbDevice_t;

/*ad*
 * The usbProbeRoutine is called as devices are connected to the USB.
 *
 * @param  dev Pointer to the USB device.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
 * @return 0        Success
 * @return -1       Failure
*ad*/
typedef int (* usbProbeRoutine)(struct usbDevice_t * dev);


/*ad*
 * The usbDisconnectRoutine is called as devices are disconnected from the USB.
 *
 * @param  dev Pointer to the USB device.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
*ad*/
typedef void (* usbDisconnectRoutine)(struct usbDevice_t * dev);


#ifdef NETOS_GNU_TOOLS
typedef struct
{
    const char *name;                           /* Name of the device */
    int  (*probe)(struct usbDevice_t *);        /* The entry point of the probe function. */
    void (*disconnect)(struct usbDevice_t *);   /* The entry point of the disconnect function.  */
    LIST_ENTRY driver_list;
} usbDriver;
#else
#pragma pack (4)
/*ad*
 * The usbDriver structure contains two function pointers and the name of the device.
 *
 * @param name Pointer to a NULL terminated sting containing the name of the USB device.
 *
 * @param probe This entry point is called whenever a new
 * device is attached to the bus. Then the device driver has to create a new instance
 * of its internal data structures for the new device.   This allows the printer driver
 * to search for USB devices that it is interested in; for example, a printer driver
 * would search for all printer devices on the USB and save the relevant information.
 * Detailed examples of probe routines are provided with NET+OS.
 * The dev argument specifies the device context, which contains pointers to all USB
 * descriptors. The interface argument specifies the interface number. If a USB driver
 * wants to bind itself to a particular device and interface, it has to return a pointer.
 * This pointer normally references the device driver's context structure.
 * Probing normally is done by checking the vendor and product identifications or the
 * class and subclass definitions. If they match, the interface number is compared with
 * the ones supported by the driver. When probing is done class-based, it might be necessary
 * to parse some more USB descriptors because the device properties can differ in a wide
 * range.
 *
 * @param disconnect This function is called whenever a device
 * that was served by this driver is disconnected.  The dev argument specifies
 * the device context and the driver_context returns a pointer to the previously
 * registered driver_context of the probe function. After returning from the disconnect
 * function, the USB framework completely deallocates all data structures
 * that are associated with this device. The usbDevice structure must not be
 * used any longer by the usb driver.
 *
 * @param  driver_list This contains a linked list of USB drivers to be added; if this
 * field is NULL, only the specified device is added.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 * @deprecated  6.1
 *
*ad*/
typedef struct
{
    const char           *name;
    usbProbeRoutine      probe;
    usbDisconnectRoutine disconnect;
    LIST_ENTRY           driver_list;
} usbDriver;
#endif


/*ad*
 * This type is a pointer to a usbDeviceIrq function, which is passed to
 * the usbRequestIrq function to request a callback when data arrives
 * from a device on the USB.
 *
 * @param status USB status code.
 *
 * @param buffer Pointer to the buffer containing the data received.
 *
 * @param xferred The number of bytes that were received.
 *
 * @param device_id Pointer used by device driver.
 *
 * @param semaphore Semaphore used by the device driver.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
 * @return 0        Success
 * @return -1       Failure
 *
*ad*/
typedef int (* usbDeviceIrq)(int status, void * buffer, int xferred, void * device_id, void * semaphore);

/*ad*
 * This type is a pointer to a routine used to set up an IRQ request.
 *
 * @param usb Pointer to the USB device.
 *
 * @param pipe Pipe to send data.
 *
 * @param handler Function pointer to call when IRQ data arrives.
 *
 * @param period Polling rate for device.
 *
 * @param dev_id Device ID.
 *
 * @param maxpacketsize Maximum packet size.
 *
 * @param buffer Buffer containing data to send.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
 * @return 0        Success
 * @return -1       Failure
 *
*ad*/
typedef int (* usbRequestIrqType)(struct usbDevice_t * usb, unsigned int pipe, usbDeviceIrq handler, int period, void * dev_id, int maxpacketsize, void * buffer);

#define USB_MAXCHILDREN (8)

/*ad*
 * This type is a pointer to a routine called when a USB transfer is completed
 *
 * @param context Context passed to callback.
 *
 * @param status USB status code.
 *
 * @param xferred The number of bytes that were received.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
 * @return 0        Success
 * @return -1       Failure
 *
*ad*/
typedef int (* USB_CALLBACK)(void * context, int status, int xferred);


/*ad*
 * This type is a pointer to a routine used to send USB commands to OHCI.
 *
 * @param usb Pointer to the USB device.
 *
 * @param pipe Pipe to send data.
 *
 * @param cmd USB command to send.
 *
 * @param data Data to send (optional).
 *
 * @param len Number of bytes of data to send.
 *
 * @param xferred Pointer to an integer that is filled in with the number of bytes sent.
 *
 * @param timeout How long to wait for a response from the device.
 *
 * @param callback Routine to call if in non-blocking mode (zero timeout).
 *
 * @param context Pointer passed to callback routine.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
 * @return 0        Success
 * @return -1       Failure
 *
*ad*/
typedef int (* usbQueueGeneralRequest)(struct usbDevice_t * usb, unsigned int pipe, void * cmd, void * data, int len, int * xferred, int timeout, USB_CALLBACK callback, void * context);


/*ad*
 * This type is a pointer to a routine used to free memory for a USB device.
 *
 * @param dev Pointer to the data structure to free.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
 * @return 0        Success
 * @return -1       Failure
 *
*ad*/
typedef int (* usbDeallocate)(struct usbDevice_t * dev);

/*ad*
 * This type is a pointer to a routine used to allocate memory for a USB device.
 *
 * @param parent Pointer to the parent data structure for the USB device.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 *
 * @return 0        Success
 * @return -1       Failure
 *
*ad*/
typedef void * (* usbAllocate)(struct usbDevice_t * parent);


/*ad*
 * One of these structures are allocated per bus.
 *
 * @param root_hub Root hub.
 *
 * @param hcpriv Private data for the host controller.
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
*ad*/
typedef struct
{
    struct usbDevice_t    *root_hub;
    void *hcpriv;
} usbBus;

#define MAX_ENDPOINTS               128
#define MAX_ENDPOINTS_PER_DEVICE     15


/*ad*
 * The NET+OS USB host library provides a set of APIs that enable you to
 * create your own USB device drivers.  The NET+OS software package provides
 * examples in the /netos/src/examples/usb_host directory.
 * The starting point for the driver is to call usbRegister (see the
 * usbRegister link below); after that, a pointer to the usbDevice structure
 * is passed as a handle to most of the APIs in the USB
 * host library.  The "probe" function (passed into usbRegister) is called as devices
 * attach to the USB; a pointer to the usbDevice structure for the corresponding
 * device is passed to the driver when the probe function is called.  The driver
 * then needs to save the usbDevice structure for subsequent calls.  The usb host fills in
 * the information in this structure when the device attaches to the bus.
 * The usb driver may only write to the driverData parameter. By the time
 * the "probe" function is called for your driver, all the descriptors
 * have already been filled in.
 *
 * @param devnum Device number on the USB bus.
 *
 * @param speed The speed of this device.  A one indicates a low speed device;
 * a zero indicates a full speed device; a two indicates a high speed device.
 *
 * @param maxpacketsize The number of bytes that the device can accept in one
 * transfer.
 *
 * @param bus Pointer to the usbBus structure.
 *
 * @param driver A pointer to the usbDriver structure that was passed to
 * usbRegister.
 *
 * @param descriptor The device descriptor for this device.
 *
 * @param config  All the configuration structures for this device.
 *
 * @param parent Pointer to the next device on the bus.
 *
 * @param parent_port Port number on the parent device (or hub) that this device is connected to.
 *
 * @param maxchild Maximum number of child devices if this device is a hub device.
 * Each instance needs its own set of data structures.
 *
 * @param children Pointers to the children for this device.
 *
 * @param tt_think_time Transation translator think time if this device is a hub device.
 *
 * @param hcpriv A pointer used by the host controller private area.
 *
 * @param hcEdData Private data for host controller.
 *
 * @param private_ptr Private data for USB stack.
 *
 * @param driverData Pointer to be used by the USB driver.
 *
 * @param Endpoint_Opened_In TRUE if this input endpoint has been opened.
 *
 * @param Endpoint_Opened_Out TRUE if this output endpoint has been opened.
 *
 * @param FunctionAddress Address of this endpoint.
 *
 * @param endpoint_pipe_in Pointer to the input endpoint's pipe structure.
 *
 * @param endpoint_pipe_out Pointer to the ouput endpoint's pipe structure.
 *
 * @param host_controller Handle to host controller context
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 6.1
 * @see @link usbDriver
 * @see @link usb_register
 * @see @link usbDeviceDescriptor
 * @see @link usbConfigDescriptor
*ad*/
typedef struct usbDevice_t
{
    int                 devnum;
    int                 speed;
    int                 maxpacketsize;
    usbBus              *bus;
    usbDriver           *driver;
    usbDeviceDescriptor descriptor;
    usbConfigDescriptor config[USB_MAXCONFIG];
    struct usbDevice_t  *parent;
    unsigned int        parent_port;
    int                 maxchild;
    struct usbDevice_t  *children[USB_MAXCHILDREN];
    unsigned int        tt_think_time;
    void                *hcpriv;
    void                *hcEdData;
    void                *private_ptr;
    void                *driverData;
    char                Endpoint_Opened_In[MAX_ENDPOINTS_PER_DEVICE];
    char                Endpoint_Opened_Out[MAX_ENDPOINTS_PER_DEVICE];
    int                 FunctionAddress;
    void                *endpoint_pipe_in[MAX_ENDPOINTS_PER_DEVICE];
    void                *endpoint_pipe_out[MAX_ENDPOINTS_PER_DEVICE];
    void                *host_controller;
} usbDevice;


/*
 *  - device number (7 bits)
 *  - endpoint number (4 bits)
 *  - current Data0/1 state (1 bit)
 *  - direction (1 bit)
 *  - speed (2 bits)
 *  - max packet size (2 bits: 8, 16, 32 or 64)
 *  - pipe type (2 bits: control, interrupt, bulk, isochronous)
 *
 * We'll just encode it as a simple
 * unsigned int. The encoding is:
 *
 *  - device:       bits 8-14
 *  - endpoint:     bits 15-18
 *  - Data0/1:      bit 19
 *  - direction:    bit 7       (0 = Host-to-Device, 1 = Device-to-Host)
 *  - speed:        bits 26-27  (0 = Full Speed, 1 = Low Speed, 2 = High Speed)
 *  - max size:     bits 0-1    (00 = 8, 01 = 16, 10 = 32, 11 = 64)
 *  - pipe type:    bits 30-31  (00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk)
 *
 */

#define USB_MAXPACKET(pipe)     (8 << ((pipe) & 3))
#define USB_PACKETID(pipe)      (((pipe) & 0x80) ? 0x69 : 0xE1)

#define USB_PIPE_DEVICE(pipe)   (((pipe) >> 8) & 0x7f)
#define USB_PIPE_ENDPOINT(pipe) (((pipe) >> 15) & 0xf)
#define USB_PIPE_DATA(pipe)     (((pipe) >> 19) & 1)
#define USB_PIPE_OUT(pipe)      (((pipe) & 0x80) == 0)
#define USB_PIPE_SPEED(pipe)    (((pipe) >> 26) & 3)
#define USB_PIPE_SLOW(pipe)     (USB_PIPE_SPEED(pipe) == 1)

#define USB_PIPE_TYPE(pipe)     (((pipe) >> 30) & 3)
#define USB_PIPE_ISOC(pipe)     (USB_PIPE_TYPE((pipe)) == 0)
#define USB_PIPE_INT(pipe)      (USB_PIPE_TYPE((pipe)) == 1)
#define USB_PIPE_CONTROL(pipe)  (USB_PIPE_TYPE((pipe)) == 2)
#define USB_PIPE_BULK(pipe)     (USB_PIPE_TYPE((pipe)) == 3)

#define USB_PIPE_ENDPDEV(pipe)  (((pipe) >> 8) & 0x7ff)

#define USB_PIPE_TYPE_ISOCHRONOS 0
#define USB_PIPE_TYPE_INTERRUPT  1
#define USB_PIPE_TYPE_CONTROL    2
#define USB_PIPE_TYPE_BULK       3

/* Create control pipes.. */
#define CREATE_PIPE(dev,endpoint) \
    ((dev->devnum << 8) | (endpoint << 15) | (dev->speed << 26) | dev->maxpacketsize)
#define USB_SEND_CTRL_PIPE(dev,endpoint)    ((USB_PIPE_TYPE_CONTROL << 30) | CREATE_PIPE(dev,endpoint))
#define USB_RECIEVE_CTRL_PIPE(dev,endpoint) ((USB_PIPE_TYPE_CONTROL << 30) | CREATE_PIPE(dev,endpoint) | 0x80)
#define DEFAULT_PIPE(dev)                   (dev->speed << 26)
#define USB_SEND_DEFAULT_CTRL(dev)          ((USB_PIPE_TYPE_CONTROL << 30) | DEFAULT_PIPE(dev))
#define USB_RECIEVE_DEFAULT_CTRL(dev)       ((USB_PIPE_TYPE_CONTROL << 30) | DEFAULT_PIPE(dev) | 0x80)

/* Transfer status codes */
#define USB_STATUS_NOERROR             0
#define USB_STATUS_CRC                 1
#define USB_STATUS_BITSTUFFING         2
#define USB_STATUS_DATATOGGLEMISMATCH  3
#define USB_STATUS_STALL               4
#define USB_STATUS_DEVICENOTRESPONDING 5
#define USB_STATUS_PIDCHECKFAILURE     6
#define USB_STATUS_UNEXPECTEDPID       7
#define USB_STATUS_DATAOVERRUN         8
#define USB_STATUS_DATAUNDERRUN        9
#define USB_STATUS_BUFFEROVERRUN       0xc
#define USB_STATUS_BUFFERUNDERRUN      0xd
#define USB_STATUS_NOTACCESSED         0xe
#define USB_STATUS_TIMEOUT             0x10

/* Enumeration endpoint types */
#define USB_CONTROL_ENDPOINT     0
#define USB_BULK_ENDPOINT        2
#define USB_INTERRUPT_ENDPOINT   3
#define USB_ISOCHRONOUS_ENDPOINT 4


/*ad*
 * Structure definition for the host controller context.
 *
 * @param controllerType This structure member stores the USB host controller type.
 *
 * @param registerBaseAddress This structure member stores the base address of the USB host controller register set.
 *
 * @param controllerContext This structure member stores the pointer to an internal OHCI or EHCI controller context structure.
 *
 * @param driverInterfaceFuncs This structure member stores a pointer to a table of low level driver interface functions.  Currently not implemented.
 *
 * @param devicePowerStableDelay This structure member stores the wait time in milliseconds for the host controller driver to wait before driving the USB bus after a device is connected the controller's port.
 *
 * @param controllerEndianness This structure member stores the USB host controller's register and memory access endianness.
 *
 *
 * @external
 * @category BSP:Device_Drivers:USBH
 * @since 7.2
*ad*/
typedef struct
{
    unsigned int   controllerType;
    void *         registerBaseAddress;
    void *         controllerContext;
    void *         driverInterfaceFuncs;
    unsigned short devicePowerStableDelay;
    unsigned short controllerEndianness;
} usbHostController;

/*
 * Base address of OHCI resisters for the ns9750 and the ns9360
 */
#define NS9750_USB_HOST_REG_ADDRESS  0x90100000
#define NS9360_USB_HOST_REG_ADDRESS  0x90800000

/*
 * Definitions for USB Host controller types
 */

/* Reserve values from 0x0 to 0xFF for internal OHCI controllers */
#define USBH_NS9360_OHCI              0x0   /* NS9360 OHCI controller */
#define USBH_NS9750_OHCI              0x1   /* NS9750 OHCI controller */
#define USBH_AU1200_OHCI              0x2   /* AU1200 OHCI controller */

/* Reserve values from 0x100 to 0x1FF for External OHCI controllers */
#define USBH_EXTERNAL_OHCI            0x100 /* Generic OHCI controller */
#define USBH_PHILIPS_ISP1563_OHCI     0x101 /* Philips ISP1563 OHCI controller */
#define USBH_NEC_D720101_OHCI         0x102 

/* Reserve values from 0x200 to 0x2ff for External UHCI controllers */
/* Note: UHCI controllers are currently not supported               */
#define USB_EXTERNAL_UHCI             0x200 /* Generic UHCI controller */

/* Reserve values from 0x300 to 0x3ff for External UHCI controllers */
#define USBH_EXTERNAL_EHCI            0x300 /* Generic EHCI controller */
#define USBH_PHILIPS_ISP1563_EHCI     0x301 /* Philips ISP1563 EHCI controller */
#define USBH_NEC_D720101_EHCI         0x302 


#define USBH_MAX_HOST_CONTROLLERS     16

/*
 * Definitions for host controller endianness
 */
#define USBH_REGISTER_BIG_ENDIAN      1
#define USBH_REGISTER_LITTLE_ENDIAN   2
#define USBH_MEMORY_BIG_ENDIAN        4
#define USBH_MEMORY_LITTLE_ENDIAN     8
#define USBH_ENDIAN_MASK              USBH_REGISTER_BIG_ENDIAN | USBH_REGISTER_LITTLE_ENDIAN | \
                                      USBH_MEMORY_BIG_ENDIAN |   USBH_MEMORY_LITTLE_ENDIAN


/*
 * USB Host Stack API Functions
 */

/* Send and receive control transfers */
int usb_get_status(usbDevice *device, void *buffer, int *errorCode);
int usb_set_feature(usbDevice *device, short int feature, int *errorCode);
int usb_clear_feature(usbDevice *device, short int feature, int *errorCode);
int usb_set_address(usbDevice *device, int *errorCode);
int usb_get_device_descriptor(usbDevice *device, int *bytesTransferred, int *errorCode);
int usb_clear_endpoint_feature(usbDevice *device, short int endpoint, short int feature, int * errorCode);
int usb_device_request(usbDevice *device, int outputIO, devrequest * request, unsigned char *buffer, int bytesToTransfer, int *bytesTransferred, int timeout, int *errorCode);
int usb_set_configuration(usbDevice *device, short int configuration, int *errorCode);
int usb_get_configuration(usbDevice * dev, int *errorCode);
int usb_set_interface(usbDevice * device, short int interface, short int alternative, int *errorCode);
int usb_get_string(usbDevice * device, unsigned short langId, unsigned char descriptor_index, void * buffer, int bytesToTransfer, int * bytesTransferred, int *errorCode);
int usb_check_new_device(usbDevice *device, int *errorCode);
int usb_enumerate_device(usbDevice *device, int *errorCode);

/* Send and receive bulk transfers */
int usb_bulk_transfer(usbDevice *device, int output_io, int endpoint, unsigned char *buffer, int bytesToTransfer,
int *bytesTransferred, int maxPacketSize, int timeout, int *errorCode);


/* Send and receive bulk transfers without blocking */
int usb_bulk_transfer_async(usbDevice *device, int output_io, int endpoint, unsigned char *buffer, int bytesToTransfer,
int *bytesTransferred, int maxPacketSize, int timeout, int *errorCode,
USB_CALLBACK callback_function, void *context);

/* Called at startup to initialize USB stack */
int usb_host_init(unsigned int controllerType, void * registerBaseAddress, unsigned int controllerEndianness,
                  unsigned int devicePowerStableDelay, unsigned int reservedParam,
                  usbHostController ** controllerHandle, int * errorCode);
//int usb_host_init(unsigned int devicePowerStableDelay, int * errorCode, void *ohci_base_addr);
int usb_host_start(usbHostController * controllerHandle, int * errorCode);

/* Enable interrupts for controller.  We do this at the end of initialization
 * to avoid interrupts happening before we are ready to handle them.
 */
extern int usb_host_enable_interrupts(usbHostController * controllerHandle);

/* Boundary based memory allocation and deallocation routines */
void * usb_malloc(int length, int boundary);
int usb_free(void * pointer);

/* Install and remove drivers from the USB stack */
int usb_register(usbDriver * driver, int * errorCode);
int usb_deregister(usbDriver * driver, int * errorCode);

/* Request interrupt transfer service for a device */
int usb_request_interrupt_transfer(usbDevice * device, unsigned int pipe, usbDeviceIrq handler, int period, void * device_id, int maxpacketsize, void * buffer, int *errorCode);

/* Initialize or clear the USB device information and topology */
int usb_connect_device(usbDevice *device, int * errorCode);
int usb_disconnect_device(usbDevice ** pdevice, int *errorCode);

/* Allocate hub child device and it's endpoint and transfer descriptors */
int usb_allocate_child_device(usbDevice * parentDevice, usbDevice ** childDevice, int *errorCode);

/* Get and put device number for enumeration and de-enumeration */
int usb_get_device_number(usbDevice *device, int * errorCode);
int usb_put_device_number(usbDevice *device, int * errorCode);

/* Given a hub device and a port number, return the device for that port */
usbDevice * usb_get_port_device(usbDevice *hub, int port);

/* Get a handle to the Root hub device */
usbDevice * usb_get_root_hub(usbHostController * host_controller);

/* Given a device, return the hub device it is attached to */
usbDevice *usb_get_hub(usbDevice *device);

/* Given a device, return the port number of the hub it is attached to */
int usb_get_hub_port(usbDevice *device);

/* Given a device, power the root hub port ON that it is connected to. */
int usb_enable_port_power(usbDevice *device);

/* Given a device, power the root hub port OFF that the device is connected to. */
int usb_disable_port_power(usbDevice *device);

/* reset the port that is connected to the cell modem PCIe connector */
void usb_power_cycle_cell_modem(void);

void usb_show_all_controllers(void);
/* reset the device on port number 'port' of 'hub' */
int usb_reset_device(usbDevice *hub, int port);

/* Check if any USB device is present on the cell modem port */
int usb_device_present_on_cell_modem_port (void);

/* Get a USB string descriptor in ASCII */
int usb_get_ascii_string (usbDevice *device, unsigned short langID, unsigned char indx, 
    char *string, int size, int *error);

/*ad*
 * USB Host API error codes.
 *
 * @external
 * @include 	<usbHostApi.h>
 * @category BSP:Device_Drivers:USBH
 * @since 7.4 
 * @name usb_host_error_codes   "USB Host API Error Codes"
 *
 * @param USBH_SUCCESS                                  0     Success
 * @param USBH_CRC_ERROR                                1     The last data packet from the endpoint contained a CRC error.
 * @param USBH_BITSTUFFING_ERROR                        2     The last data packet from the endpoint contained a bit stuffing violation.
 * @param USBH_DATATOGGLEMISMATCH                       3     The last packet from the endpoint had a data toggle PID that did not match the expected value.
 * @param USBH_STALL                                    4     The TD was moved to the Done Queue because the endpoint returned a STALL PID.
 * @param USBH_DEVICENOTRESPONDING                      5     The device did not respond to token (IN) or did not provide a handshake (OUT).
 * @param USBH_PIDCHECKFAILURE                          6     The check bits on the PID from the endpoint failed on data PID (IN) or handshake (OUT).
 * @param USBH_UNEXPECTEDPID                            7     The receive PID was not valid when encountered or the PID value is not defined.
 * @param USBH_DATAOVERRUN                              8     The amount of data returned by the endpoint exceeded either the size of the maximum data packet allowed from the endpoint or the remaining buffer size.
 * @param USBH_DATAUNDERRUN                             9     The endpoint returned less than maximum packet size and that amount was not sufficient to fill the specified buffer.
 * @param USBH_RESERVED1                                10    Reserved for future use by the HC.
 * @param USBH_RESERVED2                                11    Reserved for future use by the HC.
 * @param USBH_BUFFEROVERRUN                            12    During an IN, HC received data from endpoint faster than it could be written to system memory.
 * @param USBH_BUFFERUNDERRUN                           13    During an OUT, HC could not retrieve data from system memory fast enough to keep up with data USB data rate.
 * @param USBH_NOTACCESSED                              14    This internal code is set by the software before the TD is placed on a list to be processed by the HC.
 * @param USBH_TIMEOUT                                  16    The data transfer did not complete before the expected timeout.
 * @param USBH_NOT_DONE                                 19    This internal code is set by the software before the TD is placed on a list to be processed by the HC.
 * @param USBH_CANCELING                                20    This internal code indicates that a current data transfer is being cancelled.
 * @param USBH_CANCELED                                 22    This internal code indicates that a current data transfer has been cancelled.
 * @param USBH_NULL_POINTER                             30    One or more function arguments is a NULL pointer.
 * @param USBH_ENDPOINT_INCONSISTENT                    31    The I/O direction and endpoint number passed into @link usb_bulk_transfer are inconsistent.
 * @param USBH_INVALID_PACKET_SIZE                      32    The maximum packet size for an endpoint is invalid.
 * @param USBH_DEVICE_REQUEST_FAILED                    33    A USB device request control transfer failed.
 * @param USBH_MALLOC_FAILED                            34    A dynamic memory allocation process failed.
 * @param USBH_FREE_FAILED                              35    A dynamic memory de-allocation process failed.
 * @param USBH_INVALID_CONFIGURATION_DATA               36    The configuration descriptor data is invalid.
 * @param USBH_INVALID_PORT_NUMBER                      37    The port number to access is invalid.
 * @param USBH_SEMAPHORE_ACCESS_FAILED                  38    An operation to access a semaphore has failed.
 * @param USBH_INVALID_ENDPOINT_TYPE                    39    The endpoint type is invalid.
 * @param USBH_MAX_TD_COUNT_EXCEEDED                    40    The number of TDs used for the data tranfers is larger than the maximum TD count allowed.
 * @param USBH_ISOCHRONOUS_NOT_SUPPORTED                41    Isochronous data trasfers are not supported.
 * @param USBH_NO_TRANSFER_DESCRIPTORS                  42    There are no more TDs available for data transfers.
 * @param USBH_NO_ENDPOINT_DESCRIPTORS                  43    There are no more EDs available for data transfers.
 * @param USBH_ENDPOINT_REQUEST_MISMATCH                44    The ED's user request pointer does not match the TD's user request pointer.
 * @param USBH_ENDPOINT_NOT_FOUND                       45    An ED pointer was not found in a specific ED list.
 * @param USBH_INVALID_FRAME_INTERVAL                   46    The frame interval value to write to the frame interval register is invalid.
 * @param USBH_MUTEX_ACCESS_FAILED                      47    An operation to access a mutex has failed.
 * @param USBH_BLOCK_POOL_ACCESS_FAILED                 48    Access to an internal memory pool has failed.
 * @param USBH_THREAD_ACCESS_FAILED                     49    An operation to access a thread has failed.
 * @param USBH_ISR_INSTALL_FAILED                       50    The USB host controller ISR was not installed.
 * @param USBH_ISR_ENABLE_FAILED                        51    The USB host controller ISR was not enabled.
 * @param USBH_INVALID_POWER_STABLE_DELAY               52    The power stable delay before driving the USB bus must be 100ms <= x <= 2000ms, where 100ms is a minimum requirement by the USB specification and 2000ms is an artificial limit.
 * @param USBH_MAX_DEVICES                              53    The maximum number of devices (127) supported by USB has been exceeded.
 * @param USBH_INVALID_DEVICE_NUMBER                    54    The device number is outside of the range of 0 <= x <= 127.
 * @param USBH_DEVICE_NUMBER_NOT_USED                   55    This error code is currently deprecated.
 * @param USBH_UNSUPPORTED_CONTROLLER_TYPE              56    The controller type is currently not supported.
 * @param USBH_INVALID_ENDIANNESS                       57    The controller endianness value passed into @link usb_host_init is invalid. 
 * @param USBH_EXCEEDED_MAX_CONTROLLERS                 58    The maximum number of concurrently supported USB host controllers has been exceeded.
 * @param USBH_START_CONTROLLER_FAILED                  59    An operation to start the HC failed.
 * @param USBH_ENABLE_PORT_POWER_FAILED                 60    An operation to enable power to the HC's ports failed.
 * @param USBH_INVALID_REGISTER_BASE_ADDRESS            61    The register base address passed into @link usb_host_init is invalid.
 * @param USBH_TRANSACTION_ERROR                        62    This error code is currently deprecated.
 * @param USBH_BABBLE_DETECTED                          63    A data transfer babble error (or data overrun) was detected.
 * @param USBH_MEMORY_POOL_EMPTY                        64    An internal memory pool is empty.
 * @param USBH_ENDPOINT_STILL_BUSY                      65    The endpoint is still in the middle of a data transfer.
 * @param USBH_ENDPOINT_NO_BANDWIDTH                    66    The endpoint is out of bandwidth and no more transfer requests are accepted.
 * @param USBH_NOT_PORT_OWNER                           67    This internal code indicates that the EHCI controller is not the port owner.
 * @param USBH_INVALID_DEVICE_SPEED                     68    This error code is currently deprecated.
*ad*/
#define USBH_SUCCESS                                  0
#define USBH_CRC_ERROR                                1
#define USBH_BITSTUFFING_ERROR                        2
#define USBH_DATATOGGLEMISMATCH                       3
#define USBH_STALL                                    4
#define USBH_DEVICENOTRESPONDING                      5
#define USBH_PIDCHECKFAILURE                          6
#define USBH_UNEXPECTEDPID                            7
#define USBH_DATAOVERRUN                              8
#define USBH_DATAUNDERRUN                             9
#define USBH_RESERVED1                                10
#define USBH_RESERVED2                                11
#define USBH_BUFFEROVERRUN                            12
#define USBH_BUFFERUNDERRUN                           13
#define USBH_NOTACCESSED                              14
#define USBH_TIMEOUT                                  16
#define USBH_NOT_DONE                                 19
#define USBH_CANCELING                                20
#define USBH_CANCELED                                 22
#define USBH_NULL_POINTER                             30
#define USBH_ENDPOINT_INCONSISTENT                    31
#define USBH_INVALID_PACKET_SIZE                      32
#define USBH_DEVICE_REQUEST_FAILED                    33
#define USBH_MALLOC_FAILED                            34
#define USBH_FREE_FAILED                              35
#define USBH_INVALID_CONFIGURATION_DATA               36
#define USBH_INVALID_PORT_NUMBER                      37
#define USBH_SEMAPHORE_ACCESS_FAILED                  38
#define USBH_INVALID_ENDPOINT_TYPE                    39
#define USBH_MAX_TD_COUNT_EXCEEDED                    40
#define USBH_ISOCHRONOUS_NOT_SUPPORTED                41
#define USBH_NO_TRANSFER_DESCRIPTORS                  42
#define USBH_NO_ENDPOINT_DESCRIPTORS                  43
#define USBH_ENDPOINT_REQUEST_MISMATCH                44
#define USBH_ENDPOINT_NOT_FOUND                       45
#define USBH_INVALID_FRAME_INTERVAL                   46
#define USBH_MUTEX_ACCESS_FAILED                      47
#define USBH_BLOCK_POOL_ACCESS_FAILED                 48
#define USBH_THREAD_ACCESS_FAILED                     49
#define USBH_ISR_INSTALL_FAILED                       50
#define USBH_ISR_ENABLE_FAILED                        51
#define USBH_INVALID_POWER_STABLE_DELAY               52
#define USBH_MAX_DEVICES                              53
#define USBH_INVALID_DEVICE_NUMBER                    54
#define USBH_DEVICE_NUMBER_NOT_USED                   55
#define USBH_UNSUPPORTED_CONTROLLER_TYPE              56
#define USBH_INVALID_ENDIANNESS                       57
#define USBH_EXCEEDED_MAX_CONTROLLERS                 58
#define USBH_START_CONTROLLER_FAILED                  59
#define USBH_ENABLE_PORT_POWER_FAILED                 60
#define USBH_INVALID_REGISTER_BASE_ADDRESS            61
#define USBH_TRANSACTION_ERROR                        62
#define USBH_BABBLE_DETECTED                          63
#define USBH_MEMORY_POOL_EMPTY                        64
#define USBH_ENDPOINT_STILL_BUSY                      65
#define USBH_ENDPOINT_NO_BANDWIDTH                    66
#define USBH_NOT_PORT_OWNER                           67
#define USBH_INVALID_DEVICE_SPEED                     68

/*
 * Macro to swap short endians
 */
#define USB_SWAP16W(value)   (((value<<8) & 0xff00) | ((value>>8) & 0xff))

/*
 * Milliseconds to ticks macro (borrowed from NDS)
 */
#ifndef NDS_ENVIRONMENT
#if (BSP_TICKS_PER_SECOND == 1000)

#ifndef NS_MILLISECONDS_TO_TICKS
#define NS_MILLISECONDS_TO_TICKS(t) (t)
#endif

#else

/* rounds up to the nearest tick */
//#define NS_MILLISECONDS_TO_TICKS(t) (((BSP_TICKS_PER_SECOND * (t)) / 1000) + (((BSP_TICKS_PER_SECOND * (t)) % 1000) ? 1 : 0))

#endif
#endif

/*
 * USB devices address range
 */
#define FIRST_USB_DEVICE_NUMBER    1
#define MAX_USB_DEVICES          127

/*
 * USB device speeds
 */
#define USB_DEVICE_FULL_SPEED       0
#define USB_DEVICE_LOW_SPEED        1
#define USB_DEVICE_HIGH_SPEED       2


#ifdef __cplusplus
}
#endif

#endif



