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