move sboot to the root directory
[open-ath9k-htc-firmware.git] / sboot / magpie_1_1 / sboot / hif / usb / src / usb_api.c
diff --git a/sboot/magpie_1_1/sboot/hif/usb/src/usb_api.c b/sboot/magpie_1_1/sboot/hif/usb/src/usb_api.c
new file mode 100755 (executable)
index 0000000..897bcfa
--- /dev/null
@@ -0,0 +1,2499 @@
+#include "usb_defs.h"
+#include "usb_type.h"
+#include "usb_pre.h"
+#include "usb_extr.h"
+#include "usb_std.h"
+#include "reg_defs.h"
+#include "athos_api.h"
+#include "usbfifo_api.h"
+
+#include "sys_cfg.h"
+
+#if SYSTEM_MODULE_USB
+
+#define CMD_GET_CUSTOM_DATA     4
+LOCAL void flash_read(uint16_t len, uint16_t ofset);
+
+SetupPacket ControlCmd;
+USB_FIFO_CONFIG usbFifoConf;
+uint32_t fwCheckSum = 0;
+
+#define fBUS_POWER                 1
+uint16_t   UsbStatus[3];
+
+/* Variable for USB EP0 pipe (USB.c) */
+uint16_t       *pu8DescriptorEX;
+uint16_t       u16TxRxCounter;
+uint16_t       *u8ConfigDescriptorEX;
+//extern BOOLEAN     bUsbEP0HaltSt;
+Action      eUsbCxFinishAction;
+CommandType eUsbCxCommand;
+BOOLEAN     UsbChirpFinish;
+
+uint16_t       u8UsbConfigValue;
+uint16_t       u8UsbInterfaceValue;
+uint16_t       u8UsbInterfaceAlternateSetting;
+uint16_t       u16FirmwareComplete;
+
+extern uint16_t *UsbDeviceDescriptor;
+extern uint16_t *String00Descriptor;
+extern uint16_t *String10Descriptor;
+extern uint16_t *String20Descriptor;
+extern uint16_t *String30Descriptor;
+
+/////////////////////////////////////////////////
+// should be declared as extern array not pointer
+extern uint16_t u8DeviceQualifierDescriptorEX[];
+extern uint16_t u8OtherSpeedConfigDescriptorEX[];
+
+uint16_t *u8UsbDeviceDescriptor;
+uint16_t *u8String00Descriptor;
+uint16_t *u8String10Descriptor;
+uint16_t *u8String20Descriptor;
+uint16_t *u8String30Descriptor;
+
+
+#if 0   // use macro instead of function
+void mUsbEPinRsTgSet(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg |= BIT4;
+    USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        (USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT4));
+
+}
+
+void mUsbEPinRsTgClr(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg &= ~BIT4;
+    USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        (USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&(~BIT4)));
+}
+
+void mUsbEPoutRsTgSet(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg |= BIT4;
+    USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        (USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT4));
+}
+
+void mUsbEPoutRsTgClr(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg &= ~BIT4;
+    USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        (USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&(~BIT4)));
+}
+
+void mUsbEPinStallSet(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg |= BIT3;
+    USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT3);
+}
+
+void mUsbEPinStallClr(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg &= ~BIT3;
+
+    USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        (USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&(~BIT3)));
+}
+
+void mUsbEPoutStallSet(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg |= BIT3;
+    USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        (USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT3));
+}
+
+void mUsbEPoutStallClr(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //*reg &= ~BIT3;
+    USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+        (USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&(~BIT3)));
+}
+
+uint8_t mUsbEPinStallST(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //return ((*reg & BIT3) >> 3);
+    return ((USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))& BIT3) >> 3);
+}
+
+uint8_t mUsbEPoutStallST(uint8_t u8ep)
+{
+    //uint8_t* reg = (uint8_t*) (ZM_FUSB_BASE+ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1));
+    //return ((*reg & BIT3) >> 3);
+    return ((USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))& BIT3) >> 3);
+}
+
+uint8_t mUsbEPMapRd(uint8_t EPn)
+{
+    //uint8_t *reg = (uint8_t*) (ZM_FUSB_BASE+0x30+(EPn-1));
+    //return *reg;
+    return (USB_BYTE_REG_READ((0x30+(EPn-1))));
+}
+
+uint8_t mUsbFIFOCfgRd(uint8_t FIFOn)
+{
+    //uint8_t *reg = (uint8_t*) (ZM_FUSB_BASE+0x90+FIFOn);
+    //return *reg;
+    return (USB_BYTE_REG_READ((0x90+FIFOn)));
+}
+
+void vUsb_Data_Out0Byte(void)
+{
+    //ZM_INTR_SOURCE_7_REG &= ~BIT7;
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_REG, \
+        (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_REG&(~BIT7))));
+}
+
+
+void vUsb_Data_In0Byte(void)
+{
+    //ZM_INTR_SOURCE_7_REG &= ~BIT6;
+
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_REG, \
+        (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_REG&(~BIT6))));
+}
+
+
+/***********************************************************************/
+//      vUsb_ep0end()
+//      Description:
+//          1. End this transfer.
+//      input: none
+//      output: none
+/***********************************************************************/
+void vUsb_ep0end(void)
+{
+    eUsbCxCommand = CMD_VOID;
+    //ZM_CX_CONFIG_STATUS_REG = 0x01;
+    USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);
+    //mUsbEP0DoneSet();                               // Return EP0_Done flag
+}
+
+/***********************************************************************/
+//      vUsb_ep0fail()
+//      Description:
+//          1. Stall this transfer.
+//      input: none
+//      output: none
+/***********************************************************************/
+void vUsb_ep0fail(void)
+{
+    //ZM_CX_CONFIG_STATUS_REG = 0x04;
+    USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04);
+    //mUsbEP0StallSet();                              // Return EP0_Stall
+}
+
+
+/***********************************************************************/
+//      vUsb_rst()
+//      Description:
+//          1. Change descriptor table (High or Full speed).
+//      input: none
+//      output: none
+/***********************************************************************/
+void vUsb_rst(void)
+{
+//    zfUartSendStr((uint8_t *) "vUsb_rst\r\n");
+    //ZM_INTR_SOURCE_7_REG &= ~0x02;
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
+        (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&(~BIT1)));
+    UsbChirpFinish = FALSE;
+}
+
+/***********************************************************************/
+//      vUsb_suspend()
+//      Description:
+//          1. .
+//      input: none
+//      output: none
+/***********************************************************************/
+void vUsb_suspend(void)
+{
+// uP must do-over everything it should handle
+// and do before into the suspend mode
+    //mUsbIntSuspClr();                       // Go Suspend status
+    //ZM_INTR_SOURCE_7_REG &= ~0x04;
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
+        (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&(~BIT2)));
+}
+
+/***********************************************************************/
+//      vUsb_resm()
+//      Description:
+//          1. Change descriptor table (High or Full speed).
+//      input: none
+//      output: none
+/***********************************************************************/
+void vUsb_resm(void)
+{
+// uP must do-over everything it should handle
+// and do before into the suspend mode
+
+//    mUsbIntResmClr();                       // uP must wakeup immediately
+    //ZM_INTR_SOURCE_7_REG &= ~0x08;
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
+        (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&(~BIT3)));
+}
+
+#else
+
+#define mUsbEPinRsTgSet(u8ep)   USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT4)
+
+#define mUsbEPinRsTgClr(u8ep)   USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&~BIT4)
+
+#define mUsbEPoutRsTgSet(u8ep)  USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT4)
+
+#define mUsbEPoutRsTgClr(u8ep)  USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&~BIT4)
+
+#define mUsbEPinStallSet(u8ep)  USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT3)
+
+#define mUsbEPinStallClr(u8ep)  USB_BYTE_REG_WRITE((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&~BIT3)
+
+#define mUsbEPoutStallSet(u8ep) USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))|BIT3)
+
+#define mUsbEPoutStallClr(u8ep) USB_BYTE_REG_WRITE((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)), \
+                                    USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))&~BIT3)
+
+#define mUsbEPinStallST(u8ep) ((USB_BYTE_REG_READ((ZM_EP_IN_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))& BIT3) >> 3)
+
+#define mUsbEPoutStallST(u8ep) ((USB_BYTE_REG_READ((ZM_EP_OUT_MAX_SIZE_HIGH_OFFSET+(u8ep << 1)))& BIT3) >> 3)
+
+#define mUsbEPMapRd(EPn)    (USB_BYTE_REG_READ((0x30+(EPn-1))))
+
+#define mUsbFIFOCfgRd(FIFOn)    (USB_BYTE_REG_READ((0x90+FIFOn)))
+
+#define vUsb_Data_Out0Byte(void)    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_REG, \
+                                        USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_REG&~BIT7))
+
+
+#define vUsb_Data_In0Byte(void) USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_REG, \
+                                    USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_REG&~BIT6))
+
+#define vUsb_ep0end(void)                                   \
+{                                                           \
+    eUsbCxCommand = CMD_VOID;                               \
+    USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);   \
+}
+
+#define vUsb_ep0fail(void)  USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04)
+
+#define vUsb_rst()                                              \
+{                                                               \
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET,                 \
+        (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT1));    \
+    UsbChirpFinish = FALSE;                                     \
+}
+
+#define vUsb_suspend()  USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
+                            (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT2))
+
+#define vUsb_resm() USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET,     \
+                        (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT3))
+
+
+#endif
+
+LOCAL void flash_read_data(void)
+{
+    uint8_t u8temp;
+
+    // to keep tracking the txrx fifo
+    // max 64 bytes for transmission one time,
+    if (u16TxRxCounter < EP0MAXPACKETSIZE)
+        u8temp = (uint8_t) u16TxRxCounter;
+    else
+        u8temp = EP0MAXPACKETSIZE;
+
+    u16TxRxCounter -= (uint16_t) u8temp;
+
+    {
+        register uint8_t u8count;
+        uint8_t remainder;
+
+        for (u8count = 0; u8count < (u8temp/4); u8count ++)
+        {
+            uint32_t ep0_data;
+            uint16_t ep0_low;
+            uint16_t ep0_high;
+
+            // pack data into word size
+            ep0_low = *pu8DescriptorEX++;
+            ep0_high = *pu8DescriptorEX++;
+
+            // composed the data as a word
+            ep0_data = (ep0_high << 16) + ep0_low;
+
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, ep0_data);
+        }
+
+        remainder = u8temp % 4;
+
+        // Check whether there are data needed to be filled into the FIFO
+        if (remainder == 3)
+        {
+            uint32_t ep0_data;
+            uint16_t ep0_low;
+            uint16_t ep0_high;
+
+            // pack data into word size
+            ep0_low = *pu8DescriptorEX++;
+            ep0_high = *pu8DescriptorEX++;
+
+            ep0_data = (ep0_high << 16) + ep0_low;
+
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x7);
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, ep0_data);
+        }
+        else if (remainder == 2)
+        {
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, *pu8DescriptorEX);
+        }
+        else if (remainder == 1)
+        {
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, *pu8DescriptorEX);
+        }
+
+        // Restore CBus FIFO size to word size
+        USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xf);
+    }
+
+    // end of the data stage
+    if (u16TxRxCounter == 0)
+    {
+        eUsbCxCommand = CMD_VOID;
+        eUsbCxFinishAction = ACT_DONE;
+    }
+}
+
+/***********************************************************************/
+//      vUsb_ep0tx()
+//      Description:
+//          1. Transmit data to EP0 FIFO.
+//      input: none
+//      output: none
+/***********************************************************************/
+LOCAL void vUsb_ep0tx(void)
+{
+    switch (eUsbCxCommand)
+    {
+        case CMD_GET_DESCRIPTOR:
+            A_USB_EP0_TX_DATA();
+            break;
+       
+        default:
+            /* Mark endpoint STALL */
+            USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT6);
+
+            break;
+    }
+
+//    eUsbCxFinishAction = ACT_IDLE;
+}
+
+
+/***********************************************************************/
+//      vUsb_ep0rx()
+//      Description:
+//          1. Receive data from EP0 FIFO.
+//      input: none
+//      output: none
+/***********************************************************************/
+LOCAL void vUsb_ep0rx(void)
+{
+
+    switch (eUsbCxCommand)
+    {
+        case CMD_SET_DESCRIPTOR:
+            A_USB_EP0_RX_DATA();
+            break;
+        default:
+            //mUsbEP0StallSet();
+            break;
+    }
+
+    if (u16TxRxCounter != 0)
+        eUsbCxFinishAction = ACT_IDLE;
+}
+
+
+LOCAL void vUsbClrEPx(void)
+{
+    uint8_t u8ep;
+
+    // Clear All EPx Toggle Bit
+    for (u8ep = 1; u8ep <= FUSB200_MAX_EP; u8ep ++)
+    {
+        mUsbEPinRsTgSet(u8ep);
+        mUsbEPinRsTgClr(u8ep);
+    }
+    for (u8ep = 1; u8ep <= FUSB200_MAX_EP; u8ep ++)
+    {
+        mUsbEPoutRsTgSet(u8ep);
+        mUsbEPoutRsTgClr(u8ep);
+    }
+}
+
+
+/***********************************************************************/
+//      bGet_status()
+//      Description:
+//          1. Send 2 bytes status to host.
+//      input: none
+//      output: TRUE or FALSE (BOOLEAN)
+/***********************************************************************/
+LOCAL BOOLEAN bGet_status(void)
+{
+    uint8_t RecipientStatusLow;
+
+    RecipientStatusLow = UsbStatus[mDEV_REQ_REQ_RECI() & 0x0F];
+
+    //ZM_CBUS_FIFO_SIZE_REG = 0x3;
+    //ZM_EP0_DATA_REG = RecipientStatusLow;
+
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
+    USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, RecipientStatusLow);
+
+    // Restore CBus FIFO size to word size
+    //ZM_CBUS_FIFO_SIZE_REG = 0xf;
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xf);
+
+    eUsbCxFinishAction = ACT_DONE;
+    return TRUE;
+}
+
+/***********************************************************************/
+//      bClear_feature()
+//      Description:
+//          1. Send 2 bytes status to host.
+//      input: none
+//      output: TRUE or FALSE (BOOLEAN)
+/***********************************************************************/
+LOCAL BOOLEAN bClear_feature(void)
+{
+    if (mDEV_REQ_VALUE() > cUSB_FEATSEL_END)
+        return FALSE;
+
+    if ((mDEV_REQ_VALUE() == 0) && (mDEV_REQ_REQ_RECI() != cUSB_REQTYPE_ENDPOINT))
+        return FALSE;
+
+    UsbStatus[2] = 0;
+    eUsbCxFinishAction = ACT_DONE;
+
+    return TRUE;
+}
+
+/***********************************************************************/
+//      bSet_feature()
+//      Description:
+//          1. Send 2 bytes status to host.
+//      input: none
+//      output: TRUE or FALSE (BOOLEAN)
+/***********************************************************************/
+#if ZM_SELF_TEST_MODE
+
+#define TEST_J                  0x02
+#define TEST_K                  0x04
+#define TEST_SE0_NAK            0x08
+#define TEST_PKY                0x10
+
+uint16_t TestPatn0[] = { TEST_J, TEST_K, TEST_SE0_NAK };
+uint32_t TestPatn1[] = {
+    0x00000000, 0x00000000, 0xAA00AA00,         // JKJKJKJK x 9
+    0xAAAAAAAA, 0xEEAAAAAA,                     // AA x 8
+    0xEEEEEEEE, 0xFEEEEEEE,                     // EE x 8
+    0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF,         // FF x 11
+    0xF7EFDFBF, 0x7EFCFDFB, 0xFDFBDFBF};
+
+#endif
+LOCAL BOOLEAN bSet_feature(void)
+{
+
+    //A_PRINTF("bSet_feature...\n\r");
+
+    switch (mDEV_REQ_VALUE())       // FeatureSelector
+    {
+        case 0:     // ENDPOINT_HALE
+            // AVM Patch:
+            // always check RECEIPIENT
+            if (mDEV_REQ_REQ_RECI() == cUSB_REQTYPE_ENDPOINT)
+            {
+                eUsbCxFinishAction = ACT_DONE;
+            }
+            else
+            {
+                return FALSE;
+            }
+
+            break;
+
+        case 1 :        // Device Remote Wakeup
+            // Set "Device_Remote_Wakeup", Turn on the"RMWKUP" bit in Mode Register
+            mUsbRmWkupSet();
+            //USB_BYTE_REG_WRITE(ZM_MAIN_CTRL_OFFSET, USB_BYTE_REG_READ(ZM_MAIN_CTRL_OFFSET)|BIT0);
+            eUsbCxFinishAction = ACT_DONE;
+            break;
+
+    #if ZM_SELF_TEST_MODE
+        case 2 :        // Test Mode
+        //    ii = mDEV_REQ_INDEX() >> 8;
+        //    switch (ii)    // TestSelector
+            switch (mDEV_REQ_INDEX() >> 8)    // TestSelector
+            {
+                case 0x1:   // Test_J
+                case 0x2:   // Test_K
+                case 0x3:   // TEST_SE0_NAK
+                //    mUsbTsMdWr(TestPatn0[(mDEV_REQ_INDEX() >> 8) - 1]);
+                    //ZM_PHY_TEST_SELECT_REG = TestPatn0[(mDEV_REQ_INDEX() >> 8) - 1];
+                    USB_BYTE_REG_WRITE(ZM_PHY_TEST_SELECT_OFFSET, (TestPatn0[(mDEV_REQ_INDEX() >> 8) - 1]));
+                    eUsbCxFinishAction = ACT_DONE;
+                    break;
+
+                case 0x4:   // Test_Packet
+                //    mUsbTsMdWr(TEST_PKY);
+                //    mUsbEP0DoneSet();           // special case: follow the test sequence
+                    //ZM_PHY_TEST_SELECT_REG = TEST_PKY;
+                    //ZM_CX_CONFIG_STATUS_REG = 0x01;
+                    USB_BYTE_REG_WRITE(ZM_PHY_TEST_SELECT_OFFSET, TEST_PKY);
+                    USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT0);
+                    /***********************************************************************///////
+                    // Jay ask to modify, 91-6-5 (Begin)        //
+                    /***********************************************************************///////
+                //    mUsbTsMdWr(TEST_PKY);
+                //    mUsbEP0DoneSet();           // special case: follow the test sequence
+                    //ZM_PHY_TEST_SELECT_REG = TEST_PKY;
+                    USB_BYTE_REG_WRITE(ZM_PHY_TEST_SELECT_OFFSET, TEST_PKY);
+
+                    //ZM_CX_CONFIG_STATUS_REG = 0x01;
+                    /***********************************************************************///////
+                    // Jay ask to modify, 91-6-5 (Begin)        //
+                    /***********************************************************************///////
+                    {
+                    uint16_t ii;
+
+                        /* Set to two bytes mode */
+                        //ZM_CBUS_FIFO_SIZE_REG = 0x0f;
+                        USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x0f);
+
+                        for (ii = 0; ii < sizeof(TestPatn1)/sizeof(uint32_t); ii++)
+                        {
+                            //ZM_EP0_DATA_REG = TestPatn1[ii];
+                            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, TestPatn1[ii]);
+                        }
+
+                        /* Set to one byte mode */
+                        //ZM_CBUS_FIFO_SIZE_REG = 0x07;
+                        //ZM_EP0_DATA_REG = 0x007EFDFB;
+                        USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x07);
+                        USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, 0x007EFDFB);
+
+                        /* Set to four bytes mode */
+                        //ZM_CBUS_FIFO_SIZE_REG = 0x0f;
+                        USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x0f);
+                    }
+                    /***********************************************************************///////
+                    // Jay ask to modify, 91-6-5 (End)          //
+                    /***********************************************************************///////
+
+                    // Turn on "r_test_packet_done" bit(flag) (Bit 5)
+                    //mUsbTsPkDoneSet();
+                    //ZM_CX_CONFIG_STATUS_REG = 0x02;
+                    USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT1);
+                    break;
+
+                case 0x5:   // Test_Force_Enable
+                    //FUSBPort[0x08] = 0x20;    //Start Test_Force_Enable
+                    break;
+
+                default:
+                    return FALSE;
+            }
+            break;
+    #endif
+        default :
+            return FALSE;
+    }
+
+    if (eUsbCxFinishAction == ACT_DONE)
+        UsbStatus[2] = 1;
+
+    return TRUE;
+}
+
+
+/***********************************************************************/
+//      bSet_address()
+//      Description:
+//          1. Set addr to FUSB200 register.
+//      input: none
+//      output: TRUE or FALSE (BOOLEAN)
+/***********************************************************************/
+LOCAL BOOLEAN bSet_address(void)
+{
+
+    //A_PRINTF("bSet_feature...\n\r");
+
+    if (mDEV_REQ_VALUE() >= 0x0100)
+        return FALSE;
+    else
+    {
+//        zfUartSendStrAndHex((uint8_t *) "USB_SET_ADDRESS=", mDEV_REQ_VALUE());
+        //ZM_DEVICE_ADDRESS_REG = mDEV_REQ_VALUE();
+        USB_BYTE_REG_WRITE(ZM_DEVICE_ADDRESS_OFFSET, mDEV_REQ_VALUE());
+
+        eUsbCxFinishAction = ACT_DONE;
+        return TRUE;
+    }
+}
+
+/***********************************************************************/
+//      bGet_descriptor()
+//      Description:
+//          1. Point to the start location of the correct descriptor.
+//          2. set the transfer length
+//      input: none
+//      output: TRUE or FALSE (BOOLEAN)
+/***********************************************************************/
+LOCAL BOOLEAN bGet_descriptor(void)
+{
+    //A_PRINTF("bGet_descriptor...\n\r");
+
+// Change Descriptor type
+#if 0
+    u8ConfigDescriptorEX[mTABLE_IDX(1)] =
+        m2BYTE(CONFIG_LENGTH, DT_CONFIGURATION);
+    u8OtherSpeedConfigDescriptorEX[mTABLE_IDX(1)] =
+        m2BYTE(CONFIG_LENGTH, DT_OTHER_SPEED_CONFIGURATION);
+#endif
+
+    //*(volatile uint32_t*)0x1c0004 = 'G';
+
+    switch (mDEV_REQ_VALUE_HIGH())
+    {
+        case 1:                 // device descriptor
+            pu8DescriptorEX = u8UsbDeviceDescriptor;
+            u16TxRxCounter = mTABLE_LEN(u8UsbDeviceDescriptor[0]);
+            //u16TxRxCounter = 18;
+            break;
+
+        case 2:                 // configuration descriptor
+                                // It includes Configuration, Interface and Endpoint Table
+//            zfUartSendStr((uint8_t *)"Configuration Descriptor\r\n");
+            switch (mDEV_REQ_VALUE_LOW())
+            {
+                case 0x00:      // configuration no: 0
+                    pu8DescriptorEX = u8ConfigDescriptorEX;
+                    u16TxRxCounter = u8ConfigDescriptorEX[1];
+                    //u16TxRxCounter = 46;
+                    break;
+                default:
+                    return FALSE;
+            }
+            break;
+
+        case 3:                 // string descriptor
+                                // DescriptorIndex = low_byte of wValue
+//            zfUartSendStr((uint8_t *)"String Descriptor\r\n");
+            switch (mDEV_REQ_VALUE_LOW())
+            {
+                case 0x00:
+                    pu8DescriptorEX = u8String00Descriptor;
+                    //u16TxRxCounter = 4;
+                    break;
+
+                case 0x10:
+                    pu8DescriptorEX = u8String10Descriptor;
+                    //u16TxRxCounter = 12;
+                    break;
+
+                case 0x20:
+                    pu8DescriptorEX = u8String20Descriptor;
+                    //u16TxRxCounter = 24;
+                    break;
+
+                case 0x30:
+                    pu8DescriptorEX = u8String30Descriptor;
+                    break;
+
+                default:
+                    return FALSE;
+            }
+            u16TxRxCounter = mTABLE_LEN(pu8DescriptorEX[0]);
+            break;
+
+        case 6:                     // Device_Qualifier descritor
+//            zfUartSendStr((uint8_t *) "Device_Qualifier Descriptor\r\n");
+            pu8DescriptorEX = u8DeviceQualifierDescriptorEX;
+            u16TxRxCounter = mTABLE_LEN(u8DeviceQualifierDescriptorEX[0]);
+            //u16TxRxCounter = 10;
+            break;
+
+        case 7:                     // Other_Speed_Configuration
+//            zfUartSendStr((uint8_t *)"Other_Speed Descriptor\r\n");
+            // It includes Configuration, Interface and Endpoint Table
+            pu8DescriptorEX = u8OtherSpeedConfigDescriptorEX;
+            u16TxRxCounter = u8OtherSpeedConfigDescriptorEX[1];
+            //u16TxRxCounter = 46;
+            break;
+
+        default:
+//            zfUartSendStrAndHex((uint8_t *) "Descriptor error=", mDEV_REQ_VALUE_HIGH());
+            return FALSE;
+    }
+
+    if (u16TxRxCounter > mDEV_REQ_LENGTH())
+        u16TxRxCounter = mDEV_REQ_LENGTH();
+
+//    vUsbEP0TxData();
+    A_USB_EP0_TX_DATA();
+    
+    // somehow if there is still data need to send out, we shouldn't set CX_DONE
+    // wait for another EP0_IN
+    if( u16TxRxCounter > 0 )
+    {
+        eUsbCxCommand = CMD_GET_DESCRIPTOR;
+    }
+
+    return TRUE;
+}
+
+
+/***********************************************************************/
+//      bGet_configuration()
+//      Description:
+//          1. Send 1 bytes configuration value to host.
+//      input: none
+//      output: none
+/***********************************************************************/
+LOCAL BOOLEAN bGet_configuration(void)
+{
+
+    //A_PRINTF("bGet_configuration...\n\r");
+
+    //ZM_CBUS_FIFO_SIZE_REG = 0x1;
+    //ZM_EP0_DATA_REG = u8UsbConfigValue;
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+    USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, u8UsbConfigValue);
+
+    // Restore CBus FIFO size to word size
+    //ZM_CBUS_FIFO_SIZE_REG = 0xf;
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xf);
+
+    eUsbCxFinishAction = ACT_DONE;
+
+    return TRUE;
+}
+
+/***********************************************************************/
+//      bSet_configuration()
+//      Description:
+//          1. Get 1 bytes configuration value from host.
+//          2-1. if (value == 0) then device return to address state
+//          2-2. if (value match descriptor table)
+//                  then config success & Clear all EP toggle bit
+//          2-3  else stall this command
+//      input: none
+//      output: TRUE or FALSE
+/***********************************************************************/
+LOCAL BOOLEAN bSet_configuration(void)
+{
+void vUsbClrEPx(void);
+
+    //A_PRINTF("bSet_configuration...\n\r");
+
+    if (mLOW_BYTE(mDEV_REQ_VALUE()) == 0)
+    {
+        u8UsbConfigValue = 0;
+        //mUsbCfgClr();
+        //ZM_DEVICE_ADDRESS_REG &= ~BIT7;
+        USB_BYTE_REG_WRITE(ZM_DEVICE_ADDRESS_OFFSET, (USB_BYTE_REG_READ(ZM_DEVICE_ADDRESS_OFFSET)&~BIT7));
+    }
+    else
+    {
+        if (mUsbHighSpeedST())                  // First judge HS or FS??
+        {
+            if (mLOW_BYTE(mDEV_REQ_VALUE()) > HS_CONFIGURATION_NUMBER)
+                return FALSE;
+
+            u8UsbConfigValue = mLOW_BYTE(mDEV_REQ_VALUE());
+            vUsbFIFO_EPxCfg_HS();
+
+            // Set into 512 byte mode */
+            //ZM_SOC_USB_MODE_CTRL_REG |= BIT2;
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                    (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT2));
+        //    mUsbSOFMaskHS();
+        }
+        else
+        {
+            if (mLOW_BYTE(mDEV_REQ_VALUE()) > FS_CONFIGURATION_NUMBER)
+                return FALSE;
+
+            u8UsbConfigValue = mLOW_BYTE(mDEV_REQ_VALUE());
+            vUsbFIFO_EPxCfg_FS();
+
+            // Set into 64 byte mode */
+            //M_SOC_USB_MODE_CTRL_REG &= ~BIT2;
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)&~BIT2));
+        //    mUsbSOFMaskFS();
+        }
+        //mUsbCfgSet();
+        //ZM_DEVICE_ADDRESS_REG |= BIT7;
+        USB_BYTE_REG_WRITE(ZM_DEVICE_ADDRESS_OFFSET, \
+            (USB_BYTE_REG_READ(ZM_DEVICE_ADDRESS_OFFSET)|BIT7));
+
+        vUsbClrEPx();
+
+        mUsbGlobIntEnable();
+        mUSB_REG_OUT_INT_ENABLE();
+
+    }
+
+    eUsbCxFinishAction = ACT_DONE;
+    return TRUE;
+}
+
+
+/***********************************************************************/
+//      bGet_interface()
+//      Description:
+//          Getting interface
+//      input: none
+//      output: TRUE or FALSE
+/***********************************************************************/
+LOCAL BOOLEAN bGet_interface(void)
+{
+
+//    A_PRINTF("bGet_interface...\n\r");
+    if (mUsbCfgST() == 0)
+        return FALSE;
+
+    // If there exists many interfaces, Interface0,1,2,...N,
+    // You must check & select the specific one
+    switch (u8UsbConfigValue)
+    {
+        #if (HS_CONFIGURATION_NUMBER >= 1)
+        // Configuration 1
+        case 1:
+            if (mDEV_REQ_INDEX() > HS_C1_INTERFACE_NUMBER)
+                return FALSE;
+            break;
+        #endif
+        #if (HS_CONFIGURATION_NUMBER >= 2)
+        // Configuration 2
+        case 2:
+            if (mDEV_REQ_INDEX2() > HS_C2_INTERFACE_NUMBER)
+                return FALSE;
+            break;
+        #endif
+        default:
+            return FALSE;
+    }
+
+    //ZM_CBUS_FIFO_SIZE_REG = 0x1;
+    //ZM_EP0_DATA_REG = u8UsbInterfaceAlternateSetting;
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+    USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, u8UsbInterfaceAlternateSetting);
+
+    // Restore CBus FIFO size to word size
+    //ZM_CBUS_FIFO_SIZE_REG = 0xf;
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x0f);
+
+    u16TxRxCounter = 1; //sizeof(u8UsbInterfaceAlternateSetting);
+    eUsbCxFinishAction = ACT_DONE;
+    return TRUE;
+}
+
+/***********************************************************************/
+//      bSet_interface()
+//      Description:
+//          1-1. If (the device stays in Configured state)
+//                  &(command match the alternate setting)
+//                      then change the interface
+//          1-2. else stall it
+//      input: none
+//      output: TRUE or FALSE
+/***********************************************************************/
+LOCAL BOOLEAN bSet_interface(void)
+{
+void vUsbClrEPx(void);
+
+    //A_PRINTF("bSet_interface...\n\r");
+
+    if (mUsbCfgST())
+    {
+
+        // If there exists many interfaces, Interface0,1,2,...N,
+        // You must check & select the specific one
+        switch (mDEV_REQ_INDEX())
+        {
+            case 0: // Interface0
+
+                if (mLOW_BYTE(mDEV_REQ_VALUE()) == mLOW_BYTE(u8ConfigDescriptorEX[mTABLE_IDX(12)]))
+                {
+                    u8UsbInterfaceValue = (uint8_t) mDEV_REQ_INDEX();
+                    u8UsbInterfaceAlternateSetting = mLOW_BYTE(mDEV_REQ_VALUE());
+                    if (mUsbHighSpeedST())                  // First judge HS or FS??
+                    {
+                        vUsbFIFO_EPxCfg_HS();
+
+                        // Set into 512 byte mode */
+                        USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                            (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT2));
+                    }
+                    else
+                    {
+                        vUsbFIFO_EPxCfg_FS();
+
+                        // Set into 64 byte mode */
+                        USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                            (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)&~BIT2));
+                    }
+                    vUsbClrEPx();
+                    eUsbCxFinishAction = ACT_DONE;
+
+                    mUsbGlobIntEnable();
+                    mUSB_REG_OUT_INT_ENABLE();
+                    return TRUE;
+                }
+        //    case 1: // Interface1
+        //    case 2: // Interface2
+        //    default:
+        //        break;
+        }
+    }
+    return FALSE;
+}
+
+/***********************************************************************/
+//      vUsbEP0TxData()
+//      Description:
+//          1. Send data(max or short packet) to host.
+//      input: none
+//      output: none
+/***********************************************************************/
+LOCAL void vUsbEP0TxData(void)
+{
+    uint8_t u8temp;
+    uint32_t idx=0;
+  
+    //wait a little to make sure ep0 fifo is empty before sending data out
+    while(1)
+    {
+        if(idx++>0xffff) {
+            USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, USB_BYTE_REG_READ(ZM_CX_CONFIG_STATUS_OFFSET)|BIT3);
+            break;
+        }
+
+        if(USB_BYTE_REG_READ(ZM_CX_CONFIG_STATUS_OFFSET)&BIT5)
+        {
+            break;
+        }
+    }
+    // to keep tracking the txrx fifo
+    // max 64 bytes for transmission one time,
+    if (u16TxRxCounter < EP0MAXPACKETSIZE)
+        u8temp = (uint8_t) u16TxRxCounter;
+    else
+        u8temp = EP0MAXPACKETSIZE;
+
+    u16TxRxCounter -= (uint16_t) u8temp;
+
+    {
+        register uint8_t u8count;
+        uint8_t remainder;
+
+        for (u8count = 0; u8count < (u8temp/4); u8count ++)
+        {
+            uint32_t ep0_data;
+            uint16_t ep0_low;
+            uint16_t ep0_high;
+
+            // pack data into word size
+            ep0_low = *pu8DescriptorEX++;
+            ep0_high = *pu8DescriptorEX++;
+
+            // composed the data as a word
+            ep0_data = (ep0_high << 16) + ep0_low;
+
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, ep0_data);
+        }
+
+        remainder = u8temp % 4;
+
+        // Check whether there are data needed to be filled into the FIFO
+        if (remainder == 3)
+        {
+            uint32_t ep0_data;
+            uint16_t ep0_low;
+            uint16_t ep0_high;
+
+            // pack data into word size
+            ep0_low = *pu8DescriptorEX++;
+            ep0_high = *pu8DescriptorEX++;
+
+            ep0_data = (ep0_high << 16) + ep0_low;
+
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x7);
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, ep0_data);
+        }
+        else if (remainder == 2)
+        {
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, *pu8DescriptorEX);
+        }
+        else if (remainder == 1)
+        {
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, *pu8DescriptorEX);
+        }
+
+        // Restore CBus FIFO size to word size
+        USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xf);
+    }
+
+    // end of the data stage
+    if (u16TxRxCounter == 0)
+    {
+        eUsbCxCommand = CMD_VOID;
+        eUsbCxFinishAction = ACT_DONE;
+    }
+}
+
+/***********************************************************************/
+//      vUsbEP0RxData()
+//      Description:
+//          1. Receive data(max or short packet) from host.
+//      input: none
+//      output: none
+/***********************************************************************/
+LOCAL void vUsbEP0RxData(void)
+{
+    uint8_t u8temp;
+
+    if (u16TxRxCounter < EP0MAXPACKETSIZE)
+        u8temp = (uint8_t) u16TxRxCounter;
+    else
+        u8temp = EP0MAXPACKETSIZE;
+
+    u16TxRxCounter -= (uint16_t) u8temp;
+
+    // Receive u8Temp bytes data
+    {
+    register uint8_t u8count;
+    uint8_t *p = (uint8_t *) pu8DescriptorEX;
+
+        for (u8count = 0; u8count < ((u8temp+3) >> 2); u8count ++)
+        {
+            uint32_t ep0_data;
+
+            ep0_data = USB_WORD_REG_READ(ZM_EP0_DATA_OFFSET);   //read usb ep0 fifo data,
+
+            {
+// skip the writing to ram if not build for rom code
+#if 0 //1 defined(_ROM_)
+                *p++ = mGetByte0(ep0_data);
+                *p++ = mGetByte1(ep0_data);
+                *p++ = mGetByte2(ep0_data);
+                *p++ = mGetByte3(ep0_data);
+#endif
+                fwCheckSum = fwCheckSum ^ ep0_data;
+             }
+        }
+
+        pu8DescriptorEX += (u8count << 1);
+    }
+
+    // end of the data stage
+    if (u16TxRxCounter == 0)
+    {
+        eUsbCxCommand = CMD_VOID;
+        eUsbCxFinishAction = ACT_DONE;
+    }
+}
+
+
+/***********************************************************************/
+//      vUsb_SetupDescriptor()
+//      Description:
+//          Setup the pointer to the descriptor in the SRAM and EEPROM
+//
+/***********************************************************************/
+LOCAL void vUsb_SetupDescriptor(void)
+{
+// eeprom exist the usb configuration is only supportted in rom version
+#if defined(_ROM_)
+    //
+    // check the offset of PID's value is correct or not, need to be defined!!, ryan
+    //
+
+    if( *((uint32_t*)USB_DESC_IN_EEPROM_FLAG_ADDR) == USB_DESC_IN_EEP_PATTERN)
+    {
+        A_PRINTF("- custom usb config\n");
+
+        u8UsbDeviceDescriptor = (uint16_t *) USB_DEVICE_DESCRIPTOR_ADDR;
+        u8String00Descriptor = (uint16_t *) USB_STRING00_DESCRIPTOR_ADDR;
+        u8String10Descriptor = (uint16_t *) USB_STRING10_DESCRIPTOR_ADDR;
+        u8String20Descriptor = (uint16_t *) USB_STRING20_DESCRIPTOR_ADDR;
+        u8String30Descriptor = (uint16_t *) USB_STRING30_DESCRIPTOR_ADDR;
+    }
+    else
+#endif
+    {
+        u8UsbDeviceDescriptor = (uint16_t *) &UsbDeviceDescriptor;
+        u8String00Descriptor = (uint16_t *) &String00Descriptor;
+        u8String10Descriptor = (uint16_t *) &String10Descriptor;
+        u8String20Descriptor = (uint16_t *) &String20Descriptor;
+        u8String30Descriptor = (uint16_t *) &String30Descriptor;
+    }
+
+    /* Point Device Qualifierdescriptors and Other Speed Descriptor
+        *  - Device Qualifierdescriptor is located in RAM segment, extern these
+        *    symbol at the beginning of this file
+     */
+}
+
+
+/***********************************************************************/
+//      bStandardCommand()
+//      Description:
+//          1. Process standard command.
+//      input: none
+//      output: TRUE or FALSE
+/***********************************************************************/
+LOCAL BOOLEAN bStandardCommand(void)
+{
+    switch (mDEV_REQ_REQ())                 // by Standard Request codes
+    {
+        case USB_GET_STATUS:
+            return (A_USB_GET_STATUS());
+
+        case USB_CLEAR_FEATURE:
+            return (A_USB_CLEAR_FEATURE());
+
+        case USB_SET_FEATURE:
+            return (A_USB_SET_FEATURE());
+
+        case USB_SET_ADDRESS:
+            return (A_USB_SET_ADDRESS());
+
+        case USB_GET_DESCRIPTOR:
+            return (A_USB_GET_DESCRIPTOR());
+
+#if 0
+        case USB_SET_DESCRIPTOR:
+//            if (!bUsbEP0HaltSt)
+            return (bSet_descriptor());
+#endif
+
+        case USB_GET_CONFIGURATION:
+            return (A_USB_GET_CONFIG());
+
+        case USB_SET_CONFIGURATION:
+            //A_PRINTF(" \n--> SET_CONFIGURATION\r\n");
+//            if (!bUsbEP0HaltSt)
+//             return (A_USB_SET_CONFIG());
+
+        {
+            A_USB_SET_CONFIG();
+
+#if ENABLE_SWAP_DATA_MODE
+            // SWAP FUNCTION should be enabled while DMA engine is not working,
+            // the best place to enable it is before we trigger the DMA
+            MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
+            MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
+
+        #if SYSTEM_MODULE_HP_EP5
+            MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
+        #endif
+
+        #if SYSTEM_MODULE_HP_EP6
+            MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
+        #endif
+
+#endif //ENABLE_SWAP_DATA_MODE
+
+
+#if !ENABLE_STREAM_MODE
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT3);
+
+ /*
+ // ryan:
+ // 04/01: bit0 could disable lpdn dma, which is good at debugging while async_fifo have problem,
+ //            we could disable this and check the fifo_rcv_size to see if we have correct at fifo or not
+ */
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, ((USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT1))); // upstream DMA enable
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, ((USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT0))); // downstream DMA enable
+
+        #if SYSTEM_MODULE_HP_EP5
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, ((USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT8)));
+        #endif
+
+        #if SYSTEM_MODULE_HP_EP6
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, ((USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT9)));
+        #endif
+
+#else
+/////////////ENABLE_STREAM_MODE/////////////////
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)&(~BIT1)));  // disable upstream DMA mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)&(~BIT3)));  // enable upstream stream mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET,
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|(BIT1)));    // enable upstream DMA mode
+
+        #if SYSTEM_MODULE_HP_EP1
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)&(~BIT0)));  // diable LP downstream DMA mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|(BIT6)));    // enable LP downstream stream mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|(BIT0)));   // enable LP downstream DMA mode
+        #endif
+
+        #if SYSTEM_MODULE_HP_EP5
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)&(~BIT8)));     // disable HP downstream DMA mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|(BIT7)));    // enable HP downstream stream mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT8));     // enable HP downstream DMA mode
+        #endif
+
+
+        #if SYSTEM_MODULE_HP_EP6
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)&(~BIT9)));    // disable MP downstream DMA mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT10));      // enable MP downstream stream mode
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|BIT9));    // enable MP downstream DMA mode
+        #endif
+
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MODE_CTRL_OFFSET, \
+                (USB_WORD_REG_READ(ZM_SOC_USB_MODE_CTRL_OFFSET)|(BIT4)));   // define the host dma buffer size - 4096(00) 8192 (01) 16384(10) 32768(11) bytes
+
+            USB_WORD_REG_WRITE(ZM_SOC_USB_TIME_CTRL_OFFSET, USB_STREAM_MODE_TIMEOUT_CTRL);  // set stream mode timeout critirea
+
+            USB_WORD_REG_WRITE(ZM_SOC_USB_MAX_AGGREGATE_OFFSET, USB_STREAM_MODE_AGG_CNT); // set stream mode packet buffer critirea
+#endif  //!ENABLE_STREAM_MODE
+
+
+
+//extern void Magpie_init(void);
+//Magpie_init();
+
+            return TRUE;
+        }
+
+        case USB_GET_INTERFACE:
+//            A_PRINTF(" \n--> GET_INTERFACE\r\n");
+//            if (!bUsbEP0HaltSt)
+                //return (bGet_interface());
+            return (A_USB_GET_INTERFACE());
+
+        case USB_SET_INTERFACE:
+//            A_PRINTF(" \n--> SET_INTERFACE\r\n");
+//            if (!bUsbEP0HaltSt)
+//          return (bSet_interface());
+//          return (A_USB_SET_INTERFACE());
+            A_USB_SET_INTERFACE();
+            return TRUE;
+    }
+    return FALSE;
+}
+
+
+LOCAL void flash_read(uint16_t len, uint16_t ofset)
+{
+    uint16_t i=0;
+    
+    uint8_t buf[64];
+    uint16_t end_addr = 0x0;
+    uint16_t start_addr = 0x0;
+    uint32_t ep0_data = 0x0;
+
+#if 0    
+    //sanity check, just in case
+    if(u16TxRxCounter < EP0MAXPACKETSIZE)
+        u8temp = (uint8_t) u16TxRxCounter;
+    else
+
+    if( u16TxRxCounter > 64 )
+        len = EP0MAXPACKETSIZE;
+    else
+        len = u16TxRxCounter + 4-(u16TxRxCounter%4);
+#endif
+
+    start_addr = ofset;
+    end_addr = start_addr + len;
+
+    A_PRINTF("read flash from %x to %x\n", ofset, end_addr);
+
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+    
+    for (i = 0; start_addr < end_addr; i++, start_addr+=4)
+    {
+//        A_SFLASH_READ(1, ofset, 4, buf + i*4);
+//        *((volatile uint32_t *)(buf+i*4)) = *(uint32_t *)(0xf000000+start_addr);
+//    A_PRINTF(" %08x ", *(uint32_t *)(0xf000000+start_addr));
+    USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, *(uint32_t *)(0xf000000+start_addr));
+    }
+
+//    A_PRINTF("\n\n\r");    
+    USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT0);
+
+
+
+
+#if 0    
+     USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+            
+    for(i=0; i<len; i+4)
+    {
+        ep0_data = *(uint32_t *)(buf+i);
+
+        USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, ep0_data);
+    }
+
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+
+    USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT0); 
+#endif
+}
+
+extern BOOLEAN download_enable;
+
+LOCAL void VendorCommand(void)
+{
+#define cUSB_REQ_DOWNLOAD          0x30
+#define cUSB_REQ_DOWNLOAD_COMP     0x31
+#define cUSB_REQ_BOOT              0x32
+#define cUSB_REQ_RESERVED_1        0x33
+#define cUSB_REQ_RESERVED_2        0x34
+
+#define cUSB_REQ_FLASH_READ        0x35
+#define cUSB_REQ_FLASH_READ_COMP   0x36
+
+//#define ZM_FIRMWARE_ADDR           0x200000
+
+    void (*funcPtr)(void);
+    uint16_t *text_addr = 0;
+    uint32_t ep0_data = 0x0;
+//    static download_enable = FALSE;
+    
+    CURRENT_PROGRAM = (uint32_t)VendorCommand;
+
+    switch (mDEV_REQ_REQ())
+    {
+        case cUSB_REQ_FLASH_READ:
+            
+            ep0_data = *(uint32_t *)(0xf000000);
+        
+            u16TxRxCounter = mDEV_REQ_LENGTH();
+            pu8DescriptorEX = (uint16_t*)( (mDEV_REQ_VALUE()));
+//            A_PRINTF("Get a flash_read (%x) request with lenght:%d, and offset %x...\n", cUSB_REQ_FLASH_READ, u16TxRxCounter, pu8DescriptorEX);
+
+//            eUsbCxCommand = CMD_GET_CUSTOM_DATA;
+
+#if 1
+            flash_read(u16TxRxCounter, (uint16_t)pu8DescriptorEX);
+#else
+            eUsbCxCommand = CMD_GET_CUSTOM_DATA;
+            USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, ep0_data);
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+            USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT0);
+#endif
+            break;
+            
+        case cUSB_REQ_FLASH_READ_COMP:
+        
+            ep0_data = *(uint32_t *)(0xf000004);
+            A_PRINTF("get a upload complete request...\n");        
+            
+            //eUsbCxCommand = CMD_SET_DESCRIPTOR;
+//                USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+                USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, ep0_data);
+                USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+               USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT0);
+            
+            //download_enable = TRUE;
+
+            break;
+
+        case cUSB_REQ_DOWNLOAD:
+            //if( download_enable )
+            {
+                u16TxRxCounter = mDEV_REQ_LENGTH();
+                pu8DescriptorEX = (uint16_t*)( (mDEV_REQ_VALUE() << 8));
+                A_PRINTF("\t[cUSB_REQ_DOWNLOAD]: 0x%08x, %02x\n\r", pu8DescriptorEX, u16TxRxCounter);
+
+                eUsbCxCommand = CMD_SET_DESCRIPTOR;
+                
+            }
+//            else
+//                A_PRINTF("firmware download deny!!\n\r");
+            break;
+
+        case cUSB_REQ_DOWNLOAD_COMP:
+            
+            text_addr = (uint16_t*)( (mDEV_REQ_VALUE() << 8));
+            A_PRINTF("\t\n\r==>[cUSB_REQ_COMP]: 0x%08x\n\r", text_addr);
+#if 0
+            if (fwCheckSum != 0)
+            {
+                A_PRINTF("cksum=%x", fwCheckSum);
+                fwCheckSum = 0;
+                //Return fail
+                DEBUG_SYSTEM_STATE |= BIT27;
+
+                USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+                USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, 1);
+                USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+                USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT0);
+            }
+            else
+#endif
+            {
+                /* Set EP0 Done */
+                //ZM_CX_CONFIG_STATUS_REG = 0x01;
+                fwCheckSum = 0;
+                USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+                USB_WORD_REG_WRITE(ZM_EP0_DATA_OFFSET, 0);
+                USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+               USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, BIT0);
+
+                A_PRINTF("VendorCmd: DownloadComplete!\n");
+
+                               DEBUG_SYSTEM_STATE &= ~BIT27;
+                DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x3f;
+
+                // this value should be assign from host along with the DOWNLOAD_COMP in wValue
+                if( text_addr != 0 )
+                    funcPtr = (void *)(text_addr);
+
+                download_enable = TRUE;
+
+                               // only jump to text address in ROM version
+                               #if defined(_ROM_)
+                //    funcPtr();    // jump to the firmware and never return
+                               #endif
+                //app_start();
+                       }
+//            else
+//                A_PRINTF("Integrity is not fine!\n\r");
+
+            break;
+    }
+}
+
+
+/***********************************************************************/
+//      vUsb_ep0setup()
+//      Description:
+//          1. Read 8-byte setup packet.
+//          2. Decode command as Standard, Class, Vendor or NOT support command
+//      input: none
+//      output: none
+/***********************************************************************/
+extern uint16_t u8HSConfigDescriptor01[];
+extern uint16_t u8FSConfigDescriptor01[];
+
+LOCAL void vUsb_ep0setup(void)
+{
+register uint8_t ii;
+volatile uint32_t ep0_data;
+//BOOLEAN bStandardCommand(void);
+//BOOLEAN bClassCommand(void);
+//void VendorCommand(void);
+
+    //zcPrint._printf("\t---> %s <---\n\r", __FUNCTION__);
+    if (UsbChirpFinish != TRUE)
+    {
+        UsbChirpFinish = TRUE;
+
+        // Setup Descriptor pointer
+        //vUsb_SetupDescriptor();
+        A_USB_SETUP_DESC();
+
+        u8OtherSpeedConfigDescriptorEX[0] = 0x0709;
+
+        if (mUsbHighSpeedST())                  // Judge HS or FS??
+        {
+            u8ConfigDescriptorEX = u8HSConfigDescriptor01;
+
+        // copy Device Qualifierdescriptors (from rom to sram)
+            for (ii = 1; ii < 4; ii++)
+            {
+                u8DeviceQualifierDescriptorEX[ii] = u8UsbDeviceDescriptor[ii];
+            }
+
+        // Number of Other-speed Configurations
+        // byte 9 Reserved for future use, must be zero
+            u8DeviceQualifierDescriptorEX[4] = (u8UsbDeviceDescriptor[8] >> 8) & 0x00ff;
+
+         // copy Other Speed Descriptor
+            for (ii = 1; ii < (USB_TOTAL_DESC_LEN/2); ii++)
+            {
+                u8OtherSpeedConfigDescriptorEX[ii] = u8FSConfigDescriptor01[ii];
+            }
+
+#if 0
+            MaxPktSize = HS_C1_I0_A0_EP1_MAX_PACKET;
+        // Device stays in High Speed
+            u8DeviceDescriptorEX = u8HSDeviceDescriptor;
+
+        // copy Device Qualifierdescriptors (from rom to sram)
+            for (ii = mTABLE_WID(2) ; ii < mTABLE_WID(8); ii ++)
+                u8DeviceQualifierDescriptorEX[ii] = u8FSDeviceDescriptor[ii];
+
+        // Number of Other-speed Configurations
+        // byte 9 Reserved for future use, must be zero
+            u8DeviceQualifierDescriptorEX[mTABLE_IDX(8)]
+                = mHIGH_BYTE(u8FSDeviceDescriptor[mTABLE_IDX(17)]);
+            u8ConfigDescriptorEX = u8HSConfigDescriptor01;
+            u8OtherSpeedConfigDescriptorEX = u8FSConfigDescriptor01;
+#endif
+        }
+        else
+        {
+            u8ConfigDescriptorEX = u8FSConfigDescriptor01;
+
+        // copy Device Qualifierdescriptors (from rom to sram)
+            for (ii = 1; ii < 4; ii++)
+            {
+                u8DeviceQualifierDescriptorEX[ii] = u8UsbDeviceDescriptor[ii];
+            }
+
+        // Number of Other-speed Configurations
+        // byte 9 Reserved for future use, must be zero
+            u8DeviceQualifierDescriptorEX[4] = (u8UsbDeviceDescriptor[8] >> 8) & 0x00ff;
+
+         // copy Other Speed Descriptor
+            for (ii = 1; ii < (USB_TOTAL_DESC_LEN/2); ii++)
+            {
+                u8OtherSpeedConfigDescriptorEX[ii] = u8HSConfigDescriptor01[ii];
+            }
+
+#if 0
+            MaxPktSize = FS_C1_I0_A0_EP1_MAX_PACKET;
+        // Device stays in Full Speed
+            u8DeviceDescriptorEX = u8FSDeviceDescriptor;
+
+        // copy Device Qualifierdescriptors (from rom to sram)
+            for (ii = mTABLE_WID(2) ; ii < mTABLE_WID(8); ii ++)
+                u8DeviceQualifierDescriptorEX[ii] = u8HSDeviceDescriptor[ii];
+
+        // Number of Other-speed Configurations
+        // byte 9 Reserved for future use, must be zero
+            u8DeviceQualifierDescriptorEX[mTABLE_IDX(8)]
+                = mHIGH_BYTE(u8HSDeviceDescriptor[mTABLE_IDX(17)]);
+            u8ConfigDescriptorEX = u8FSConfigDescriptor01;
+            u8OtherSpeedConfigDescriptorEX = u8HSConfigDescriptor01;
+#endif
+        }
+     //Change bLength
+        u8DeviceQualifierDescriptorEX[0] = 0x060A;
+    }
+
+    if( USB_BYTE_REG_READ(ZM_CX_CONFIG_STATUS_OFFSET) & BIT5)
+    {
+        int kkk=0;
+        kkk++;
+    }
+    //ep0_data = ZM_EP0_DATA_REG;
+    ep0_data = USB_WORD_REG_READ(ZM_EP0_DATA_OFFSET);
+
+    ii = mGetByte0(ep0_data);
+
+    ControlCmd.Direction = (uint8_t)(ii & 0x80);// xfer Direction(IN, OUT)
+    ControlCmd.Type = (uint8_t)(ii & 0x60);     // type(Standard, Class, Vendor)
+    ControlCmd.Object = (uint8_t)(ii & 0x03);   // Device, Interface, Endpoint
+
+    ControlCmd.Request = mGetByte1(ep0_data);
+    ControlCmd.Value = mGetByte2(ep0_data) + (mGetByte3(ep0_data) << 8);
+
+    //ep0_data = ZM_EP0_DATA_REG;
+    ep0_data = USB_WORD_REG_READ(ZM_EP0_DATA_OFFSET);
+
+    ControlCmd.Index = mGetByte0(ep0_data) + (mGetByte1(ep0_data) << 8);
+    ControlCmd.Length = mGetByte2(ep0_data) + (mGetByte3(ep0_data) << 8);
+
+//  Command Decode
+    if (mDEV_REQ_REQ_TYPE() == (cUSB_REQTYPE_STD << bmREQ_TYPE))
+    {                                       // standard command
+        //if (bStandardCommand() == FALSE)
+        if (A_USB_STANDARD_CMD() == FALSE)
+        {
+            eUsbCxFinishAction = ACT_STALL;
+        }
+    }
+    else if (mDEV_REQ_REQ_TYPE() == (cUSB_REQTYPE_VENDOR << bmREQ_TYPE))
+    {                                       // vendor command
+        //VendorCommand();
+        A_USB_VENDOR_CMD();
+    }
+    else
+    {
+    // Invalid(bad) command, Return EP0_STALL flag
+        A_PRINTF("request not support..  stall", __FUNCTION__);
+        eUsbCxFinishAction = ACT_STALL;
+    }
+
+    //zcPrint._printf("\t<--- %s --->\n\r", __FUNCTION__);
+}
+
+
+/*! - init FUSB phy
+ *
+ */
+LOCAL void cFUSB200Init(void)
+{
+    /* Clear USB reset interrupt */
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&0xfd));
+
+    // Disable all fifo interrupt
+    /* Clear all USB OUT FIFO */
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_1_OFFSET, 0xff);
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_2_OFFSET, 0xff);
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_3_OFFSET, 0xff);
+
+    /* Clear all USB IN FIFO */
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_5_OFFSET, 0xff);
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_6_OFFSET, 0xff);
+
+    // Soft Reset
+    //ZM_MAIN_CTRL_REG = 0x10;
+    //ZM_MAIN_CTRL_REG &= ~0x10;
+
+    // Soft Reset
+    USB_BYTE_REG_WRITE(ZM_MAIN_CTRL_OFFSET, 0x10);
+    USB_BYTE_REG_WRITE(ZM_MAIN_CTRL_OFFSET, 0x0);
+
+    // Clear all fifo
+    USB_BYTE_REG_WRITE(ZM_TEST_OFFSET, BIT0); // will be cleared after one cycle.
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_0_OFFSET, 0); //BIT6);  // Mask out INT status
+
+    // reset the specific mode
+    USB_BYTE_REG_WRITE(ZM_VDR_SPECIFIC_MODE_OFFSET, 0x0);
+
+    // reset the zero-length fifo indication ? workaround...
+    USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, 0x0);
+
+    // Enable Chip
+    USB_BYTE_REG_WRITE(ZM_MAIN_CTRL_OFFSET, (BIT5|BIT2));
+
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_1_OFFSET, 0x0);
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_2_OFFSET, 0x0);
+    USB_BYTE_REG_WRITE(ZM_INTR_MASK_BYTE_3_OFFSET, 0x0);
+
+//    USB_WORD_REG_WRITE(0x104, 0x000000C0);
+
+}
+
+
+LOCAL void _usbfifo_enable_event_isr(void)
+{
+    mUSB_STATUS_IN_INT_ENABLE();
+}
+
+LOCAL void _usbfifo_init(USB_FIFO_CONFIG *pConfig) 
+{
+    usbFifoConf.get_command_buf = pConfig->get_command_buf;
+    usbFifoConf.recv_command    = pConfig->recv_command;
+    usbFifoConf.get_event_buf   = pConfig->get_event_buf;
+    usbFifoConf.send_event_done = pConfig->send_event_done;
+}
+
+LOCAL void vUsb_Reg_Out(void)
+{
+    uint16_t usbfifolen;
+    uint16_t ii;
+    volatile uint32_t *regaddr;    // = (volatile uint32_t *) ZM_CMD_BUFFER;
+    uint16_t cmdLen;
+    uint32_t ep4_data;
+    VBUF *buf;
+
+    //mUSB_REG_OUT_INT_DISABLE();
+
+    buf = usbFifoConf.get_command_buf();
+
+    if ( buf != NULL )     // copy free
+        regaddr = (uint32_t *)buf->desc_list->buf_addr;
+    else
+        goto ERR;
+
+    // read fifo size of the current packet.
+    usbfifolen = USB_BYTE_REG_READ(ZM_EP4_BYTE_COUNT_LOW_OFFSET);
+
+    cmdLen = usbfifolen;
+
+    if(usbfifolen % 4)
+        usbfifolen = (usbfifolen >> 2) + 1;
+    else
+        usbfifolen = usbfifolen >> 2;
+
+    for(ii = 0; ii < usbfifolen; ii++)
+    {
+        ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);   // read fifo data out
+        *regaddr = ep4_data;
+        regaddr++;
+    }
+
+    if ( buf != NULL )
+    {
+//        zfUartSendStrAndHex((u8_t *) "cmdLen=", cmdLen);
+//        zfMemoryCopyInWord(buf->desc_list->buf_addr, ZM_CMD_BUFFER, usbfifolen*4);
+        buf->desc_list->next_desc = NULL;
+        buf->desc_list->data_offset = 0;
+        buf->desc_list->data_size = cmdLen;
+        buf->desc_list->control = 0;
+        buf->next_buf = NULL;
+        buf->buf_length = cmdLen;
+
+        usbFifoConf.recv_command(buf);
+    }
+    goto DONE;
+ERR:
+//    we might get no command buffer here?
+//    but if we return here, the ep4 fifo will be lock out,
+//    so that we still read them out but just drop it ?
+    for(ii = 0; ii < usbfifolen; ii++)
+    {
+        ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);   // read fifo data out
+    }
+
+DONE:
+    //mUSB_STATUS_IN_INT_ENABLE();
+
+}
+
+LOCAL void vUsb_Status_In(void)
+{
+    uint16_t count;
+    uint16_t remainder;
+    volatile u32_t *regaddr;
+    u16_t RegBufLen;
+    VBUF *evntbuf = NULL;
+
+    //regaddr = (volatile uint32_t *) ZM_CMD_BUFFER;
+
+    //mUSB_STATUS_IN_INT_DISABLE();
+
+    evntbuf = usbFifoConf.get_event_buf();
+    if ( evntbuf != NULL )
+    {
+//zfUartSendStr((u8_t *) "#G1\r\n");
+//        A_PRINTF("#G1\n\r");
+        regaddr = VBUF_GET_DATA_ADDR(evntbuf);
+        RegBufLen = evntbuf->buf_length;
+//        A_PRINTF("RegBufLen=%d\n\r", RegBufLen);
+//zfUartSendStrAndHex((u8_t *) "RegBufLen=", RegBufLen);
+    }
+    else
+    {
+        mUSB_STATUS_IN_INT_DISABLE();
+//        A_PRINTF("#G2\n\r");
+        goto ERR_DONE;
+    }
+
+    /* INT use EP3 */
+    for(count = 0; count < (RegBufLen / 4); count++)
+    {
+//zfUartSendStrAndHex((u8_t *) "data=", *regaddr);
+        USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
+        regaddr++;
+    }
+
+    remainder = RegBufLen % 4;
+
+    if (remainder)
+    {
+        switch(remainder)
+        {
+        case 3:
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x7);
+            break;
+        case 2:
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
+            break;
+        case 1:
+            USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
+            break;
+        }
+
+        USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
+    }
+
+    // Restore CBus FIFO size to word size
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
+
+    mUSB_EP3_XFER_DONE();
+
+    if ( evntbuf != NULL )
+    {
+        usbFifoConf.send_event_done(evntbuf);
+    }
+
+ERR_DONE:
+    //mUSB_REG_OUT_INT_ENABLE();
+}
+
+/////////////////////////////////////////////////////////
+/***********************************************************************/
+//      zfResetUSBFIFO()
+//      Description:
+//          1. Reset all the USB FIFO used for WLAN
+//      input: none
+//      output: none
+/***********************************************************************/
+LOCAL void zfResetUSBFIFO(void)
+{
+    A_PUTS("zfResetUSBFIFO\n\r");
+
+}
+
+/***********************************************************************/
+//      zfTurnOffPower()
+//      Description:
+//          1. Function to turn off ADDA/RF power, PLL
+//      input: none
+//      output: none
+/***********************************************************************/
+LOCAL void zfTurnOffPower(void)
+{
+    A_PUTS("zfTurnOffPower\n\r");
+#if defined(MAGPIE_ASIC)
+/*
+ *  1. set CPU bypass
+ *  2. turn off CPU PLL
+ *  3. turn off ETH PLL
+ *  4. disable ETH PLL bypass and update
+ *  5. set SUSPEND_ENABLE
+ */
+
+    /*HAL_WORD_REG_WRITE(MAGPIE_REG_USB_DIVIDE_ADDR,((0x8<<8)|0x8));  */
+    /* 1. */ HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_BYPASS_ADDR,
+                (HAL_WORD_REG_READ(MAGPIE_REG_CPU_PLL_BYPASS_ADDR)|(BIT0|BIT4)));
+             A_DELAY_USECS(100); // wait for stable
+
+    /* 2. */ HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_ADDR,
+                (HAL_WORD_REG_READ(MAGPIE_REG_CPU_PLL_ADDR)|(BIT16)));
+    
+    /* 3. */ HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_ADDR,
+                (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_ADDR)|(BIT16)));
+
+    /* 4. */ HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_BYPASS_ADDR,
+                (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_BYPASS_ADDR)|(BIT16|BIT0)));
+                
+    /* 5. */ HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,
+                (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)|(BIT0)));
+#endif
+
+}
+
+
+LOCAL void zfGenWatchDogEvent(void)
+{
+    uint32_t event= 0x0000C600;
+
+    mUSB_STATUS_IN_INT_DISABLE();
+
+    //ZM_CBUS_FIFO_SIZE_REG = 0xf;
+    USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x0f);
+
+    //ZM_EP3_DATA_REG = event;
+    USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, event);
+
+    mUSB_EP3_XFER_DONE();
+}
+
+LOCAL void zfJumpToBootCode(void)
+{
+    extern int _start(void);
+
+    /* Jump to the boot code */
+    _start();
+}
+
+LOCAL void _usb_rom_task(void)
+{
+    register uint8_t usb_interrupt_level1;
+    register uint8_t usb_interrupt_level2;
+    register uint8_t usb_ctrl_err_indication;
+
+    usb_interrupt_level1 = USB_BYTE_REG_READ(ZM_INTR_GROUP_OFFSET);
+
+    if (usb_interrupt_level1 & BIT6)
+    {
+        A_USB_GEN_WDT();
+        A_PRINTF("Generate Event\n");
+    }
+
+    if (usb_interrupt_level1 & BIT0)            //Group Byte 0
+    {
+        usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET);
+
+        // refer to FUSB200, p 48, offset:21H, bit7 description, should clear the command abort interrupt first!?
+        if (usb_interrupt_level2 & BIT7)
+        {
+            USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_0_OFFSET, (USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET)& ~BIT7));
+        }
+
+        if (usb_interrupt_level2 & BIT1)
+        {
+            A_PRINTF("![USB] ep0 IN in \n\r");
+            A_USB_EP0_TX();                       // USB EP0 tx interrupt
+        }
+        if (usb_interrupt_level2 & BIT2)
+        {
+            //A_PRINTF("![USB] ep0 OUT in\n\r");
+            A_USB_EP0_RX();                       // USB EP0 rx interrupt
+        }
+        if (usb_interrupt_level2 & BIT0)
+        {
+            //A_PRINTF("![USB] ep0 SETUP in\n\r");
+            A_USB_EP0_SETUP();
+        }
+
+        if (eUsbCxFinishAction == ACT_STALL)
+        {
+            USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04);
+//            A_PRINTF("![USB] ZM_CX_CONFIG_STATUS_REG = 0x04\n\r");
+        }
+        else if (eUsbCxFinishAction == ACT_DONE)
+        {
+            // set CX_DONE to indicate the transmistion of control frame
+            USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);
+        }
+        eUsbCxFinishAction = ACT_IDLE;
+    }
+
+    if (usb_interrupt_level1 & BIT7)            //Group Byte 7
+    {
+        //usb_interrupt_level2 = ZM_INTR_SOURCE_7_REG;
+        usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET);
+
+        if (usb_interrupt_level2 & BIT1)
+        {
+            vUsb_rst();
+        }
+        if (usb_interrupt_level2 & BIT2)
+        {
+            vUsb_suspend();
+        }
+        if (usb_interrupt_level2 & BIT3)
+        {
+            vUsb_resm();
+        }
+    }
+
+}
+
+
+LOCAL void _usb_fw_task(void)
+{
+    register uint8_t usb_interrupt_level1;
+    register uint8_t usb_interrupt_level2;
+    register uint8_t usb_ctrl_err_indication;
+
+    usb_interrupt_level1 = USB_BYTE_REG_READ(ZM_INTR_GROUP_OFFSET);
+
+#if 0 // these endpoints are handled by DMA
+    if (usb_interrupt_level1 & BIT5)            //Group Byte 5
+    {
+        vUsb_Data_In();
+    }
+#endif
+    if (usb_interrupt_level1 & BIT4)
+    {
+        usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_4_OFFSET);
+        if( usb_interrupt_level2 & BIT6)
+            A_USB_REG_OUT();//vUsb_Reg_Out();
+    }
+
+    if (usb_interrupt_level1 & BIT6)
+    {
+        //zfGenWatchDogEvent();
+    usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_6_OFFSET);
+        if( usb_interrupt_level2 & BIT6)
+             A_USB_STATUS_IN();//vUsb_Status_In();
+    }
+
+    if (usb_interrupt_level1 & BIT0)            //Group Byte 0
+    {
+        //usb_interrupt_level2 = ZM_INTR_SOURCE_0_REG;
+        usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET);
+
+        // refer to FUSB200, p 48, offset:21H, bit7 description, should clear the command abort interrupt first!?
+        if (usb_interrupt_level2 & BIT7)
+        {
+            //ZM_INTR_SOURCE_0_REG &= 0x7f;       // Handle command abort
+            USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_0_OFFSET, (USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET)& ~BIT7));
+            A_PRINTF("![SOURCE_0] bit7 on\n\r");
+        }
+
+        if (usb_interrupt_level2 & BIT1)
+        {
+            //A_PRINTF("![USB] ep0 IN in \n\r");
+            A_USB_EP0_TX();                       // USB EP0 tx interrupt
+        }
+        if (usb_interrupt_level2 & BIT2)
+        {
+            //A_PRINTF("![USB] ep0 OUT in\n\r");
+            A_USB_EP0_RX();                       // USB EP0 rx interrupt
+        }
+        if (usb_interrupt_level2 & BIT0)
+        {
+            //A_PRINTF("![USB] ep0 SETUP in\n\r");
+            A_USB_EP0_SETUP();
+            //vWriteUSBFakeData();
+        }
+//        else if (usb_interrupt_level2 & BIT3)
+        if (usb_interrupt_level2 & BIT3)
+        {
+            vUsb_ep0end();
+//            A_PRINTF("![SOURCE_0] ep0 CMD_END\n\r");
+        }
+        if (usb_interrupt_level2 & BIT4)
+        {
+            vUsb_ep0fail();
+//            A_PRINTF("![SOURCE_0] ep0 CMD_FAIL\n\r");
+        }
+        if (eUsbCxFinishAction == ACT_STALL)
+        {
+            // set CX_STL to stall Endpoint0 & will also clear FIFO0
+            USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04);
+//            A_PRINTF("![USB] ZM_CX_CONFIG_STATUS_REG = 0x04\n\r");
+        }
+        else if (eUsbCxFinishAction == ACT_DONE)
+        {
+            // set CX_DONE to indicate the transmistion of control frame
+            USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);
+        }
+        eUsbCxFinishAction = ACT_IDLE;
+    }
+
+    if (usb_interrupt_level1 & BIT7)            //Group Byte 7
+    {
+        //usb_interrupt_level2 = ZM_INTR_SOURCE_7_REG;
+        usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET);
+
+#if 0
+        if (usb_interrupt_level2 & BIT7)
+        {
+            vUsb_Data_Out0Byte();
+//            A_PRINTF("![SOURCE_7] bit7 on, clear it\n\r");
+        }
+        if (usb_interrupt_level2 & BIT6)
+        {
+            vUsb_Data_In0Byte();
+//            A_PRINTF("![SOURCE_7] bit6 on, clear it\n\r");
+        }
+#endif
+
+        if (usb_interrupt_level2 & BIT1)
+        {
+            vUsb_rst();
+            //USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_REG, (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~0x2));
+            A_PRINTF("!USB reset\n\r");
+//            A_PRINTF("![0x1012c]: %\n\r", USB_WORD_REG_READ(0x12c));
+        }
+        if (usb_interrupt_level2 & BIT2)
+        {
+           // TBD: the suspend resume code should put here, Ryan, 07/18
+           //
+           //  issue, jump back to rom code and what peripherals should we reset here?
+           //
+
+                       /* Set GO_TO_SUSPEND bit to USB main control register */
+            vUsb_suspend();
+            A_PRINTF("!USB suspend\n\r");
+
+            // keep the record of suspend
+#if defined(PROJECT_MAGPIE)
+            *((volatile uint32_t*)WATCH_DOG_MAGIC_PATTERN_ADDR) = SUS_MAGIC_PATTERN;
+#elif defined(PROJECT_K2)
+            HAL_WORD_REG_WRITE(MAGPIE_REG_RST_STATUS_ADDR, SUS_MAGIC_PATTERN);
+#endif /* #if defined(PROJECT_MAGPIE) */
+
+            /* Reset USB FIFO */
+            A_USB_RESET_FIFO();
+
+            /* Turn off power */
+            A_USB_POWER_OFF();
+
+// DON'T restart when not in ASIC
+#if defined(MAGPIE_ASIC)
+            /* Jump to boot code */
+            A_USB_JUMP_BOOT();
+#endif
+
+        }
+        if (usb_interrupt_level2 & BIT3)
+        {
+            vUsb_resm();
+            A_PRINTF("!USB resume\n\r");
+        }
+    }
+
+}
+
+#if 0 // old
+
+void _usb_init(void)
+{
+
+// init variables
+//    u16TxRxCounter = 0;
+//    eUsbCxCommand = CMD_VOID;
+//    u8UsbConfigValue = 0;
+    u8UsbInterfaceValue = 0;
+    u8UsbInterfaceAlternateSetting = 0;
+//    bUsbEP0HaltSt = FALSE;
+//    u16FirmwareComplete = 0;
+//    eUsbCxFinishAction = ACT_IDLE;
+    UsbStatus[0] = !fBUS_POWER;
+
+// init hardware
+
+//    cFUSB200Init();
+    A_USB_INIT_PHY();
+
+    //ZM_PHY_TEST_SELECT_REG = 0;             // Plug In
+    USB_BYTE_REG_WRITE(ZM_PHY_TEST_SELECT_OFFSET, 0x0);
+
+    // reset the address, just in case...
+    //USB_BYTE_REG_WRITE(ZM_DEVICE_ADDRESS_OFFSET, 0x0);
+
+}
+
+#else // new
+
+#if defined(PROJECT_MAGPIE)
+
+/* -  spec, ch11, reset
+ *
+ *  1. turn on ETH PLL and set ETH PLL to 384Mhz
+ *  2. set "USB_DMA, USB_CORE, ETH_PLL, CPU_PLL, USB_POR reset" bit 
+ *  3. clear "ETH_PLL, CPU_PLL" reset bit
+ *  4. set USB divider to 48, 192/16=12
+ *  5. disable ETH PLL bypass
+ *  6. clear USB_POR
+ *  7. clear USB_DMA, USB_CORE
+ *  8. enable USB_AHB_ARB
+ *
+ *  note: don't know why bit3, bit4 should deassert? here especially bit4?
+ *        since if we don't deassert this, clk won't come up
+ *
+ */
+#if defined(MAGPIE_ASIC)
+#define RST_USB_COLD_INIT()      \
+{                               \
+    /********* number of PLLDIV_LOW and PLLDIV_HIGH ***********/        \
+    /*HAL_WORD_REG_WRITE(MAGPIE_REG_USB_DIVIDE_ADDR,((0x8<<8)|0x8));  */    \
+    /* 1. */ HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_ADDR, 0x305);                            \
+    /* 2. */ HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,                                  \
+                (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)|(BIT0|BIT1|BIT2|BIT3|BIT4))); \
+    /* 3. */ HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,                                  \
+                (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&(~(BIT1|BIT2))));            \
+    /* 4. */ HAL_WORD_REG_WRITE(MAGPIE_REG_USB_DIVIDE_ADDR, 0x1010);                        \
+    /* 5. */ HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_BYPASS_ADDR, 0x0);                       \
+    A_DELAY_USECS(100);  /* wait for clock source stable */                                 \
+    /* 6. */ HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,                                  \
+                (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&(~(BIT0))));                 \
+    /* 7. */ HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,                                  \
+                (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&(~(BIT3|BIT4))));            \
+    /* 8. */ HAL_WORD_REG_WRITE(MAGPIE_REG_AHB_ARB_ADDR,                                    \
+                (HAL_WORD_REG_READ(MAGPIE_REG_AHB_ARB_ADDR)|BIT2));                       \
+    /* HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR, ); */                                  \
+    /* HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR, (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)|((BIT0|BIT3|BIT4))));  */  \
+    /* HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR, (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&(~(BIT0|BIT3|BIT4)))); */  \
+}
+
+/* -  back from suspend
+ *
+ *  1. turn on ETH PLL , 0x5600c, ~bit0
+ *  2. clear USB SUSPEND_ENABLE, 0x56030, ~bit0
+ *
+ */
+#define RST_USB_SUSP_INIT()                                                                 \
+{                                                                                           \
+    /* 1. */ HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_BYPASS_ADDR,                             \
+                (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_BYPASS_ADDR)&(~BIT0)));               \
+    /* 2. */ HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,                             \
+                (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)&(~BIT0)));               \
+}
+
+/* -  back from watchdog
+ *
+ */
+#define RST_USB_WDT_INIT()
+
+
+#elif defined(MAGPIE_FPGA)
+// fpag don't have PLL, skip 1~5
+#define RST_USB_COLD_INIT()                                                                      \
+{                                                                                           \
+    /* 6. */ HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,                                  \
+                (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&(~(BIT0))));                 \
+    /* 7. */ HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR,                                  \
+                (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)&(~(BIT3|BIT4))));            \
+    /* 8. */ HAL_WORD_REG_WRITE(MAGPIE_REG_AHB_ARB_ADDR,                                    \
+                (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)|BIT2));                       \
+    A_DELAY_USECS(100);  /* wait for clock source stable */                                 \
+}
+
+/* -  back from suspend
+ *
+ */
+#define RST_USB_SUSP_INIT()
+
+/* -  back from watchdog
+ *
+ */
+#define RST_USB_WDT_INIT()
+
+
+#endif
+
+
+#elif defined(PROJECT_K2)
+#define RST_USB_INIT()      \
+{                               \
+    HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR, HAL_WORD_REG_READ(MAGPIE_REG_RST_PWDN_CTRL_ADDR)|BIT12);  \
+    A_DELAY_USECS(10); \
+    HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR, HAL_WORD_REG_READ(MAGPIE_REG_RST_PWDN_CTRL_ADDR)&(~BIT12));  \
+}
+#endif
+/*
+    @ToDo: this is used to enable usb access internal memory, dma need this
+    HAL_WORD_REG_WRITE(MAGPIE_REG_AHB_ARB_ADDR, (HAL_WORD_REG_READ(MAGPIE_REG_AHB_ARB_ADDR)&(~(BIT2))));  \
+    A_DELAY_USECS(20); \
+    HAL_WORD_REG_WRITE(MAGPIE_REG_AHB_ARB_ADDR, (HAL_WORD_REG_READ(MAGPIE_REG_AHB_ARB_ADDR)|(BIT2))); \
+    A_DELAY_USECS(20); \
+*/
+
+
+LOCAL void _usb_clk_init(void)
+{
+    T_BOOT_TYPE mBootMode;
+
+    DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x31;
+    
+    mBootMode = A_WDT_LASTBOOT();
+
+#if defined(PROJECT_MAGPIE)
+
+    if( mBootMode == ENUM_WDT_BOOT )
+    {
+        RST_USB_WDT_INIT();
+    }
+    else if ( mBootMode == ENUM_SUSP_BOOT )
+    {
+        RST_USB_SUSP_INIT();
+    }
+    else
+    {
+        RST_USB_COLD_INIT();
+    }
+    
+#elif defined(PROJECT_K2)
+    if( mBootMode == ENUM_COLD_BOOT )
+    {
+        RST_USB_INIT();
+    }
+#endif
+
+    DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x32;
+
+    //A_DELAY_USECS(300); // delay 300 micro seconds, wait for clock stable!
+}
+
+
+void _usb_init(void)
+{
+    u32_t   cold_start;
+
+//    A_PUTS("\n - _usb_init - \n\r");
+
+#if defined(PROJECT_MAGPIE)
+    //if ( *((volatile uint32_t*)WATCH_DOG_MAGIC_PATTERN_ADDR) == WDT_MAGIC_PATTERN || *((volatile uint32_t*)WATCH_DOG_MAGIC_PATTERN_ADDR) == SUS_MAGIC_PATTERN )
+    if( A_WDT_LASTBOOT()!= ENUM_COLD_BOOT)
+#elif defined(PROJECT_K2)
+    if (HAL_WORD_REG_READ(MAGPIE_REG_RST_STATUS_ADDR) == WDT_MAGIC_PATTERN || HAL_WORD_REG_READ(MAGPIE_REG_RST_STATUS_ADDR) == SUS_MAGIC_PATTERN)
+#endif /* #if defined(PROJECT_MAGPIE) */
+        cold_start = 0;
+    else
+        cold_start = 1;
+
+    DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x30;
+// init variables
+//    u16TxRxCounter = 0;
+//    eUsbCxCommand = CMD_VOID;
+//    u8UsbConfigValue = 0;
+    u8UsbInterfaceValue = 0;
+    u8UsbInterfaceAlternateSetting = 0;
+//    bUsbEP0HaltSt = FALSE;
+//    u16FirmwareComplete = 0;
+//    eUsbCxFinishAction = ACT_IDLE;
+    UsbStatus[0] = !fBUS_POWER;
+
+
+/*!
+ * move the setting to A_USB_CLK_INIT(), so that we could patch these things
+ */
+#if 1 
+    A_USB_CLK_INIT();
+
+#else
+
+#if defined(PROJECT_MAGPIE)
+
+//#if defined(MAGPIE_ASIC)
+    //
+    // @Bug 36267 - wdt reset or other reset will reset usb phy, we need to init again here
+    //            - this won't work at FPGA, skip this checking if build for FPGA
+    // 
+    // @Bug 36947 - L3 fpga's reset behavior of usb is not as what I expect!, need to confirm
+    //            
+    // ToBeNote: if (Bug36947), skip the checking and reset usb anyway, but will see the connection broken
+//    if (cold_start)
+//#endif
+    A_USB_CLK_INIT();
+#elif defined(PROJECT_K2)
+    if (cold_start)
+    {
+        DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x31;
+        RST_USB_INIT();
+    }
+#endif /* #if defined(PROJECT_MAGPIE) */
+
+#endif
+
+        A_DELAY_USECS(300); // delay 300 usecs, wait for clock stable!
+    
+       while( 1 )
+    {
+        /*
+         * wait for USBSOC_HCLK_RDY tight high, indicate the 30Mhz is ready for use
+         */
+        if(HAL_WORD_REG_READ(0x10128)& BIT8)
+            break;
+
+        //A_DELAY_USECS(200); // delay 200 micro seconds, wait for clock stable!
+       }
+
+    DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x33;
+    A_PUTS("6. usb_hclk rdy\n\r");
+
+    //
+    // @Bug 36267 - wdt reset or other reset will reset usb phy, we need to init again here
+    //
+    // @Bug 36947 - L3 fpga's reset behavior of usb is not as what I expect!, need to confirm
+#if defined(PROJECT_MAGPIE)
+
+    // in cold or suspend boot, we do reinit the USB_PHY, skip only when watchdog start
+    //
+    // 
+#if defined(MAGPIE_ASIC)
+    if (cold_start)
+#endif
+#elif defined(PROJECT_K2)
+    if (cold_start)
+#endif /* #if defined(PROJECT_MAGPIE) */
+    {
+        DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x34;
+        A_USB_INIT_PHY();
+
+        DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xff)) | 0x35;
+        //ZM_PHY_TEST_SELECT_REG = 0;             // Plug In
+        USB_BYTE_REG_WRITE(ZM_PHY_TEST_SELECT_OFFSET, 0x0);
+
+        // reset the address, just in case...
+        //USB_BYTE_REG_WRITE(ZM_DEVICE_ADDRESS_OFFSET, 0x0);
+    }
+
+     /* If watchdog reset happens, target needs to send a message to host through EP3 */
+     if ( A_WDT_LASTBOOT() == ENUM_WDT_BOOT )
+        mUSB_STATUS_IN_INT_ENABLE();
+     else
+        mUSB_STATUS_IN_INT_DISABLE();
+
+}
+
+#endif
+
+////////////////////////////////////////////////////////
+void usbfifo_module_install(struct usbfifo_api *apis)
+{    
+        /* hook in APIs */
+    apis->_init = _usbfifo_init;
+    apis->_enable_event_isr = _usbfifo_enable_event_isr;
+}
+
+
+void cmnos_usb_module_install(struct usb_api *apis)
+{
+    apis->_usb_init = _usb_init;
+    apis->_usb_rom_task = _usb_rom_task;
+    apis->_usb_fw_task = _usb_fw_task;
+    apis->_usb_init_phy = cFUSB200Init;
+
+    apis->_usb_ep0_setup = vUsb_ep0setup;
+    apis->_usb_ep0_tx_data = vUsbEP0TxData;
+    apis->_usb_ep0_rx_data = vUsbEP0RxData;
+
+    apis->_usb_get_configuration = bGet_configuration;
+    apis->_usb_set_configuration = bSet_configuration;
+
+    apis->_usb_get_interface = bGet_interface;
+    apis->_usb_set_interface = bSet_interface;
+
+    apis->_usb_standard_cmd = bStandardCommand;
+    apis->_usb_vendor_cmd = VendorCommand;
+
+    apis->_usb_reset_fifo= zfResetUSBFIFO;
+    apis->_usb_power_off = zfTurnOffPower;
+    apis->_usb_gen_wdt = zfGenWatchDogEvent;
+    apis->_usb_jump_boot = zfJumpToBootCode;
+
+    apis->_usb_get_descriptor = bGet_descriptor;
+    apis->_usb_set_address = bSet_address;
+    apis->_usb_set_feature = bSet_feature;
+    apis->_usb_clr_feature = bClear_feature;
+
+    apis->_usb_get_status = bGet_status;
+    apis->_usb_setup_desc = vUsb_SetupDescriptor;
+
+    apis->_usb_reg_out = vUsb_Reg_Out;
+    apis->_usb_status_in = vUsb_Status_In;
+
+    apis->_usb_ep0_tx = vUsb_ep0tx;
+    apis->_usb_ep0_rx = vUsb_ep0rx;
+    
+    apis->_usb_clk_init = _usb_clk_init;
+}
+
+#endif