]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - 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
1 #include <inttypes.h>
2 #include <cpu_def.h>
3 #include <system_def.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <endian.h>
8 #include <usb/lpc.h>
9 #include <usb/usb.h>
10 #include <usb/usb_loader.h>
11 #include <usb/usbdebug.h>
12 #include <cmd_proc.h>
13 #include <hal_gpio.h>
14
15 #include "appl_defs.h"
16 #include "usb/usb_defs.h"
17 #include "appl_fpga.h"
18
19 #ifdef CONFIG_KEYVAL
20 #include <keyvalpb.h>
21 #include <lpciap.h>
22 #include <lpciap_kvpb.h>
23 #include <hal_machperiph.h>
24 #endif /*CONFIG_KEYVAL*/
25
26 #ifdef CONFIG_OC_MTD_DRV_SYSLESS
27 #include <mtd_spi_drv.h>
28 #endif
29
30 #include <endian.h>
31 #if __BYTE_ORDER == __BIG_ENDIAN
32 #include <byteswap.h>
33 #define SWAP(x) ((((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF))
34 #else /*__LITTLE_ENDIAN*/
35 #define SWAP(x) (x)
36 #endif
37
38 #define USB_VENDOR_TARGET_TUMBL                   0x03
39 #define USB_VENDOR_TARGET_32BIT                   0x04
40 #define USB_VENDOR_TARGET_SPI_FLASH               0x05
41
42 #define USB_CMD_FPGA_CONFIGURE                    0xF000
43 #define USB_CMD_FPGA_MEASURE_READ                 0xF001
44 #define USB_CMD_FPGA_MEASURE_WRITE                0xF002
45
46 #define USB_CMD_FPGA_IRC_GET_RESET                0xF010
47 #define USB_CMD_FPGA_IRC_SET_RESET                0xF011
48 #define USB_CMD_FPGA_IRC_DUMP                     0xF012
49
50 #define USB_CMD_FPGA_LXMASTER_GET_RESET           0xF020
51 #define USB_CMD_FPGA_LXMASTER_SET_RESET           0xF021
52 #define USB_CMD_FPGA_LXMASTER_TRANSMITTER_GET_REG 0xF022
53 #define USB_CMD_FPGA_LXMASTER_TRANSMITTER_SET_REG 0xF023
54 #define USB_CMD_FPGA_LXMASTER_TRANSMITTER_WRITE   0xF024
55 #define USB_CMD_FPGA_LXMASTER_TRANSMITTER_DUMP    0xF025
56
57 #define USB_CMD_FPGA_TUMBL_SET_RESET              0xF100
58 #define USB_CMD_FPGA_TUMBL_SET_HALT               0xF101
59 #define USB_CMD_FPGA_TUMBL_SET_TRACE              0xF102
60 #define USB_CMD_FPGA_TUMBL_KICK_TRACE             0xF103
61 #define USB_CMD_FPGA_TUMBL_GET_PC                 0xF104
62
63 #define USB_CMD_FPGA_TUMBL_DUMP_IMEM              0xF200
64 #define USB_CMD_FPGA_TUMBL_DUMP_DMEM              0xF201
65
66 #define USB_CMD_FPGA_RESET                        0xFFFF
67
68 usb_device_t usb_device;
69 usb_ep_t eps[NUM_ENDPOINTS];
70
71 #define CDC0_EPIDX_NOTIFY 0
72 #define CDC0_EPIDX_RXD    1
73 #define CDC0_EPIDX_TXD    2
74 #define CDC0_MASK_EP_NOTIFY  (1<<CDC0_EPIDX_NOTIFY)
75 #define CDC0_MASK_EP_RXD     (1<<CDC0_EPIDX_RXD)
76 #define CDC0_MASK_EP_TXD     (1<<CDC0_EPIDX_TXD)
77
78 unsigned char cdc0_ep_tx_buff[CDC0_MAX_PACKET] __attribute__ ((aligned (8)));
79 unsigned char cdc0_ep_rx_buff[CDC0_MAX_PACKET] __attribute__ ((aligned (8)));
80 unsigned char ep0_buffer[USB_MAX_PACKET0] __attribute__ ((aligned (8)));
81 int cdc0_tx_index = 0, cdc0_tx_ready = 1;
82 int cdc0_tx_flush_required;
83 int cdc0_rx_index = 0, cdc0_rx_chars = 0;
84
85 uint16_t cdc0_serial_state = 0; /* USBCDC_SERIAL_STATE_xxx */
86 acm_desc_t usbcdc_acm_description;
87
88 int usb_active = 0;
89
90 #ifdef CONFIG_OC_CMDPROC
91
92 cmd_io_t cmd_io_usbcon_dev;
93
94 #define ED_LINE_CHARS 512
95
96 char ed_line_chars_usbcon_in[ED_LINE_CHARS + 1];
97 char ed_line_chars_usbcon_out[ED_LINE_CHARS + 1];
98
99 ed_line_buf_t ed_line_buf_usbcon_in =
100 {
101 flg:
102   FL_ELB_ECHO,
103   inbuf: 0,
104 alloc:
105   sizeof(ed_line_chars_usbcon_in),
106   maxlen: 0,
107   lastch: 0,
108 buf:
109   ed_line_chars_usbcon_in
110 };
111
112 ed_line_buf_t ed_line_buf_usbcon_out =
113 {
114 flg:
115   FL_ELB_NOCRLF,
116   inbuf: 0,
117 alloc:
118   sizeof(ed_line_chars_usbcon_out),
119   maxlen: 0,
120   lastch: 0,
121 buf:
122   ed_line_chars_usbcon_out
123 };
124
125 cmd_io_t cmd_io_usbcon =
126 {
127 putc:
128   cmd_io_line_putc,
129 getc:
130   NULL,
131 write:
132   cmd_io_write_bychar,
133 read:
134   NULL,
135 priv:
136   {
137   ed_line:
138     {
139     in:
140       &ed_line_buf_usbcon_in,
141     out:
142       &ed_line_buf_usbcon_out,
143     io_stack:
144       &cmd_io_usbcon_dev
145     }
146   }
147 };
148
149 #endif
150
151 static int usb_flash_pkt_wr(struct usb_ep_t *ep, int len, int code)
152 {
153   unsigned char *ptr = ep->ptr - len;
154
155 #ifdef CONFIG_KEYVAL
156   lpcisp_kvpb_copy(NULL, (void *)ep->user_data, ptr, len);
157 #endif /*CONFIG_KEYVAL*/
158
159   ep->user_data += len;
160   ep->ptr = ep0_buffer;
161   return USB_COMPLETE_OK;
162 }
163
164 static int usb_tumbl_pkt_wr(struct usb_ep_t *ep, int len, int code)
165 {
166   unsigned char *ptr = ep->ptr - len;
167
168   fpga_tumbl_write(ep->user_data, ptr, len);
169
170   ep->user_data += len;
171   ep->ptr = ep0_buffer;
172   return USB_COMPLETE_OK;
173 }
174
175 static int usb_32bit_pkt_wr(struct usb_ep_t *ep, int len, int code)
176 {
177   uint32_t *srcptr = (uint32_t *)(ep->ptr - len);
178   volatile uint32_t *dstptr = (uint32_t *)ep->user_data;
179   int pos;
180
181   for (pos = 0; len - pos >= 4; pos += 4, dstptr++, srcptr++)
182     *dstptr = *srcptr;
183
184   ep->user_data += len;
185   ep->ptr = ep0_buffer;
186   return USB_COMPLETE_OK;
187 }
188
189 int usb_32bit_pkt_rd(struct usb_ep_t *ep, int len, int code)
190 {
191   volatile uint32_t *srcptr;
192   uint32_t *dstptr;
193   int pos;
194
195   ep->ptr = ep0_buffer;
196   dstptr = (uint32_t *)ep->ptr;
197   srcptr = (uint32_t *)ep->user_data;
198
199   for (pos = 0; len - pos >= 4; pos += 4, dstptr++, srcptr++)
200     *dstptr = *srcptr;
201
202   ep->user_data += len;
203   return USB_COMPLETE_OK;
204 }
205
206 static int usb_flash_erase(unsigned addr, unsigned len)
207 {
208 #ifdef CONFIG_KEYVAL
209   lpcisp_erase((void *)addr, len);
210 #endif /*CONFIG_KEYVAL*/
211   return 0;
212 }
213
214 static int usb_spi_flash_pkt_wr(struct usb_ep_t *ep, int len, int code)
215 {
216   unsigned char *ptr = ep->ptr - len;
217
218 #ifdef CONFIG_OC_MTD_DRV_SYSLESS
219   mtd_spi_write(&mtd_spi_state, ptr, len, ep->user_data, 0);
220 #endif /*CONFIG_KEYVAL*/
221
222   ep->user_data += len;
223   ep->ptr = ep0_buffer;
224   return USB_COMPLETE_OK;
225 }
226
227 int usb_spi_flash_pkt_rd(struct usb_ep_t *ep, int len, int code)
228 {
229   ep->ptr = ep0_buffer;
230 #ifdef CONFIG_OC_MTD_DRV_SYSLESS
231   mtd_spi_read(&mtd_spi_state, ep->ptr, len, ep->user_data, 0);
232 #endif /*CONFIG_KEYVAL*/
233
234   ep->user_data += len;
235   return USB_COMPLETE_OK;
236 }
237
238 int usb_spi_flash_mass_erase(int mode)
239 {
240 #ifdef CONFIG_OC_MTD_DRV_SYSLESS
241   mtd_spi_set_protect_mode(&mtd_spi_state, 0, 0);
242   mtd_spi_chip_erase(&mtd_spi_state, mode, 0);
243 #endif /*CONFIG_KEYVAL*/
244   return 0;
245 }
246
247 static void usb_goto(unsigned address)
248 {
249 #ifdef CONFIG_KEYVAL
250   lpc_watchdog_init(1, 10);
251   lpc_watchdog_feed();
252
253   while (1)
254     {}
255
256 #endif /*CONFIG_KEYVAL*/
257 }
258
259 /* Not re-entrant */
260 uint16_t vendor_call_ret = 0xFFFF;
261
262 uint16_t appl_usb_vendor_call(uint16_t command, uint16_t argument)
263 {
264   int i, j;
265
266   switch (command)
267   {
268     case USB_CMD_FPGA_CONFIGURE:
269       return fpga_configure();
270
271     case USB_CMD_FPGA_MEASURE_READ:
272       return fpga_measure_bus_read();
273
274     case USB_CMD_FPGA_MEASURE_WRITE:
275       return fpga_measure_bus_write();
276
277     case USB_CMD_FPGA_IRC_GET_RESET:
278       printf("IRC RESET: 0x%02x\n", *fpga_irc_reset);
279       return 0;
280
281     case USB_CMD_FPGA_IRC_SET_RESET:
282       /* When starting, zero out counters */
283       *fpga_irc_reset = argument & 0x0001;
284       return 0;
285
286     case USB_CMD_FPGA_IRC_DUMP:
287       for (i = 0; i < 8; i++)
288         printf("IRC%d: count = %d, count index = %d, mark = %d, ab_error = %d, index_event = %d, index = %d\n", i+1,
289                (unsigned int) fpga_irc[i]->count, (unsigned int) fpga_irc[i]->count_index, ((*(fpga_irc_state[i])) & 0x01) != 0,
290                ((*(fpga_irc_state[i])) & 0x02) != 0, ((*(fpga_irc_state[i])) & 0x04) != 0, ((*(fpga_irc_state[i])) & 0x08) != 0);
291       return 0;
292
293     case USB_CMD_FPGA_LXMASTER_GET_RESET:
294       printf("LXMASTER RESET: 0x%02"PRIx32"\n", *fpga_lx_master_reset);
295       return 0;
296
297     case USB_CMD_FPGA_LXMASTER_SET_RESET:
298       /* When starting, zero out counters */
299       *fpga_lx_master_reset = argument & 0x0001;
300       return 0;
301
302     case USB_CMD_FPGA_LXMASTER_TRANSMITTER_GET_REG:
303       printf("LXMASTER TRANSMITTER REG: 0x%02"PRIx32"\n", *fpga_lx_master_transmitter_reg);
304       return 0;
305
306     case USB_CMD_FPGA_LXMASTER_TRANSMITTER_SET_REG:
307       /* When starting, zero out counters */
308       *fpga_lx_master_transmitter_reg = argument & 0x0001;
309       return 0;
310
311     case USB_CMD_FPGA_LXMASTER_TRANSMITTER_WRITE:
312       for (i = 0; i < (argument / 4); i++)
313         fpga_lx_master_transmitter_base[i] = fpga_lx_master_conf[i];
314       return 0;
315
316     case USB_CMD_FPGA_LXMASTER_TRANSMITTER_DUMP:
317       printf("LX MASTER TRANSMITTER MEM:\n");
318       for (i = 0; i < 16; i++)
319       {
320         for (j = 0; j < 16; j++)
321           printf("%04X ", (unsigned int) (fpga_lx_master_transmitter_base[i*16 + j] & 0xFFFF));
322
323         printf("\n");
324       }
325       return 0;
326
327     case USB_CMD_FPGA_TUMBL_SET_RESET:
328       return fpga_tumbl_set_reset(argument);
329
330     case USB_CMD_FPGA_TUMBL_SET_HALT:
331       return fpga_tumbl_set_halt(argument);
332
333     case USB_CMD_FPGA_TUMBL_SET_TRACE:
334       return fpga_tumbl_set_trace(argument);
335
336     case USB_CMD_FPGA_TUMBL_KICK_TRACE:
337       return fpga_tumbl_kick_trace();
338
339     case USB_CMD_FPGA_TUMBL_GET_PC:
340       printf("Tubml PC: 0x%08X\n", (unsigned int) *fpga_tumbl_pc);
341       return 0;
342
343     case USB_CMD_FPGA_TUMBL_DUMP_IMEM:
344       printf("TUMBL IMEM:\n");
345       for (i = 0; i < 64; i++)
346       {
347         for (j = 0; j < 8; j++)
348           printf("%08X ", (unsigned int) fpga_tumbl_imem[i*8 + j]);
349
350         printf("\n");
351       }
352       return 0;
353
354     case USB_CMD_FPGA_TUMBL_DUMP_DMEM:
355       printf("TUMBL DMEM:\n");
356       for (i = 0; i < 128; i++)
357       {
358         for (j = 0; j < 8; j++)
359           printf("%08X ", (unsigned int) fpga_tumbl_dmem[i*8 + j]);
360
361         printf("\n");
362       }
363       return 0;
364
365     case USB_CMD_FPGA_RESET:
366       hal_gpio_direction_output(XC_INIT_PIN, 0);
367
368       for (i = 0; i < 128; i++)
369         {}
370
371       hal_gpio_direction_output(XC_INIT_PIN, 1);
372       return 0;
373   }
374
375   return 0xFFFF;
376 }
377
378 int appl_usb_vendor(usb_device_t *udev)
379 {
380   unsigned long addr;
381   unsigned len;
382   USB_DEVICE_REQUEST *dreq;
383
384   usb_active = 1;
385   dreq = &udev->request;
386
387 #ifdef CONFIG_KEYVAL
388
389   if (dreq->bRequest != (USB_VENDOR_GET_SET_MEMORY |
390                          USB_DATA_DIR_FROM_HOST | USB_VENDOR_TARGET_FLASH))
391     lpcisp_kvpb_flush(NULL);
392
393 #endif /*CONFIG_KEYVAL*/
394
395   switch (dreq->bRequest & USB_VENDOR_MASK)
396   {
397     case USB_VENDOR_GET_CAPABILITIES:
398       ep0_buffer[0] = 0xAA; // test
399       usb_send_control_data(udev, ep0_buffer, 1);
400       return 1;
401
402     case USB_VENDOR_RESET_DEVICE:
403       usb_send_control_data(udev, NULL, 0);
404 #ifdef CONFIG_KEYVAL
405       lpc_watchdog_init(1, 10);
406       lpc_watchdog_feed();
407
408       while (1)
409         {}
410
411 #endif /*CONFIG_KEYVAL*/
412       return 1;
413
414     case USB_VENDOR_GOTO:
415       usb_send_control_data(udev, NULL, 0);
416       usb_goto(dreq->wValue);
417       return 1;
418
419     case USB_VENDOR_ERASE_MEMORY:
420       usb_send_control_data(udev, NULL, 0);
421       usb_flash_erase(dreq->wValue, dreq->wIndex);
422       return 1;
423
424     case USB_VENDOR_ERASE_1KB_MEMORY:  /* erase memory for 1 KB */
425       usb_send_control_data(udev, NULL, 0);
426       usb_flash_erase((uint32_t)dreq->wValue << 10, dreq->wIndex << 10);
427       return 1;
428
429     case USB_VENDOR_MASS_ERASE:
430       usb_send_control_data(udev, NULL, 0);
431       if (dreq->wIndex == 5)
432          usb_spi_flash_mass_erase(dreq->wValue);
433       return 1;
434
435     case USB_VENDOR_CALL:
436       vendor_call_ret = SWAP(appl_usb_vendor_call(dreq->wIndex, dreq->wValue));
437       usb_send_control_data(udev, (unsigned char *) &vendor_call_ret, sizeof(uint16_t));
438       return 1;
439
440     case USB_VENDOR_GET_SET_MEMORY:
441       addr = (dreq->wValue & 0xffff) | (((unsigned long)dreq->wIndex & 0xffff) << 16);
442       len = dreq->wLength;
443
444       if ((dreq->bmRequestType & USB_DATA_DIR_MASK) == USB_DATA_DIR_FROM_HOST)
445       {
446         switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
447         {
448           case USB_VENDOR_TARGET_RAM:
449             udev->ep0.ptr = (void *)addr;
450             break;
451
452           case USB_VENDOR_TARGET_FLASH:
453             udev->ep0.next_pkt_fnc = usb_flash_pkt_wr;
454             udev->ep0.user_data = addr;
455             udev->ep0.ptr = ep0_buffer;
456             break;
457
458           case USB_VENDOR_TARGET_TUMBL:
459             udev->ep0.next_pkt_fnc = usb_tumbl_pkt_wr;
460             udev->ep0.user_data = addr;
461             udev->ep0.ptr = ep0_buffer;
462             break;
463
464           case USB_VENDOR_TARGET_32BIT:
465             udev->ep0.next_pkt_fnc = usb_32bit_pkt_wr;
466             udev->ep0.user_data = addr;
467             udev->ep0.ptr = ep0_buffer;
468             break;
469
470           case USB_VENDOR_TARGET_SPI_FLASH:
471             udev->ep0.next_pkt_fnc = usb_spi_flash_pkt_wr;
472             udev->ep0.user_data = addr;
473             udev->ep0.ptr = ep0_buffer;
474             break;
475
476           default:
477             return -1;
478         }
479
480         if (len)
481           usb_set_control_endfnc(udev, usb_ack_setup);
482         else
483           usb_send_control_data(udev, NULL, 0);
484
485         return 1;
486       }
487       else
488       {
489         switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
490         {
491           case USB_VENDOR_TARGET_RAM:
492             usb_send_control_data(udev, (void *)addr, len);
493             break;
494
495           case USB_VENDOR_TARGET_32BIT:
496             udev->ep0.next_pkt_fnc = usb_32bit_pkt_rd;
497             udev->ep0.user_data=addr;
498             usb_send_control_data( udev, ep0_buffer, len);
499             break;
500
501           case USB_VENDOR_TARGET_SPI_FLASH:
502             udev->ep0.next_pkt_fnc = usb_spi_flash_pkt_rd;
503             udev->ep0.user_data=addr;
504             usb_send_control_data( udev, ep0_buffer, len);
505             break;
506
507           default:
508             return -1;
509         }
510
511         return 1;
512       }
513
514       break;
515   }
516
517   return 0;
518 }
519
520 int usb_app_fill_serial_number(uint32_t ul_sn)
521 {
522   char *p = usb_devdes_serial_number;
523   int len_max = sizeof(usb_devdes_serial_number);
524   char c;
525
526   while ((len_max -= 2) >= 2)
527   {
528     p += 2;
529     c = ((ul_sn >> (32 - 4)) & 0xf) + '0';
530     ul_sn <<= 4;
531
532     if (c > '9')
533       c += 'A' - '9' - 1;
534
535     *p = c;
536   }
537
538   return 0;
539 }
540
541 static inline
542 int usb_app_epnum2event_mask(int epnum)
543 {
544   int evmask;
545   int evbit;
546   /* LPC17xx EP1RX 0x04, EP1TX 0x08, EP2RX 0x10, EP2TX 0x20 */
547
548   evbit = (epnum & ~USB_ENDPOINT_DIRECTION_MASK) * 2;
549   if (epnum & USB_ENDPOINT_DIRECTION_MASK)
550     evbit++;
551
552   evmask = 1 << evbit;
553
554   return evmask;
555 }
556
557 int usb_app_init(void)
558 {
559   memset(&usb_device, 0, sizeof(usb_device));
560
561   eps[CDC0_EPIDX_NOTIFY].max_packet_size = USB_MAX_PACKET;
562   eps[CDC0_EPIDX_RXD].max_packet_size = CDC0_MAX_PACKET;
563   eps[CDC0_EPIDX_TXD].max_packet_size = CDC0_MAX_PACKET;
564   eps[CDC0_EPIDX_NOTIFY].epnum = CDC0_EP_NOTIFY;
565   eps[CDC0_EPIDX_RXD].epnum = CDC0_EP_RXD;
566   eps[CDC0_EPIDX_TXD].epnum = CDC0_EP_TXD;
567   eps[CDC0_EPIDX_NOTIFY].event_mask = usb_app_epnum2event_mask(CDC0_EP_NOTIFY); /* 0x08; */
568   eps[CDC0_EPIDX_RXD].event_mask = usb_app_epnum2event_mask(CDC0_EP_RXD); /* 0x10; */
569   eps[CDC0_EPIDX_TXD].event_mask = usb_app_epnum2event_mask(CDC0_EP_TXD); /* 0x20; */
570   eps[CDC0_EPIDX_NOTIFY].udev = &usb_device;
571   eps[CDC0_EPIDX_RXD].udev = &usb_device;
572   eps[CDC0_EPIDX_TXD].udev = &usb_device;
573
574   usb_device.id = 1;
575   usb_device.devdes_table = &usb_devdes_table;
576   usb_device.init = usb_lpc_init;
577   usb_debug_set_level(DEBUG_LEVEL_NONE);
578   usb_device.cntep = NUM_ENDPOINTS;
579   usb_device.ep = eps;
580   usb_device.vendor_fnc = appl_usb_vendor;
581   usb_device.class_fnc = usbcdc_acm_class_response;
582
583   usb_init(&usb_device);
584   usb_connect(&usb_device);
585
586   return 0;
587 }
588
589 int cdc0_txd_check_ep(void)
590 {
591   if (usb_device.ep_events & CDC0_MASK_EP_TXD)
592   {
593     usb_device.ep_events &= ~CDC0_MASK_EP_TXD;
594     //TODO: Use some field in the structure, probably flags
595     cdc0_tx_ready = 1;
596   }
597
598   /* Respond if there is something to send and RX is ready */
599   if (cdc0_tx_ready && ((cdc0_tx_index != 0) || cdc0_tx_flush_required))
600   {
601     usb_udev_write_endpoint(&eps[CDC0_EPIDX_TXD], cdc0_ep_tx_buff, cdc0_tx_index);
602     cdc0_tx_flush_required = (cdc0_tx_index == CDC0_MAX_PACKET);
603     cdc0_tx_index = 0;
604     cdc0_tx_ready = 0;
605     hal_gpio_set_value(LED2_PIN, 0);
606     return 1;
607   }
608
609   return 0;
610 }
611
612 int usb_app_poll(void)
613 {
614   int active = usb_active;
615   usb_active = 0;
616
617   usb_check_events(&usb_device);
618   usb_control_response(&usb_device);
619
620   /* Check RXD/OUT endpoint */
621   if (usb_device.ep_events & CDC0_MASK_EP_NOTIFY)
622   {
623     usb_udev_read_endpoint(&eps[CDC0_EPIDX_NOTIFY], &cdc0_serial_state, 2);
624     usb_device.ep_events &= ~CDC0_MASK_EP_NOTIFY;
625     usb_active = 1;
626   }
627
628   /* Check RXD/OUT endpoint */
629   if (usb_device.ep_events & CDC0_MASK_EP_RXD)
630   {
631     cdc0_rx_chars = usb_udev_read_endpoint(&eps[CDC0_EPIDX_RXD], cdc0_ep_rx_buff, CDC0_MAX_PACKET);
632     cdc0_rx_index = 0;
633     usb_device.ep_events &= ~CDC0_MASK_EP_RXD;
634     hal_gpio_set_value(LED2_PIN, 0);
635     usb_active = 1;
636   }
637
638   /* Check RX endpoint */
639   usb_active |= cdc0_txd_check_ep();
640
641   return active;
642 }
643
644 int usb_app_stop(void)
645 {
646   usb_disconnect(&usb_device);
647   return 0;
648 }
649
650 #ifdef CONFIG_OC_CMDPROC
651
652 int cmd_io_getc_usbcon(struct cmd_io *cmd_io)
653 {
654   if (cdc0_rx_index >= cdc0_rx_chars)
655     return -1;
656
657   return cdc0_ep_rx_buff[cdc0_rx_index++];
658 }
659
660 int cmd_io_putc_usbcon(struct cmd_io *cmd_io, int ch)
661 {
662   if (cdc0_tx_index >= CDC0_MAX_PACKET)
663   {
664     /* Check EP1 status and return -1 if unavailable */
665     usb_check_events(&usb_device);
666     cdc0_txd_check_ep();
667
668     /* Check again if it wasn't emptied */
669     if (cdc0_tx_index >= CDC0_MAX_PACKET)
670       return -1;
671   }
672
673   cdc0_ep_tx_buff[cdc0_tx_index++] = (unsigned char)ch;
674   return ch;
675 }
676
677 cmd_io_t cmd_io_usbcon_dev =
678 {
679   .putc = cmd_io_putc_usbcon,
680   .getc = cmd_io_getc_usbcon,
681   .write = cmd_io_write_bychar,
682   .read = cmd_io_read_bychar,
683   .priv.uart = { -1 }
684 };
685
686 #endif