]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-dad.git/blob - sw/app/lx_dad/appl_usb.c
fe970993000c1275b38ad1559fbcc8634abb7aa4
[fpga/lx-cpu1/lx-dad.git] / sw / app / lx_dad / appl_usb.c
1 #include <stdint.h>
2 #include <inttypes.h>
3 #include <cpu_def.h>
4 #include <system_def.h>
5 #include <string.h>
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <endian.h>
9 #include <usb/lpc.h>
10 #include <usb/usb.h>
11 #include <usb/usb_loader.h>
12 #include <usb/usbdebug.h>
13 #include <cmd_proc.h>
14 #include <hal_gpio.h>
15
16 #include "appl_defs.h"
17 #include "usb/usb_defs.h"
18
19 #ifdef APPL_WITH_FPGA
20 #include "appl_fpga.h"
21 #endif /*APPL_WITH_FPGA*/
22
23 #ifdef CONFIG_KEYVAL
24 #include <keyvalpb.h>
25 #include <lpciap.h>
26 #include <lpciap_kvpb.h>
27 #include <hal_machperiph.h>
28 #endif /*CONFIG_KEYVAL*/
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_32BIT                   0x04
39
40 #define USB_CMD_FPGA_CONFIGURE                    0xF000
41 #define USB_CMD_FPGA_MEASURE_READ                 0xF001
42 #define USB_CMD_FPGA_MEASURE_WRITE                0xF002
43
44 #define USB_CMD_FPGA_RESET                        0xFFFF
45
46 usb_device_t usb_device;
47 usb_ep_t eps[NUM_ENDPOINTS];
48
49 #define CDC0_EPIDX_NOTIFY 0
50 #define CDC0_EPIDX_RXD    1
51 #define CDC0_EPIDX_TXD    2
52 #define CDC0_MASK_EP_NOTIFY  (1<<CDC0_EPIDX_NOTIFY)
53 #define CDC0_MASK_EP_RXD     (1<<CDC0_EPIDX_RXD)
54 #define CDC0_MASK_EP_TXD     (1<<CDC0_EPIDX_TXD)
55
56 unsigned char cdc0_ep_tx_buff[USB_MAX_PACKET] __attribute__ ((aligned (8)));
57 unsigned char cdc0_ep_rx_buff[USB_MAX_PACKET] __attribute__ ((aligned (8)));
58 unsigned char ep0_buffer[USB_MAX_PACKET0] __attribute__ ((aligned (8)));
59 int cdc0_tx_index = 0, cdc0_tx_ready = 1;
60 int cdc0_tx_flush_required;
61 int cdc0_rx_index = 0, cdc0_rx_chars = 0;
62
63 uint16_t cdc0_serial_state = 0; /* USBCDC_SERIAL_STATE_xxx */
64 acm_desc_t usbcdc_acm_description;
65
66 int usb_active = 0;
67
68 #ifdef CONFIG_OC_CMDPROC
69
70 cmd_io_t cmd_io_usbcon_dev;
71
72 #define ED_LINE_CHARS 512
73
74 char ed_line_chars_usbcon_in[ED_LINE_CHARS + 1];
75 char ed_line_chars_usbcon_out[ED_LINE_CHARS + 1];
76
77 ed_line_buf_t ed_line_buf_usbcon_in =
78 {
79 flg:
80   FL_ELB_ECHO,
81   inbuf: 0,
82 alloc:
83   sizeof(ed_line_chars_usbcon_in),
84   maxlen: 0,
85   lastch: 0,
86 buf:
87   ed_line_chars_usbcon_in
88 };
89
90 ed_line_buf_t ed_line_buf_usbcon_out =
91 {
92 flg:
93   FL_ELB_NOCRLF,
94   inbuf: 0,
95 alloc:
96   sizeof(ed_line_chars_usbcon_out),
97   maxlen: 0,
98   lastch: 0,
99 buf:
100   ed_line_chars_usbcon_out
101 };
102
103 cmd_io_t cmd_io_usbcon =
104 {
105 putc:
106   cmd_io_line_putc,
107 getc:
108   NULL,
109 write:
110   cmd_io_write_bychar,
111 read:
112   NULL,
113 priv:
114   {
115   ed_line:
116     {
117     in:
118       &ed_line_buf_usbcon_in,
119     out:
120       &ed_line_buf_usbcon_out,
121     io_stack:
122       &cmd_io_usbcon_dev
123     }
124   }
125 };
126
127 #endif
128
129 static int usb_flash_pkt_wr(struct usb_ep_t *ep, int len, int code)
130 {
131   unsigned char *ptr = ep->ptr - len;
132
133 #ifdef CONFIG_KEYVAL
134   lpcisp_kvpb_copy(NULL, (void *)ep->user_data, ptr, len);
135 #endif /*CONFIG_KEYVAL*/
136
137   ep->user_data += len;
138   ep->ptr = ep0_buffer;
139   return USB_COMPLETE_OK;
140 }
141
142 static int usb_32bit_pkt_wr(struct usb_ep_t *ep, int len, int code)
143 {
144   uint32_t *srcptr = (uint32_t *)(ep->ptr - len);
145   volatile uint32_t *dstptr = (uint32_t *)ep->user_data;
146   int pos;
147
148   for (pos = 0; len - pos >= 4; pos += 4, dstptr++, srcptr++)
149     *dstptr = *srcptr;
150
151   ep->user_data += len;
152   ep->ptr = ep0_buffer;
153   return USB_COMPLETE_OK;
154 }
155
156 int usb_32bit_pkt_rd(struct usb_ep_t *ep, int len, int code)
157 {
158   volatile uint32_t *srcptr;
159   uint32_t *dstptr;
160   int pos;
161
162   ep->ptr = ep0_buffer;
163   dstptr = (uint32_t *)ep->ptr;
164   srcptr = (uint32_t *)ep->user_data;
165
166   for (pos = 0; len - pos >= 4; pos += 4, dstptr++, srcptr++)
167     *dstptr = *srcptr;
168
169   ep->user_data += len;
170   return USB_COMPLETE_OK;
171 }
172
173 static int usb_flash_erase(unsigned addr, unsigned len)
174 {
175 #ifdef CONFIG_KEYVAL
176   lpcisp_erase((void *)addr, len);
177 #endif /*CONFIG_KEYVAL*/
178   return 0;
179 }
180
181 static void usb_goto(unsigned address)
182 {
183 #ifdef CONFIG_KEYVAL
184   lpc_watchdog_init(1, 10);
185   lpc_watchdog_feed();
186
187   while (1)
188     {}
189
190 #endif /*CONFIG_KEYVAL*/
191 }
192
193 /* Not re-entrant */
194 uint16_t vendor_call_ret = 0xFFFF;
195
196 uint16_t appl_usb_vendor_call(uint16_t command, uint16_t argument)
197 {
198   int i;
199
200   switch (command)
201   {
202    #ifdef APPL_WITH_FPGA
203     case USB_CMD_FPGA_CONFIGURE:
204       return fpga_configure();
205
206     case USB_CMD_FPGA_MEASURE_READ:
207       return fpga_measure_bus_read();
208
209     case USB_CMD_FPGA_MEASURE_WRITE:
210       return fpga_measure_bus_write();
211
212     case USB_CMD_FPGA_RESET:
213       hal_gpio_direction_output(XC_INIT_PIN, 0);
214
215       for (i = 0; i < 128; i++)
216         {}
217
218       hal_gpio_direction_output(XC_INIT_PIN, 1);
219    #endif /*APPL_WITH_FPGA*/
220       return 0;
221   }
222
223   return 0xFFFF;
224 }
225
226 int appl_usb_vendor(usb_device_t *udev)
227 {
228   unsigned long addr;
229   unsigned len;
230   USB_DEVICE_REQUEST *dreq;
231
232   usb_active = 1;
233   dreq = &udev->request;
234
235 #ifdef CONFIG_KEYVAL
236
237   if (dreq->bRequest != (USB_VENDOR_GET_SET_MEMORY |
238                          USB_DATA_DIR_FROM_HOST | USB_VENDOR_TARGET_FLASH))
239     lpcisp_kvpb_flush(NULL);
240
241 #endif /*CONFIG_KEYVAL*/
242
243   switch (dreq->bRequest & USB_VENDOR_MASK)
244   {
245     case USB_VENDOR_GET_CAPABILITIES:
246       ep0_buffer[0] = 0xAA; // test
247       usb_send_control_data(udev, ep0_buffer, 1);
248       return 1;
249
250     case USB_VENDOR_RESET_DEVICE:
251       usb_send_control_data(udev, NULL, 0);
252 #ifdef CONFIG_KEYVAL
253       lpc_watchdog_init(1, 10);
254       lpc_watchdog_feed();
255
256       while (1)
257         {}
258
259 #endif /*CONFIG_KEYVAL*/
260       return 1;
261
262     case USB_VENDOR_GOTO:
263       usb_send_control_data(udev, NULL, 0);
264       usb_goto(dreq->wValue);
265       return 1;
266
267     case USB_VENDOR_ERASE_MEMORY:
268       usb_send_control_data(udev, NULL, 0);
269       usb_flash_erase(dreq->wValue, dreq->wIndex);
270       return 1;
271
272     case USB_VENDOR_ERASE_1KB_MEMORY:  /* erase memory for 1 KB */
273       usb_send_control_data(udev, NULL, 0);
274       usb_flash_erase((uint32_t)dreq->wValue << 10, dreq->wIndex << 10);
275       return 1;
276
277     case USB_VENDOR_CALL:
278       vendor_call_ret = SWAP(appl_usb_vendor_call(dreq->wIndex, dreq->wValue));
279       usb_send_control_data(udev, (unsigned char *) &vendor_call_ret, sizeof(uint16_t));
280       return 1;
281
282     case USB_VENDOR_GET_SET_MEMORY:
283       addr = (dreq->wValue & 0xffff) | (((unsigned long)dreq->wIndex & 0xffff) << 16);
284       len = dreq->wLength;
285
286       if ((dreq->bmRequestType & USB_DATA_DIR_MASK) == USB_DATA_DIR_FROM_HOST)
287       {
288         switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
289         {
290           case USB_VENDOR_TARGET_RAM:
291             udev->ep0.ptr = (void *)addr;
292             break;
293
294           case USB_VENDOR_TARGET_FLASH:
295             udev->ep0.next_pkt_fnc = usb_flash_pkt_wr;
296             udev->ep0.user_data = addr;
297             udev->ep0.ptr = ep0_buffer;
298             break;
299
300           case USB_VENDOR_TARGET_32BIT:
301             udev->ep0.next_pkt_fnc = usb_32bit_pkt_wr;
302             udev->ep0.user_data = addr;
303             udev->ep0.ptr = ep0_buffer;
304             break;
305
306           default:
307             return -1;
308         }
309
310         if (len)
311           usb_set_control_endfnc(udev, usb_ack_setup);
312         else
313           usb_send_control_data(udev, NULL, 0);
314
315         return 1;
316       }
317       else
318       {
319         switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
320         {
321           case USB_VENDOR_TARGET_RAM:
322             usb_send_control_data(udev, (void *)addr, len);
323             break;
324
325           case USB_VENDOR_TARGET_32BIT:
326             udev->ep0.next_pkt_fnc = usb_32bit_pkt_rd;
327             udev->ep0.user_data=addr;
328             usb_send_control_data( udev, ep0_buffer, len);
329             break;
330
331           default:
332             return -1;
333         }
334
335         return 1;
336       }
337
338       break;
339   }
340
341   return 0;
342 }
343
344 int usb_app_fill_serial_number(uint32_t ul_sn)
345 {
346   char *p = usb_devdes_serial_number;
347   int len_max = sizeof(usb_devdes_serial_number);
348   char c;
349
350   while ((len_max -= 2) >= 2)
351   {
352     p += 2;
353     c = ((ul_sn >> (32 - 4)) & 0xf) + '0';
354     ul_sn <<= 4;
355
356     if (c > '9')
357       c += 'A' - '9' - 1;
358
359     *p = c;
360   }
361
362   return 0;
363 }
364
365 int usb_app_init(void)
366 {
367   memset(&usb_device, 0, sizeof(usb_device));
368
369   eps[CDC0_EPIDX_NOTIFY].max_packet_size = USB_MAX_PACKET;
370   eps[CDC0_EPIDX_RXD].max_packet_size = USB_MAX_PACKET;
371   eps[CDC0_EPIDX_TXD].max_packet_size = USB_MAX_PACKET;
372   eps[CDC0_EPIDX_NOTIFY].epnum = CDC0_EP_NOTIFY;
373   eps[CDC0_EPIDX_RXD].epnum = CDC0_EP_RXD;
374   eps[CDC0_EPIDX_TXD].epnum = CDC0_EP_TXD;
375   eps[CDC0_EPIDX_NOTIFY].event_mask = 0x08;
376   eps[CDC0_EPIDX_RXD].event_mask = 0x10;
377   eps[CDC0_EPIDX_TXD].event_mask = 0x20;
378   eps[CDC0_EPIDX_NOTIFY].udev = &usb_device;
379   eps[CDC0_EPIDX_RXD].udev = &usb_device;
380   eps[CDC0_EPIDX_TXD].udev = &usb_device;
381
382   usb_device.id = 1;
383   usb_device.devdes_table = &usb_devdes_table;
384   usb_device.init = usb_lpc_init;
385   usb_debug_set_level(DEBUG_LEVEL_NONE);
386   usb_device.cntep = NUM_ENDPOINTS;
387   usb_device.ep = eps;
388   usb_device.vendor_fnc = appl_usb_vendor;
389   usb_device.class_fnc = usbcdc_acm_class_response;
390
391   usb_init(&usb_device);
392   usb_connect(&usb_device);
393
394   return 0;
395 }
396
397 int cdc0_txd_check_ep(void)
398 {
399   if (usb_device.ep_events & CDC0_MASK_EP_TXD)
400   {
401     usb_device.ep_events &= ~CDC0_MASK_EP_TXD;
402     //TODO: Use some field in the structure, probably flags
403     cdc0_tx_ready = 1;
404   }
405
406   /* Respond if there is something to send and RX is ready */
407   if (cdc0_tx_ready && ((cdc0_tx_index != 0) || cdc0_tx_flush_required))
408   {
409     usb_udev_write_endpoint(&eps[CDC0_EPIDX_TXD], cdc0_ep_tx_buff, cdc0_tx_index);
410     cdc0_tx_flush_required = (cdc0_tx_index == USB_MAX_PACKET);
411     cdc0_tx_index = 0;
412     cdc0_tx_ready = 0;
413     hal_gpio_set_value(LED2_PIN, 0);
414     return 1;
415   }
416
417   return 0;
418 }
419
420 int usb_app_poll(void)
421 {
422   int active = usb_active;
423   usb_active = 0;
424
425   usb_check_events(&usb_device);
426   usb_control_response(&usb_device);
427
428   /* Check RXD/OUT endpoint */
429   if (usb_device.ep_events & CDC0_MASK_EP_NOTIFY)
430   {
431     usb_udev_read_endpoint(&eps[CDC0_EPIDX_NOTIFY], &cdc0_serial_state, 2);
432     usb_device.ep_events &= ~CDC0_MASK_EP_NOTIFY;
433     usb_active = 1;
434   }
435
436   /* Check RXD/OUT endpoint */
437   if (usb_device.ep_events & CDC0_MASK_EP_RXD)
438   {
439     cdc0_rx_chars = usb_udev_read_endpoint(&eps[CDC0_EPIDX_RXD], cdc0_ep_rx_buff, USB_MAX_PACKET);
440     cdc0_rx_index = 0;
441     usb_device.ep_events &= ~CDC0_MASK_EP_RXD;
442     hal_gpio_set_value(LED2_PIN, 0);
443     usb_active = 1;
444   }
445
446   /* Check RX endpoint */
447   usb_active |= cdc0_txd_check_ep();
448
449   return active;
450 }
451
452 int usb_app_stop(void)
453 {
454   usb_disconnect(&usb_device);
455   return 0;
456 }
457
458 #ifdef CONFIG_OC_CMDPROC
459
460 int cmd_io_getc_usbcon(struct cmd_io *cmd_io)
461 {
462   if (cdc0_rx_index >= cdc0_rx_chars)
463     return -1;
464
465   return cdc0_ep_rx_buff[cdc0_rx_index++];
466 }
467
468 int cmd_io_putc_usbcon(struct cmd_io *cmd_io, int ch)
469 {
470   if (cdc0_tx_index >= USB_MAX_PACKET)
471   {
472     /* Check EP1 status and return -1 if unavailable */
473     usb_check_events(&usb_device);
474     cdc0_txd_check_ep();
475
476     /* Check again if it wasn't emptied */
477     if (cdc0_tx_index >= USB_MAX_PACKET)
478       return -1;
479   }
480
481   cdc0_ep_tx_buff[cdc0_tx_index++] = (unsigned char)ch;
482   return ch;
483 }
484
485 cmd_io_t cmd_io_usbcon_dev =
486 {
487   .putc = cmd_io_putc_usbcon,
488   .getc = cmd_io_getc_usbcon,
489   .write = cmd_io_write_bychar,
490   .read = cmd_io_read_bychar,
491   .priv.uart = { -1 }
492 };
493
494 #endif