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