]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blobdiff - sw/app/rocon/appl_usb.c
RoCoN: USB CDC ACM use maximal packet length - 64 bytes.
[fpga/lx-cpu1/lx-rocon.git] / sw / app / rocon / appl_usb.c
index e809fc837c692953bbd39e2b4a4fdf3c7c1249ee..9e87227ae33ba1faf7befe5cf3d43031a9051c93 100644 (file)
-#include <types.h>
+#include <inttypes.h>
 #include <cpu_def.h>
 #include <system_def.h>
 #include <string.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <endian.h>
 #include <usb/lpc.h>
 #include <usb/usb.h>
 #include <usb/usb_loader.h>
 #include <usb/usbdebug.h>
+#include <cmd_proc.h>
+#include <hal_gpio.h>
 
 #include "appl_defs.h"
+#include "usb/usb_defs.h"
+#include "appl_fpga.h"
+
+#ifdef CONFIG_KEYVAL
+#include <keyvalpb.h>
+#include <lpciap.h>
+#include <lpciap_kvpb.h>
+#include <hal_machperiph.h>
+#endif /*CONFIG_KEYVAL*/
 
-#ifdef CONFIG_LIB_U2U_V2
- #define NUM_ENDPOINTS 2
- #define USB_VENDOR_ID      0x1669
- #define USB_PRODUCT_ID     0x1001
+#ifdef CONFIG_OC_MTD_DRV_SYSLESS
+#include <mtd_spi_drv.h>
 #endif
 
-#include "usb/usb_defs.h"
+#include <endian.h>
+#if __BYTE_ORDER == __BIG_ENDIAN
+#include <byteswap.h>
+#define SWAP(x) ((((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF))
+#else /*__LITTLE_ENDIAN*/
+#define SWAP(x) (x)
+#endif
+
+#define USB_VENDOR_TARGET_TUMBL                   0x03
+#define USB_VENDOR_TARGET_32BIT                   0x04
+#define USB_VENDOR_TARGET_SPI_FLASH               0x05
+
+#define USB_CMD_FPGA_CONFIGURE                    0xF000
+#define USB_CMD_FPGA_MEASURE_READ                 0xF001
+#define USB_CMD_FPGA_MEASURE_WRITE                0xF002
+
+#define USB_CMD_FPGA_IRC_GET_RESET                0xF010
+#define USB_CMD_FPGA_IRC_SET_RESET                0xF011
+#define USB_CMD_FPGA_IRC_DUMP                     0xF012
+
+#define USB_CMD_FPGA_LXMASTER_GET_RESET           0xF020
+#define USB_CMD_FPGA_LXMASTER_SET_RESET           0xF021
+#define USB_CMD_FPGA_LXMASTER_TRANSMITTER_GET_REG 0xF022
+#define USB_CMD_FPGA_LXMASTER_TRANSMITTER_SET_REG 0xF023
+#define USB_CMD_FPGA_LXMASTER_TRANSMITTER_WRITE   0xF024
+#define USB_CMD_FPGA_LXMASTER_TRANSMITTER_DUMP    0xF025
+
+#define USB_CMD_FPGA_TUMBL_SET_RESET              0xF100
+#define USB_CMD_FPGA_TUMBL_SET_HALT               0xF101
+#define USB_CMD_FPGA_TUMBL_SET_TRACE              0xF102
+#define USB_CMD_FPGA_TUMBL_KICK_TRACE             0xF103
+#define USB_CMD_FPGA_TUMBL_GET_PC                 0xF104
+
+#define USB_CMD_FPGA_TUMBL_DUMP_IMEM              0xF200
+#define USB_CMD_FPGA_TUMBL_DUMP_DMEM              0xF201
+
+#define USB_CMD_FPGA_RESET                        0xFFFF
 
 usb_device_t usb_device;
 usb_ep_t eps[NUM_ENDPOINTS];
 
-#define MASK_EP1RX  0x01
-#define MASK_EP1TX  0x02
+#define CDC0_EPIDX_NOTIFY 0
+#define CDC0_EPIDX_RXD    1
+#define CDC0_EPIDX_TXD    2
+#define CDC0_MASK_EP_NOTIFY  (1<<CDC0_EPIDX_NOTIFY)
+#define CDC0_MASK_EP_RXD     (1<<CDC0_EPIDX_RXD)
+#define CDC0_MASK_EP_TXD     (1<<CDC0_EPIDX_TXD)
 
-extern int usb_common_loader(usb_device_t *udev);
+unsigned char cdc0_ep_tx_buff[CDC0_MAX_PACKET] __attribute__ ((aligned (8)));
+unsigned char cdc0_ep_rx_buff[CDC0_MAX_PACKET] __attribute__ ((aligned (8)));
+unsigned char ep0_buffer[USB_MAX_PACKET0] __attribute__ ((aligned (8)));
+int cdc0_tx_index = 0, cdc0_tx_ready = 1;
+int cdc0_tx_flush_required;
+int cdc0_rx_index = 0, cdc0_rx_chars = 0;
 
-#ifdef CONFIG_LIB_U2U_V2
+uint16_t cdc0_serial_state = 0; /* USBCDC_SERIAL_STATE_xxx */
+acm_desc_t usbcdc_acm_description;
 
-#include "ul_dcnv.h"
-#include "u2u_vend.h"
+int usb_active = 0;
 
-const char ul_dcnv_idstr[]=".mt u2u_v2int";
+#ifdef CONFIG_OC_CMDPROC
 
-ul_dcnv_state_t ep1_dcnv_state;
-unsigned char ep1_rx_buff[USB_MAX_PACKET];
-unsigned char ep1_tx_buff[USB_MAX_PACKET];
+cmd_io_t cmd_io_usbcon_dev;
 
-int appl_usb_vendor(usb_device_t *udev)
+#define ED_LINE_CHARS 512
+
+char ed_line_chars_usbcon_in[ED_LINE_CHARS + 1];
+char ed_line_chars_usbcon_out[ED_LINE_CHARS + 1];
+
+ed_line_buf_t ed_line_buf_usbcon_in =
 {
-  int ret;
-  ret = usb_u2u_vendor4dcnv(&ep1_dcnv_state, udev);
-  if(ret)
-    return ret;
-  return usb_common_loader(udev);
-}
+flg:
+  FL_ELB_ECHO,
+  inbuf: 0,
+alloc:
+  sizeof(ed_line_chars_usbcon_in),
+  maxlen: 0,
+  lastch: 0,
+buf:
+  ed_line_chars_usbcon_in
+};
 
-int appl_usb_u2u_poll(void)
+ed_line_buf_t ed_line_buf_usbcon_out =
 {
-  int active=0;
+flg:
+  FL_ELB_NOCRLF,
+  inbuf: 0,
+alloc:
+  sizeof(ed_line_chars_usbcon_out),
+  maxlen: 0,
+  lastch: 0,
+buf:
+  ed_line_chars_usbcon_out
+};
 
-  if (usb_device.ep_events & MASK_EP1RX) {  //EP1RX
-    int size;
-    size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,USB_MAX_PACKET);
-    ul_dcnv_send(&ep1_dcnv_state,ep1_rx_buff,size);
-    usb_device.ep_events &= ~MASK_EP1RX;
-    //timer_tx_off=5;          //rozsviceni diod pri vysilani 
-    //CLR_OUT_PIN(LED_PORT,LED1_BIT);
-    active=1;
+cmd_io_t cmd_io_usbcon =
+{
+putc:
+  cmd_io_line_putc,
+getc:
+  NULL,
+write:
+  cmd_io_write_bychar,
+read:
+  NULL,
+priv:
+  {
+  ed_line:
+    {
+    in:
+      &ed_line_buf_usbcon_in,
+    out:
+      &ed_line_buf_usbcon_out,
+    io_stack:
+      &cmd_io_usbcon_dev
+    }
   }
+};
 
-  if(usb_device.ep_events & MASK_EP1TX){
-    ep1_dcnv_state.rx_wait4host=0;
-    usb_device.ep_events &= ~MASK_EP1TX;
-  }
+#endif
+
+static int usb_flash_pkt_wr(struct usb_ep_t *ep, int len, int code)
+{
+  unsigned char *ptr = ep->ptr - len;
+
+#ifdef CONFIG_KEYVAL
+  lpcisp_kvpb_copy(NULL, (void *)ep->user_data, ptr, len);
+#endif /*CONFIG_KEYVAL*/
+
+  ep->user_data += len;
+  ep->ptr = ep0_buffer;
+  return USB_COMPLETE_OK;
+}
+
+static int usb_tumbl_pkt_wr(struct usb_ep_t *ep, int len, int code)
+{
+  unsigned char *ptr = ep->ptr - len;
+
+  fpga_tumbl_write(ep->user_data, ptr, len);
+
+  ep->user_data += len;
+  ep->ptr = ep0_buffer;
+  return USB_COMPLETE_OK;
+}
+
+static int usb_32bit_pkt_wr(struct usb_ep_t *ep, int len, int code)
+{
+  uint32_t *srcptr = (uint32_t *)(ep->ptr - len);
+  volatile uint32_t *dstptr = (uint32_t *)ep->user_data;
+  int pos;
+
+  for (pos = 0; len - pos >= 4; pos += 4, dstptr++, srcptr++)
+    *dstptr = *srcptr;
+
+  ep->user_data += len;
+  ep->ptr = ep0_buffer;
+  return USB_COMPLETE_OK;
+}
+
+int usb_32bit_pkt_rd(struct usb_ep_t *ep, int len, int code)
+{
+  volatile uint32_t *srcptr;
+  uint32_t *dstptr;
+  int pos;
+
+  ep->ptr = ep0_buffer;
+  dstptr = (uint32_t *)ep->ptr;
+  srcptr = (uint32_t *)ep->user_data;
+
+  for (pos = 0; len - pos >= 4; pos += 4, dstptr++, srcptr++)
+    *dstptr = *srcptr;
+
+  ep->user_data += len;
+  return USB_COMPLETE_OK;
+}
+
+static int usb_flash_erase(unsigned addr, unsigned len)
+{
+#ifdef CONFIG_KEYVAL
+  lpcisp_erase((void *)addr, len);
+#endif /*CONFIG_KEYVAL*/
+  return 0;
+}
+
+static int usb_spi_flash_pkt_wr(struct usb_ep_t *ep, int len, int code)
+{
+  unsigned char *ptr = ep->ptr - len;
+
+#ifdef CONFIG_OC_MTD_DRV_SYSLESS
+  mtd_spi_write(&mtd_spi_state, ptr, len, ep->user_data, 0);
+#endif /*CONFIG_KEYVAL*/
+
+  ep->user_data += len;
+  ep->ptr = ep0_buffer;
+  return USB_COMPLETE_OK;
+}
+
+int usb_spi_flash_pkt_rd(struct usb_ep_t *ep, int len, int code)
+{
+  ep->ptr = ep0_buffer;
+#ifdef CONFIG_OC_MTD_DRV_SYSLESS
+  mtd_spi_read(&mtd_spi_state, ep->ptr, len, ep->user_data, 0);
+#endif /*CONFIG_KEYVAL*/
+
+  ep->user_data += len;
+  return USB_COMPLETE_OK;
+}
+
+int usb_spi_flash_mass_erase(int mode)
+{
+#ifdef CONFIG_OC_MTD_DRV_SYSLESS
+  mtd_spi_set_protect_mode(&mtd_spi_state, 0, 0);
+  mtd_spi_chip_erase(&mtd_spi_state, mode, 0);
+#endif /*CONFIG_KEYVAL*/
+  return 0;
+}
+
+static void usb_goto(unsigned address)
+{
+#ifdef CONFIG_KEYVAL
+  lpc_watchdog_init(1, 10);
+  lpc_watchdog_feed();
+
+  while (1)
+    {}
+
+#endif /*CONFIG_KEYVAL*/
+}
 
-  if (!ep1_dcnv_state.rx_wait4host) { // EP1TX
-    int size=ul_dcnv_rec(&ep1_dcnv_state, ep1_tx_buff, USB_MAX_PACKET);
-    if (size){
-      usb_udev_write_endpoint(&eps[1],ep1_tx_buff,size);
-      ep1_dcnv_state.rx_wait4host=1;
-    } else {
-      if (ul_dcnv_rec_start(&ep1_dcnv_state, ep1_tx_buff,8)==8) { //HEADER
-        usb_udev_write_endpoint(&eps[1],ep1_tx_buff,8);
-        //timer_rx_off=5;        //rosviceni diody pri prijmu 
-        //CLR_OUT_PIN(LED_PORT,LED2_BIT);
-        ep1_dcnv_state.rx_wait4host=1;
-        active=1;
+/* Not re-entrant */
+uint16_t vendor_call_ret = 0xFFFF;
+
+uint16_t appl_usb_vendor_call(uint16_t command, uint16_t argument)
+{
+  int i, j;
+
+  switch (command)
+  {
+    case USB_CMD_FPGA_CONFIGURE:
+      return fpga_configure();
+
+    case USB_CMD_FPGA_MEASURE_READ:
+      return fpga_measure_bus_read();
+
+    case USB_CMD_FPGA_MEASURE_WRITE:
+      return fpga_measure_bus_write();
+
+    case USB_CMD_FPGA_IRC_GET_RESET:
+      printf("IRC RESET: 0x%02x\n", *fpga_irc_reset);
+      return 0;
+
+    case USB_CMD_FPGA_IRC_SET_RESET:
+      /* When starting, zero out counters */
+      *fpga_irc_reset = argument & 0x0001;
+      return 0;
+
+    case USB_CMD_FPGA_IRC_DUMP:
+      for (i = 0; i < 8; i++)
+        printf("IRC%d: count = %d, count index = %d, mark = %d, ab_error = %d, index_event = %d, index = %d\n", i+1,
+               (unsigned int) fpga_irc[i]->count, (unsigned int) fpga_irc[i]->count_index, ((*(fpga_irc_state[i])) & 0x01) != 0,
+               ((*(fpga_irc_state[i])) & 0x02) != 0, ((*(fpga_irc_state[i])) & 0x04) != 0, ((*(fpga_irc_state[i])) & 0x08) != 0);
+      return 0;
+
+    case USB_CMD_FPGA_LXMASTER_GET_RESET:
+      printf("LXMASTER RESET: 0x%02"PRIx32"\n", *fpga_lx_master_reset);
+      return 0;
+
+    case USB_CMD_FPGA_LXMASTER_SET_RESET:
+      /* When starting, zero out counters */
+      *fpga_lx_master_reset = argument & 0x0001;
+      return 0;
+
+    case USB_CMD_FPGA_LXMASTER_TRANSMITTER_GET_REG:
+      printf("LXMASTER TRANSMITTER REG: 0x%02"PRIx32"\n", *fpga_lx_master_transmitter_reg);
+      return 0;
+
+    case USB_CMD_FPGA_LXMASTER_TRANSMITTER_SET_REG:
+      /* When starting, zero out counters */
+      *fpga_lx_master_transmitter_reg = argument & 0x0001;
+      return 0;
+
+    case USB_CMD_FPGA_LXMASTER_TRANSMITTER_WRITE:
+      for (i = 0; i < (argument / 4); i++)
+        fpga_lx_master_transmitter_base[i] = fpga_lx_master_conf[i];
+      return 0;
+
+    case USB_CMD_FPGA_LXMASTER_TRANSMITTER_DUMP:
+      printf("LX MASTER TRANSMITTER MEM:\n");
+      for (i = 0; i < 16; i++)
+      {
+        for (j = 0; j < 16; j++)
+          printf("%04X ", (unsigned int) (fpga_lx_master_transmitter_base[i*16 + j] & 0xFFFF));
+
+        printf("\n");
       }
-    }
+      return 0;
+
+    case USB_CMD_FPGA_TUMBL_SET_RESET:
+      return fpga_tumbl_set_reset(argument);
+
+    case USB_CMD_FPGA_TUMBL_SET_HALT:
+      return fpga_tumbl_set_halt(argument);
+
+    case USB_CMD_FPGA_TUMBL_SET_TRACE:
+      return fpga_tumbl_set_trace(argument);
+
+    case USB_CMD_FPGA_TUMBL_KICK_TRACE:
+      return fpga_tumbl_kick_trace();
+
+    case USB_CMD_FPGA_TUMBL_GET_PC:
+      printf("Tubml PC: 0x%08X\n", (unsigned int) *fpga_tumbl_pc);
+      return 0;
+
+    case USB_CMD_FPGA_TUMBL_DUMP_IMEM:
+      printf("TUMBL IMEM:\n");
+      for (i = 0; i < 64; i++)
+      {
+        for (j = 0; j < 8; j++)
+          printf("%08X ", (unsigned int) fpga_tumbl_imem[i*8 + j]);
+
+        printf("\n");
+      }
+      return 0;
+
+    case USB_CMD_FPGA_TUMBL_DUMP_DMEM:
+      printf("TUMBL DMEM:\n");
+      for (i = 0; i < 128; i++)
+      {
+        for (j = 0; j < 8; j++)
+          printf("%08X ", (unsigned int) fpga_tumbl_dmem[i*8 + j]);
+
+        printf("\n");
+      }
+      return 0;
+
+    case USB_CMD_FPGA_RESET:
+      hal_gpio_direction_output(XC_INIT_PIN, 0);
+
+      for (i = 0; i < 128; i++)
+        {}
+
+      hal_gpio_direction_output(XC_INIT_PIN, 1);
+      return 0;
   }
-  return active;
+
+  return 0xFFFF;
 }
 
-#endif /*CONFIG_LIB_U2U_V2*/
+int appl_usb_vendor(usb_device_t *udev)
+{
+  unsigned long addr;
+  unsigned len;
+  USB_DEVICE_REQUEST *dreq;
+
+  usb_active = 1;
+  dreq = &udev->request;
+
+#ifdef CONFIG_KEYVAL
+
+  if (dreq->bRequest != (USB_VENDOR_GET_SET_MEMORY |
+                         USB_DATA_DIR_FROM_HOST | USB_VENDOR_TARGET_FLASH))
+    lpcisp_kvpb_flush(NULL);
+
+#endif /*CONFIG_KEYVAL*/
+
+  switch (dreq->bRequest & USB_VENDOR_MASK)
+  {
+    case USB_VENDOR_GET_CAPABILITIES:
+      ep0_buffer[0] = 0xAA; // test
+      usb_send_control_data(udev, ep0_buffer, 1);
+      return 1;
+
+    case USB_VENDOR_RESET_DEVICE:
+      usb_send_control_data(udev, NULL, 0);
+#ifdef CONFIG_KEYVAL
+      lpc_watchdog_init(1, 10);
+      lpc_watchdog_feed();
+
+      while (1)
+        {}
+
+#endif /*CONFIG_KEYVAL*/
+      return 1;
+
+    case USB_VENDOR_GOTO:
+      usb_send_control_data(udev, NULL, 0);
+      usb_goto(dreq->wValue);
+      return 1;
+
+    case USB_VENDOR_ERASE_MEMORY:
+      usb_send_control_data(udev, NULL, 0);
+      usb_flash_erase(dreq->wValue, dreq->wIndex);
+      return 1;
+
+    case USB_VENDOR_ERASE_1KB_MEMORY:  /* erase memory for 1 KB */
+      usb_send_control_data(udev, NULL, 0);
+      usb_flash_erase((uint32_t)dreq->wValue << 10, dreq->wIndex << 10);
+      return 1;
+
+    case USB_VENDOR_MASS_ERASE:
+      usb_send_control_data(udev, NULL, 0);
+      if (dreq->wIndex == 5)
+         usb_spi_flash_mass_erase(dreq->wValue);
+      return 1;
+
+    case USB_VENDOR_CALL:
+      vendor_call_ret = SWAP(appl_usb_vendor_call(dreq->wIndex, dreq->wValue));
+      usb_send_control_data(udev, (unsigned char *) &vendor_call_ret, sizeof(uint16_t));
+      return 1;
+
+    case USB_VENDOR_GET_SET_MEMORY:
+      addr = (dreq->wValue & 0xffff) | (((unsigned long)dreq->wIndex & 0xffff) << 16);
+      len = dreq->wLength;
+
+      if ((dreq->bmRequestType & USB_DATA_DIR_MASK) == USB_DATA_DIR_FROM_HOST)
+      {
+        switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
+        {
+          case USB_VENDOR_TARGET_RAM:
+            udev->ep0.ptr = (void *)addr;
+            break;
+
+          case USB_VENDOR_TARGET_FLASH:
+            udev->ep0.next_pkt_fnc = usb_flash_pkt_wr;
+            udev->ep0.user_data = addr;
+            udev->ep0.ptr = ep0_buffer;
+            break;
+
+          case USB_VENDOR_TARGET_TUMBL:
+            udev->ep0.next_pkt_fnc = usb_tumbl_pkt_wr;
+            udev->ep0.user_data = addr;
+            udev->ep0.ptr = ep0_buffer;
+            break;
+
+          case USB_VENDOR_TARGET_32BIT:
+            udev->ep0.next_pkt_fnc = usb_32bit_pkt_wr;
+            udev->ep0.user_data = addr;
+            udev->ep0.ptr = ep0_buffer;
+            break;
+
+          case USB_VENDOR_TARGET_SPI_FLASH:
+            udev->ep0.next_pkt_fnc = usb_spi_flash_pkt_wr;
+            udev->ep0.user_data = addr;
+            udev->ep0.ptr = ep0_buffer;
+            break;
+
+          default:
+            return -1;
+        }
+
+        if (len)
+          usb_set_control_endfnc(udev, usb_ack_setup);
+        else
+          usb_send_control_data(udev, NULL, 0);
+
+        return 1;
+      }
+      else
+      {
+        switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
+        {
+          case USB_VENDOR_TARGET_RAM:
+            usb_send_control_data(udev, (void *)addr, len);
+            break;
+
+          case USB_VENDOR_TARGET_32BIT:
+            udev->ep0.next_pkt_fnc = usb_32bit_pkt_rd;
+            udev->ep0.user_data=addr;
+            usb_send_control_data( udev, ep0_buffer, len);
+            break;
+
+          case USB_VENDOR_TARGET_SPI_FLASH:
+            udev->ep0.next_pkt_fnc = usb_spi_flash_pkt_rd;
+            udev->ep0.user_data=addr;
+            usb_send_control_data( udev, ep0_buffer, len);
+            break;
+
+          default:
+            return -1;
+        }
+
+        return 1;
+      }
+
+      break;
+  }
+
+  return 0;
+}
 
 int usb_app_fill_serial_number(uint32_t ul_sn)
 {
-  char *p=usb_devdes_serial_number;
-  int len_max=sizeof(usb_devdes_serial_number);
+  char *p = usb_devdes_serial_number;
+  int len_max = sizeof(usb_devdes_serial_number);
   char c;
 
-  while((len_max-=2)>=2) {
-    p+=2;
-    c=((ul_sn>>(32-4))&0xf)+'0';
-    ul_sn<<=4;
-    if(c>'9') c+='A'-'9'-1;
-    *p=c;
+  while ((len_max -= 2) >= 2)
+  {
+    p += 2;
+    c = ((ul_sn >> (32 - 4)) & 0xf) + '0';
+    ul_sn <<= 4;
+
+    if (c > '9')
+      c += 'A' - '9' - 1;
+
+    *p = c;
   }
+
   return 0;
 }
 
+static inline
+int usb_app_epnum2event_mask(int epnum)
+{
+  int evmask;
+  int evbit;
+  /* LPC17xx EP1RX 0x04, EP1TX 0x08, EP2RX 0x10, EP2TX 0x20 */
+
+  evbit = (epnum & ~USB_ENDPOINT_DIRECTION_MASK) * 2;
+  if (epnum & USB_ENDPOINT_DIRECTION_MASK)
+    evbit++;
+
+  evmask = 1 << evbit;
+
+  return evmask;
+}
+
 int usb_app_init(void)
 {
-  memset( &usb_device, 0, sizeof( usb_device));
+  memset(&usb_device, 0, sizeof(usb_device));
+
+  eps[CDC0_EPIDX_NOTIFY].max_packet_size = USB_MAX_PACKET;
+  eps[CDC0_EPIDX_RXD].max_packet_size = CDC0_MAX_PACKET;
+  eps[CDC0_EPIDX_TXD].max_packet_size = CDC0_MAX_PACKET;
+  eps[CDC0_EPIDX_NOTIFY].epnum = CDC0_EP_NOTIFY;
+  eps[CDC0_EPIDX_RXD].epnum = CDC0_EP_RXD;
+  eps[CDC0_EPIDX_TXD].epnum = CDC0_EP_TXD;
+  eps[CDC0_EPIDX_NOTIFY].event_mask = usb_app_epnum2event_mask(CDC0_EP_NOTIFY); /* 0x08; */
+  eps[CDC0_EPIDX_RXD].event_mask = usb_app_epnum2event_mask(CDC0_EP_RXD); /* 0x10; */
+  eps[CDC0_EPIDX_TXD].event_mask = usb_app_epnum2event_mask(CDC0_EP_TXD); /* 0x20; */
+  eps[CDC0_EPIDX_NOTIFY].udev = &usb_device;
+  eps[CDC0_EPIDX_RXD].udev = &usb_device;
+  eps[CDC0_EPIDX_TXD].udev = &usb_device;
+
   usb_device.id = 1;
   usb_device.devdes_table = &usb_devdes_table;
   usb_device.init = usb_lpc_init;
   usb_debug_set_level(DEBUG_LEVEL_NONE);
   usb_device.cntep = NUM_ENDPOINTS;
   usb_device.ep = eps;
+  usb_device.vendor_fnc = appl_usb_vendor;
+  usb_device.class_fnc = usbcdc_acm_class_response;
 
- #ifndef CONFIG_LIB_U2U_V2
-  usb_device.vendor_fnc=usb_common_loader;
- #else /*CONFIG_LIB_U2U_V2*/
-  eps[0].max_packet_size = USB_MAX_PACKET;
-  eps[1].max_packet_size = USB_MAX_PACKET;
-  eps[0].epnum = 0x01;
-  eps[1].epnum = 0x81;
-  eps[0].event_mask = 0x04;
-  eps[1].event_mask = 0x08;
-  eps[0].udev = &usb_device;
-  eps[1].udev = &usb_device;
+  usb_init(&usb_device);
+  usb_connect(&usb_device);
 
-  usb_device.vendor_fnc=appl_usb_vendor;
+  return 0;
+}
 
-  ul_dcnv_init_by_name(&ep1_dcnv_state,NULL,1);
-  ep1_dcnv_state.idstr=ul_dcnv_idstr;
- #endif /*CONFIG_LIB_U2U_V2*/
+int cdc0_txd_check_ep(void)
+{
+  if (usb_device.ep_events & CDC0_MASK_EP_TXD)
+  {
+    usb_device.ep_events &= ~CDC0_MASK_EP_TXD;
+    //TODO: Use some field in the structure, probably flags
+    cdc0_tx_ready = 1;
+  }
+
+  /* Respond if there is something to send and RX is ready */
+  if (cdc0_tx_ready && ((cdc0_tx_index != 0) || cdc0_tx_flush_required))
+  {
+    usb_udev_write_endpoint(&eps[CDC0_EPIDX_TXD], cdc0_ep_tx_buff, cdc0_tx_index);
+    cdc0_tx_flush_required = (cdc0_tx_index == CDC0_MAX_PACKET);
+    cdc0_tx_index = 0;
+    cdc0_tx_ready = 0;
+    hal_gpio_set_value(LED2_PIN, 0);
+    return 1;
+  }
 
-  usb_init(&usb_device);
-  usb_connect(&usb_device);
   return 0;
 }
 
 int usb_app_poll(void)
 {
-  int active = usb_loadder_active;
-  static char last_configuration = 0;
-  usb_loadder_active = 0;
+  int active = usb_active;
+  usb_active = 0;
 
   usb_check_events(&usb_device);
   usb_control_response(&usb_device);
 
-  if(usb_device.configuration != last_configuration) {
-    last_configuration = usb_device.configuration;
+  /* Check RXD/OUT endpoint */
+  if (usb_device.ep_events & CDC0_MASK_EP_NOTIFY)
+  {
+    usb_udev_read_endpoint(&eps[CDC0_EPIDX_NOTIFY], &cdc0_serial_state, 2);
+    usb_device.ep_events &= ~CDC0_MASK_EP_NOTIFY;
+    usb_active = 1;
   }
 
- #ifdef CONFIG_LIB_U2U_V2
-  if (ul_dcnv_is_open(&ep1_dcnv_state)) {
-   if (usb_device.configuration == 0)
-     ul_dcnv_close(&ep1_dcnv_state);
-   else
-     if(appl_usb_u2u_poll()>0)
-       active=1;
+  /* Check RXD/OUT endpoint */
+  if (usb_device.ep_events & CDC0_MASK_EP_RXD)
+  {
+    cdc0_rx_chars = usb_udev_read_endpoint(&eps[CDC0_EPIDX_RXD], cdc0_ep_rx_buff, CDC0_MAX_PACKET);
+    cdc0_rx_index = 0;
+    usb_device.ep_events &= ~CDC0_MASK_EP_RXD;
+    hal_gpio_set_value(LED2_PIN, 0);
+    usb_active = 1;
   }
- #endif /*CONFIG_LIB_U2U_V2*/
+
+  /* Check RX endpoint */
+  usb_active |= cdc0_txd_check_ep();
 
   return active;
 }
@@ -166,3 +646,41 @@ int usb_app_stop(void)
   usb_disconnect(&usb_device);
   return 0;
 }
+
+#ifdef CONFIG_OC_CMDPROC
+
+int cmd_io_getc_usbcon(struct cmd_io *cmd_io)
+{
+  if (cdc0_rx_index >= cdc0_rx_chars)
+    return -1;
+
+  return cdc0_ep_rx_buff[cdc0_rx_index++];
+}
+
+int cmd_io_putc_usbcon(struct cmd_io *cmd_io, int ch)
+{
+  if (cdc0_tx_index >= CDC0_MAX_PACKET)
+  {
+    /* Check EP1 status and return -1 if unavailable */
+    usb_check_events(&usb_device);
+    cdc0_txd_check_ep();
+
+    /* Check again if it wasn't emptied */
+    if (cdc0_tx_index >= CDC0_MAX_PACKET)
+      return -1;
+  }
+
+  cdc0_ep_tx_buff[cdc0_tx_index++] = (unsigned char)ch;
+  return ch;
+}
+
+cmd_io_t cmd_io_usbcon_dev =
+{
+  .putc = cmd_io_putc_usbcon,
+  .getc = cmd_io_getc_usbcon,
+  .write = cmd_io_write_bychar,
+  .read = cmd_io_read_bychar,
+  .priv.uart = { -1 }
+};
+
+#endif