uint32_t USBD_ReadEP (uint32_t EPNum, uint8_t *pData) {
  uint32_t cnt  = 0;
  uint32_t i;

  /* Setup packet                                                             */
  if ((LPC_USBx->ENDPTSETUPSTAT & 1) && (!EPNum)) {
    LPC_USBx->ENDPTSETUPSTAT = 1;
    while (LPC_USBx->ENDPTSETUPSTAT & 1);
    do {
      *((__packed uint32_t*) pData)      = EPQHx[EP_OUT_IDX(0)].setup[0];
      *((__packed uint32_t*)(pData + 4)) = EPQHx[EP_OUT_IDX(0)].setup[1];
      cnt = 8;
      LPC_USBx->USBCMD_D |= (1UL << 13);
    } while (!(LPC_USBx->USBCMD_D & (1UL << 13)));
    LPC_USBx->USBCMD_D &= (~(1UL << 13));
    LPC_USBx->ENDPTFLUSH = (1UL << EPNum) | (1UL << (EPNum + 16));
    while (LPC_USBx->ENDPTFLUSH & ((1UL << (EPNum + 16)) | (1UL << EPNum)));
    while (LPC_USBx->ENDPTSETUPSTAT & 1);
    USBD_PrimeEp(EPNum, Ep[EP_OUT_IDX(EPNum)].maxPacket);
  }

  /* OUT Packet                                                               */
  else {
    if (Ep[EP_OUT_IDX(EPNum)].buf) {
      cnt = Ep[EP_OUT_IDX(EPNum)].maxPacket - 
           ((dTDx[EP_OUT_IDX(EPNum)].dTD_token >> 16) & 0x7FFF);
      for (i = 0; i < cnt; i++) {
        pData[i] =  Ep[EP_OUT_IDX(EPNum)].buf[i];
      }
    }
    LPC_USBx->ENDPTCOMPLETE = (1UL << EPNum);
    cmpl_pnd &= ~(1UL << EPNum);
    USBD_PrimeEp(EPNum, Ep[EP_OUT_IDX(EPNum)].maxPacket);
  }
void USBD_ResetEP (uint32_t EPNum) {
  if (EPNum & 0x80) {
    EPNum &= 0x7F;
    EPQHx[EP_IN_IDX(EPNum)].dTD_token &= 0xC0;
    LPC_USBx->ENDPTFLUSH = (1UL << (EPNum + 16));  /* flush endpoint          */
    while (LPC_USBx->ENDPTFLUSH & (1UL << (EPNum + 16)));
    ENDPTCTRL(EPNum) |= (1UL << 22);    /* data toggle reset                  */
  }
  else {
    EPQHx[EP_OUT_IDX(EPNum)].dTD_token &= 0xC0;
    LPC_USBx->ENDPTFLUSH = (1UL << EPNum);         /* flush endpoint          */
    while (LPC_USBx->ENDPTFLUSH & (1UL << EPNum));
    ENDPTCTRL(EPNum) |= (1UL << 6 );    /* data toggle reset                  */
    USBD_PrimeEp(EPNum, Ep[EP_OUT_IDX(EPNum)].maxPacket);
  }
} 
void USBD_Reset(void)
{
    uint32_t i;
    uint8_t *ptr;
    cmpl_pnd = 0;

    for (i = 1; i < USBD_EP_NUM + 1; i++) {
        ENDPTCTRL(i) &= ~((1UL << 7) | (1UL << 23));
    }

    /* clear interrupts */
    LPC_USBx->ENDPTNAK       = 0xFFFFFFFF;
    LPC_USBx->ENDPTNAKEN     = 0;
    LPC_USBx->USBSTS_D       = 0xFFFFFFFF;
    LPC_USBx->ENDPTSETUPSTAT = LPC_USBx->ENDPTSETUPSTAT;
    LPC_USBx->ENDPTCOMPLETE  = LPC_USBx->ENDPTCOMPLETE;

    while (LPC_USBx->ENDPTPRIME);

    LPC_USBx->ENDPTFLUSH = 0xFFFFFFFF;

    while (LPC_USBx->ENDPTFLUSH);

    LPC_USBx->USBCMD_D &= ~0x00FF0000;    /* immediate intrrupt treshold */
    /* clear endpoint queue heads */
    ptr = (uint8_t *)EPQHx;

    for (i = 0; i < sizeof(EPQHx); i++) {
        ptr[i] = 0;
    }

    /* clear endpoint transfer descriptors */
    ptr = (uint8_t *)dTDx;

    for (i = 0; i < sizeof(dTDx); i++) {
        ptr[i] = 0;
    }

    Ep[EP_OUT_IDX(0)].maxPacket  = USBD_MAX_PACKET0;
    Ep[EP_OUT_IDX(0)].buf        = EPBufPool;
    BufUsed                      = USBD_MAX_PACKET0;
    Ep[EP_IN_IDX(0)].maxPacket   = USBD_MAX_PACKET0;
    Ep[EP_IN_IDX(0)].buf         = &(EPBufPool[BufUsed]);
    BufUsed                     += USBD_MAX_PACKET0;
    dTDx[EP_OUT_IDX(0)].next_dTD = 1;
    dTDx[EP_IN_IDX(0)].next_dTD = 1;
    dTDx[EP_OUT_IDX(0)].dTD_token = (USBD_MAX_PACKET0 << 16) | /* total bytes */
                                    (1UL << 15);               /* int on compl */
    dTDx[EP_IN_IDX(0)].dTD_token = (USBD_MAX_PACKET0 << 16) |  /* total bytes */
                                   (1UL << 15);                /* int on compl */
    EPQHx[EP_OUT_IDX(0)].next_dTD = (uint32_t) &dTDx[EP_OUT_IDX(0)];
    EPQHx[EP_IN_IDX(0)].next_dTD = (uint32_t) &dTDx[EP_IN_IDX(0)];
    EPQHx[EP_OUT_IDX(0)].cap = ((USBD_MAX_PACKET0 & 0x0EFF) << 16) |
                               (1UL << 29) |
                               (1UL << 15);                    /* int on setup */
    EPQHx[EP_IN_IDX(0)].cap = (USBD_MAX_PACKET0 << 16) |
                              (1UL << 29) |
                              (1UL << 15);                    /* int on setup */
    LPC_USBx->ENDPOINTLISTADDR = (uint32_t)EPQHx;
    LPC_USBx->USBMODE_D |= (1UL << 3);    /* Setup lockouts off */
    LPC_USBx->ENDPTCTRL0 = 0x00C000C0;
    USBD_PrimeEp(0, Ep[EP_OUT_IDX(0)].maxPacket);
}