ede7f251bd5baa41ce1d5b7e7b8a61a96343129b
[gnuk/neug.git] / src / main.c
1 /*
2  * main.c - main routine of neug
3  *
4  * Main routine:
5  * Copyright (C) 2011, 2012, 2013, 2015, 2016
6  *               Free Software Initiative of Japan
7  * Author: NIIBE Yutaka <gniibe@fsij.org>
8  *
9  * This file is a part of NeuG, a True Random Number Generator
10  * implementation.
11  *
12  * NeuG is free software: you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * NeuG is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26
27
28 #include <stdint.h>
29 #include <string.h>
30 #include <chopstx.h>
31
32 #include "config.h"
33 #include "neug.h"
34 #include "usb_lld.h"
35 #include "sys.h"
36 #include "mcu/stm32f103.h"
37 #include "adc.h"
38
39 enum {
40   FSIJ_DEVICE_RUNNING = 0,
41   FSIJ_DEVICE_EXITED,
42   FSIJ_DEVICE_EXEC_REQUESTED,
43   /**/
44   FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED = 254,
45   FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
46 };
47
48 #ifdef FRAUCHEKY_SUPPORT
49 static uint8_t running_neug;
50 extern void EP6_IN_Callback (uint16_t len);
51 extern void EP6_OUT_Callback (uint16_t len);
52 #endif
53
54 static chopstx_mutex_t usb_mtx;
55 static chopstx_cond_t usb_cnd;
56 static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
57 static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
58 static uint8_t connected;
59
60
61 #define ENDP0_RXADDR        (0x40)
62 #define ENDP0_TXADDR        (0x80)
63 #define ENDP1_TXADDR        (0xc0)
64 #define ENDP2_TXADDR        (0x100)
65 #define ENDP3_RXADDR        (0x140)
66
67 #define USB_CDC_REQ_SET_LINE_CODING             0x20
68 #define USB_CDC_REQ_GET_LINE_CODING             0x21
69 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE      0x22
70 #define USB_CDC_REQ_SEND_BREAK                  0x23
71
72 /* USB Device Descriptor */
73 static const uint8_t vcom_device_desc[18] = {
74   18,   /* bLength */
75   DEVICE_DESCRIPTOR,            /* bDescriptorType */
76   0x10, 0x01,                   /* bcdUSB = 1.1 */
77   0x02,                         /* bDeviceClass (CDC).              */
78   0x00,                         /* bDeviceSubClass.                 */
79   0x00,                         /* bDeviceProtocol.                 */
80   0x40,                         /* bMaxPacketSize.                  */
81 #include "usb-vid-pid-ver.c.inc"
82   1,                            /* iManufacturer.                   */
83   2,                            /* iProduct.                        */
84   3,                            /* iSerialNumber.                   */
85   1                             /* bNumConfigurations.              */
86 };
87
88 #define VCOM_FEATURE_BUS_POWERED        0x80
89
90 /* Configuration Descriptor tree for a CDC.*/
91 static const uint8_t vcom_config_desc[67] = {
92   9,
93   CONFIG_DESCRIPTOR,            /* bDescriptorType: Configuration   */
94   /* Configuration Descriptor.*/
95   67, 0x00,                     /* wTotalLength.                    */
96   0x02,                         /* bNumInterfaces.                  */
97   0x01,                         /* bConfigurationValue.             */
98   0,                            /* iConfiguration.                  */
99   VCOM_FEATURE_BUS_POWERED,     /* bmAttributes.                    */
100   50,                           /* bMaxPower (100mA).               */
101   /* Interface Descriptor.*/
102   9,
103   INTERFACE_DESCRIPTOR,
104   0x00,            /* bInterfaceNumber.                */
105   0x00,            /* bAlternateSetting.               */
106   0x01,            /* bNumEndpoints.                   */
107   0x02,            /* bInterfaceClass (Communications Interface Class,
108                       CDC section 4.2).  */
109   0x02,            /* bInterfaceSubClass (Abstract Control Model, CDC
110                       section 4.3).  */
111   0x01,            /* bInterfaceProtocol (AT commands, CDC section
112                       4.4).  */
113   0,               /* iInterface.                      */
114   /* Header Functional Descriptor (CDC section 5.2.3).*/
115   5,          /* bLength.                         */
116   0x24,       /* bDescriptorType (CS_INTERFACE).  */
117   0x00,       /* bDescriptorSubtype (Header Functional Descriptor). */
118   0x10, 0x01, /* bcdCDC.                          */
119   /* Call Management Functional Descriptor. */
120   5,            /* bFunctionLength.                 */
121   0x24,         /* bDescriptorType (CS_INTERFACE).  */
122   0x01,         /* bDescriptorSubtype (Call Management Functional
123                    Descriptor). */
124   0x03,         /* bmCapabilities (D0+D1).          */
125   0x01,         /* bDataInterface.                  */
126   /* ACM Functional Descriptor.*/
127   4,            /* bFunctionLength.                 */
128   0x24,         /* bDescriptorType (CS_INTERFACE).  */
129   0x02,         /* bDescriptorSubtype (Abstract Control Management
130                    Descriptor).  */
131   0x02,         /* bmCapabilities.                  */
132   /* Union Functional Descriptor.*/
133   5,            /* bFunctionLength.                 */
134   0x24,         /* bDescriptorType (CS_INTERFACE).  */
135   0x06,         /* bDescriptorSubtype (Union Functional
136                    Descriptor).  */
137   0x00,         /* bMasterInterface (Communication Class
138                    Interface).  */
139   0x01,         /* bSlaveInterface0 (Data Class Interface).  */
140   /* Endpoint 2 Descriptor.*/
141   7,
142   ENDPOINT_DESCRIPTOR,
143   ENDP2|0x80,    /* bEndpointAddress.    */
144   0x03,          /* bmAttributes (Interrupt).        */
145   0x08, 0x00,    /* wMaxPacketSize.                  */
146   0xFF,          /* bInterval.                       */
147   /* Interface Descriptor.*/
148   9,
149   INTERFACE_DESCRIPTOR,          /* bDescriptorType: */
150   0x01,          /* bInterfaceNumber.                */
151   0x00,          /* bAlternateSetting.               */
152   0x02,          /* bNumEndpoints.                   */
153   0x0A,          /* bInterfaceClass (Data Class Interface, CDC section 4.5). */
154   0x00,          /* bInterfaceSubClass (CDC section 4.6). */
155   0x00,          /* bInterfaceProtocol (CDC section 4.7). */
156   0x00,          /* iInterface.                      */
157   /* Endpoint 3 Descriptor.*/
158   7,
159   ENDPOINT_DESCRIPTOR,          /* bDescriptorType: Endpoint */
160   ENDP3,    /* bEndpointAddress. */
161   0x02,                         /* bmAttributes (Bulk).             */
162   0x40, 0x00,                   /* wMaxPacketSize.                  */
163   0x00,                         /* bInterval.                       */
164   /* Endpoint 1 Descriptor.*/
165   7,
166   ENDPOINT_DESCRIPTOR,          /* bDescriptorType: Endpoint */
167   ENDP1|0x80,                   /* bEndpointAddress. */
168   0x02,                         /* bmAttributes (Bulk).             */
169   0x40, 0x00,                   /* wMaxPacketSize.                  */
170   0x00                          /* bInterval.                       */
171 };
172
173
174 /*
175  * U.S. English language identifier.
176  */
177 static const uint8_t vcom_string0[4] = {
178   4,                            /* bLength */
179   STRING_DESCRIPTOR,
180   0x09, 0x04                    /* LangID = 0x0409: US-English */
181 };
182
183 #include "usb-strings.c.inc"
184
185 static void neug_setup_endpoints_for_interface (uint16_t interface, int stop);
186 #ifdef FRAUCHEKY_SUPPORT
187 #define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
188 extern int fraucheky_enabled (void);
189 extern void fraucheky_main (void);
190
191 extern void fraucheky_setup_endpoints_for_interface (int stop);
192 extern int fraucheky_setup (struct usb_dev *dev);
193 extern int fraucheky_get_descriptor (struct usb_dev *dev);
194 #endif
195
196 #define NUM_INTERFACES 2
197
198 static void
199 usb_device_reset (struct usb_dev *dev)
200 {
201   int i;
202
203   usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
204
205   /* Initialize Endpoint 0.  */
206   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
207
208   /* Stop the interface */
209   for (i = 0; i < NUM_INTERFACES; i++)
210     neug_setup_endpoints_for_interface (i, 1);
211
212   /* Notify upper layer.  */
213   chopstx_mutex_lock (&usb_mtx);
214   bDeviceState = ATTACHED;
215   connected = 0;
216   chopstx_cond_signal (&usb_cnd);
217   chopstx_mutex_unlock (&usb_mtx);
218 }
219
220 extern uint8_t _regnual_start, __heap_end__;
221
222 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
223
224 /* USB vendor requests to control pipe */
225 #define USB_FSIJ_MEMINFO          0
226 #define USB_FSIJ_DOWNLOAD         1
227 #define USB_FSIJ_EXEC             2
228 #define USB_NEUG_SET_PASSWD     253
229 #define USB_NEUG_GET_INFO       254
230 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
231
232 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
233   0xff,
234   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
235   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
236   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
237 };
238 static uint8_t usbbuf[64];
239
240 #define DEFAULT_PASSWD "12345678"
241 #define DEFAULT_PASSWD_LEN 8
242
243 static void set_passwd (void)
244 {
245   flash_unlock ();
246   if (neug_passwd[0] != 0xff)
247     flash_erase_page ((uint32_t)neug_passwd);
248   if (usbbuf[0] == DEFAULT_PASSWD_LEN
249       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
250     return;
251   flash_write ((uint32_t)neug_passwd, usbbuf, usbbuf[0] + 1);
252 }
253
254 static uint32_t rbit (uint32_t v)
255 {
256   uint32_t r;
257
258   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
259   return r;
260 }
261
262 /* After calling this function, CRC module remain enabled.  */
263 static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
264 {
265   uint32_t crc32 = *end_p;
266   const uint32_t *p;
267
268   RCC->AHBENR |= RCC_AHBENR_CRCEN;
269   CRC->CR = CRC_CR_RESET;
270
271   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
272     CRC->DR = rbit (*p);
273
274   if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
275     return usb_lld_ctrl_ack (dev);
276
277   return -1;
278 }
279
280
281 #define NEUG_SPECIAL_BITRATE 110
282
283 struct line_coding
284 {
285   uint32_t bitrate;
286   uint8_t format;
287   uint8_t paritytype;
288   uint8_t datatype;
289 } __attribute__((packed));
290
291 static struct line_coding line_coding = {
292   115200, /* baud rate: 115200    */
293   0x00,   /* stop bits: 1         */
294   0x00,   /* parity:    none      */
295   0x08    /* bits:      8         */
296 };
297
298 #define CDC_CTRL_DTR            0x0001
299
300 static void
301 usb_ctrl_write_finish (struct usb_dev *dev)
302 {
303   struct device_req *arg = &dev->dev_req;
304   uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
305
306   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
307       && USB_SETUP_SET (arg->type))
308     {
309       if (arg->request == USB_FSIJ_EXEC)
310         {
311           chopstx_mutex_lock (&usb_mtx);
312           if (fsij_device_state == FSIJ_DEVICE_EXITED)
313             {
314               usb_lld_prepare_shutdown (); /* No further USB communication */
315               fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
316             }
317           chopstx_mutex_unlock (&usb_mtx);
318         }
319       else if (arg->request == USB_NEUG_SET_PASSWD)
320         set_passwd ();
321       else if (arg->request == USB_NEUG_EXIT)
322         {
323           if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
324                && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
325               || (neug_passwd[0] == usbbuf[0]
326                   && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0])))
327             {
328               chopstx_mutex_lock (&usb_mtx);
329               fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
330               chopstx_cond_signal (&usb_cnd);
331               chopstx_mutex_unlock (&usb_mtx);
332             }
333         }
334     }
335   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
336            && USB_SETUP_SET (arg->type))
337     {
338       if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
339         {
340           /* Open/close the connection.  */
341           chopstx_mutex_lock (&usb_mtx);
342           connected = (arg->value & CDC_CTRL_DTR)? 1 : 0;
343           chopstx_cond_signal (&usb_cnd);
344           chopstx_mutex_unlock (&usb_mtx);
345         }
346 #ifdef FRAUCHEKY_SUPPORT
347       else if (running_neug && arg->request == USB_CDC_REQ_SET_LINE_CODING)
348         {
349           chopstx_mutex_lock (&usb_mtx);
350           if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
351             {
352               fsij_device_state = FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED;
353               chopstx_cond_signal (&usb_cnd);
354             }
355           else if (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
356             fsij_device_state = FSIJ_DEVICE_RUNNING;
357           chopstx_mutex_unlock (&usb_mtx);
358         }
359       else if (!running_neug && arg->request == MSC_MASS_STORAGE_RESET_COMMAND)
360         fraucheky_setup_endpoints_for_interface (0);
361 #endif
362     }
363 }
364
365
366 static int
367 vcom_port_data_setup (struct usb_dev *dev)
368 {
369   struct device_req *arg = &dev->dev_req;
370
371   if (USB_SETUP_GET (arg->type))
372     {
373       if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
374         return usb_lld_ctrl_send (dev, &line_coding, sizeof(line_coding));
375     }
376   else  /* USB_SETUP_SET (req) */
377     {
378       if (arg->request == USB_CDC_REQ_SET_LINE_CODING
379           && arg->len == sizeof (line_coding))
380         return usb_lld_ctrl_recv (dev, &line_coding, sizeof (line_coding));
381       else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
382         return usb_lld_ctrl_ack (dev);
383     }
384
385   return -1;
386 }
387
388 static int
389 usb_setup (struct usb_dev *dev)
390 {
391   struct device_req *arg = &dev->dev_req;
392   uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
393
394   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
395     {
396       if (USB_SETUP_GET (arg->type))
397         {
398           if (arg->request == USB_FSIJ_MEMINFO)
399             {
400               chopstx_mutex_lock (&usb_mtx);
401               if (fsij_device_state != FSIJ_DEVICE_EXITED)
402                 {
403                   chopstx_mutex_unlock (&usb_mtx);
404                   return -1;
405                 }
406               chopstx_mutex_unlock (&usb_mtx);
407               return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
408             }
409           else if (arg->request == USB_NEUG_GET_INFO)
410             {
411               if (arg->index == 0)
412                 return usb_lld_ctrl_send (dev, &neug_mode, sizeof (uint8_t));
413               else if (arg->index == 1)
414                 return usb_lld_ctrl_send (dev, &neug_err_cnt, sizeof (uint16_t));
415               else if (arg->index == 2)
416                 return usb_lld_ctrl_send (dev, &neug_err_cnt_rc, sizeof (uint16_t));
417               else if (arg->index == 3)
418                 return usb_lld_ctrl_send (dev, &neug_err_cnt_p64, sizeof (uint16_t));
419               else if (arg->index == 4)
420                 return usb_lld_ctrl_send (dev, &neug_err_cnt_p4k, sizeof (uint16_t));
421               else if (arg->index == 5)
422                 return usb_lld_ctrl_send (dev, &neug_rc_max, sizeof (uint16_t));
423               else if (arg->index == 6)
424                 return usb_lld_ctrl_send (dev, &neug_p64_max, sizeof (uint16_t));
425               else if (arg->index == 7)
426                 return usb_lld_ctrl_send (dev, &neug_p4k_max, sizeof (uint16_t));
427               else
428                 return -1;
429             }
430         }
431       else /* SETUP_SET */
432         {
433           uint8_t *addr = (uint8_t *)(0x20000000 + arg->value * 0x100 + arg->index);
434
435           if (arg->request == USB_FSIJ_DOWNLOAD)
436             {
437               chopstx_mutex_lock (&usb_mtx);
438               if (fsij_device_state != FSIJ_DEVICE_EXITED)
439                 {
440                   chopstx_mutex_unlock (&usb_mtx);
441                   return -1;
442                 }
443               chopstx_mutex_unlock (&usb_mtx);
444
445               if (addr < &_regnual_start || addr + arg->len > &__heap_end__)
446                 return -1;
447
448               if (arg->index + arg->len < 256)
449                 memset (addr + arg->index + arg->len, 0, 256 - (arg->index + arg->len));
450
451               return usb_lld_ctrl_recv (dev, addr, arg->len);
452             }
453           else if (arg->request == USB_FSIJ_EXEC && arg->len == 0)
454             {
455               chopstx_mutex_lock (&usb_mtx);
456               if (fsij_device_state != FSIJ_DEVICE_EXITED)
457                 {
458                   chopstx_mutex_unlock (&usb_mtx);
459                   return -1;
460                 }
461               chopstx_mutex_unlock (&usb_mtx);
462
463               if (((uint32_t)addr & 0x03))
464                 return -1;
465
466               return download_check_crc32 (dev, (uint32_t *)addr);
467             }
468           else if (arg->request == USB_NEUG_SET_PASSWD && arg->len <= 32)
469             {
470               usbbuf[0] = arg->len;
471               return usb_lld_ctrl_recv (dev, usbbuf + 1, arg->len);
472             }
473           else if (arg->request == USB_NEUG_EXIT && arg->len <= 32)
474             {
475               chopstx_mutex_lock (&usb_mtx);
476               if (fsij_device_state != FSIJ_DEVICE_RUNNING)
477                 {
478                   chopstx_mutex_unlock (&usb_mtx);
479                   return -1;
480                 }
481               chopstx_mutex_unlock (&usb_mtx);
482
483               usbbuf[0] = arg->len;
484               return usb_lld_ctrl_recv (dev, usbbuf + 1, arg->len);
485             }
486         }
487     }
488   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
489            && arg->index == 0)
490     {
491 #ifdef FRAUCHEKY_SUPPORT
492       if (running_neug)
493         return vcom_port_data_setup (dev);
494       else
495         return fraucheky_setup (dev);
496 #else
497       return vcom_port_data_setup (dev);
498 #endif
499     }
500
501   return -1;
502 }
503
504 static int
505 usb_get_descriptor (struct usb_dev *dev)
506 {
507   struct device_req *arg = &dev->dev_req;
508   uint8_t rcp = arg->type & RECIPIENT;
509   uint8_t desc_type = (arg->value >> 8);
510   uint8_t desc_index = (arg->value & 0xff);
511
512 #ifdef FRAUCHEKY_SUPPORT
513   if (!running_neug)
514     return fraucheky_get_descriptor (dev);
515 #endif
516
517   if (rcp != DEVICE_RECIPIENT)
518     return -1;
519
520   if (desc_type == DEVICE_DESCRIPTOR)
521     return usb_lld_ctrl_send (dev,
522                               vcom_device_desc, sizeof (vcom_device_desc));
523   else if (desc_type == CONFIG_DESCRIPTOR)
524     return usb_lld_ctrl_send (dev,
525                               vcom_config_desc, sizeof (vcom_config_desc));
526   else if (desc_type == STRING_DESCRIPTOR)
527     {
528       const uint8_t *str;
529       int size;
530
531       switch (desc_index)
532         {
533         case 0:
534           str = vcom_string0;
535           size = sizeof (vcom_string0);
536           break;
537         case 1:
538           str = neug_string_vendor;
539           size = sizeof (neug_string_vendor);
540           break;
541         case 2:
542           str = neug_string_product;
543           size = sizeof (neug_string_product);
544           break;
545         case 3:
546           str = neug_string_serial;
547           size = sizeof (neug_string_serial);
548           break;
549         case 4:
550           str = neug_revision_detail;
551           size = sizeof (neug_revision_detail);
552           break;
553         case 5:
554           str = neug_config_options;
555           size = sizeof (neug_config_options);
556           break;
557         case 6:
558           str = sys_version;
559           size = sizeof (sys_version);
560           break;
561 #ifdef USE_SYS3
562         case 7:
563           {
564             int i;
565             str = usbbuf;
566             for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
567               {
568                 if (sys_board_name[i] == 0)
569                   break;
570
571                 usbbuf[i*2+2] = sys_board_name[i];
572                 usbbuf[i*2+3] = 0;
573               }
574             usbbuf[0] = i*2 + 2;
575             usbbuf[1] = STRING_DESCRIPTOR;
576             size = i*2 + 2;
577           }
578           break;
579 #endif
580         default:
581           return -1;
582         }
583
584       return usb_lld_ctrl_send (dev, str, size);
585     }
586
587   return -1;
588 }
589
590 static void
591 neug_setup_endpoints_for_interface (uint16_t interface, int stop)
592 {
593   if (interface == 0)
594     {
595 #ifdef FRAUCHEKY_SUPPORT
596       if (running_neug)
597         {
598           if (!stop)
599             usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
600           else
601             usb_lld_stall_tx (ENDP2);
602         }
603       else
604         fraucheky_setup_endpoints_for_interface (stop);
605 #else
606       if (!stop)
607         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
608       else
609         usb_lld_stall_tx (ENDP2);
610 #endif
611     }
612   else if (interface == 1)
613     {
614       if (!stop)
615         {
616           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
617           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
618           /* Start with no data receiving (ENDP3 not enabled) */
619         }
620       else
621         {
622           usb_lld_stall_tx (ENDP1);
623           usb_lld_stall_rx (ENDP3);
624         }
625     }
626 }
627
628 static int
629 usb_set_configuration (struct usb_dev *dev)
630 {
631   int i;
632   uint8_t current_conf;
633
634   current_conf = usb_lld_current_configuration (dev);
635   if (current_conf == 0)
636     {
637       if (dev->dev_req.value != 1)
638         return -1;
639
640       usb_lld_set_configuration (dev, 1);
641       for (i = 0; i < NUM_INTERFACES; i++)
642         neug_setup_endpoints_for_interface (i, 0);
643       chopstx_mutex_lock (&usb_mtx);
644       bDeviceState = CONFIGURED;
645       chopstx_mutex_unlock (&usb_mtx);
646     }
647   else if (current_conf != dev->dev_req.value)
648     {
649       if (dev->dev_req.value != 0)
650         return -1;
651
652       usb_lld_set_configuration (dev, 0);
653       for (i = 0; i < NUM_INTERFACES; i++)
654         neug_setup_endpoints_for_interface (i, 1);
655       chopstx_mutex_lock (&usb_mtx);
656       bDeviceState = ADDRESSED;
657       chopstx_cond_signal (&usb_cnd);
658       chopstx_mutex_unlock (&usb_mtx);
659     }
660
661   /* Do nothing when current_conf == value */
662   return usb_lld_ctrl_ack (dev);
663 }
664
665
666 static int
667 usb_set_interface (struct usb_dev *dev)
668 {
669   uint16_t interface = dev->dev_req.index;
670   uint16_t alt = dev->dev_req.value;
671
672   if (interface >= NUM_INTERFACES)
673     return -1;
674
675   if (alt != 0)
676     return -1;
677   else
678     {
679       neug_setup_endpoints_for_interface (interface, 0);
680       return usb_lld_ctrl_ack (dev);
681     }
682 }
683
684 static int
685 usb_get_interface (struct usb_dev *dev)
686 {
687   const uint8_t zero = 0;
688   uint16_t interface = dev->dev_req.index;
689
690   if (interface >= NUM_INTERFACES)
691     return -1;
692
693   return usb_lld_ctrl_send (dev, &zero, 1);
694 }
695
696
697 static int
698 usb_get_status_interface (struct usb_dev *dev)
699 {
700   const uint16_t status_info = 0;
701   uint16_t interface = dev->dev_req.index;
702
703   if (interface >= NUM_INTERFACES)
704     return -1;
705
706   return usb_lld_ctrl_send (dev, &status_info, 2);
707 }
708
709 static void usb_tx_done (uint8_t ep_num, uint16_t len);
710 static void usb_rx_ready (uint8_t ep_num, uint16_t len);
711
712
713 #define INTR_REQ_USB 20
714 #define PRIO_USB 3
715
716 static void *
717 usb_main (void *arg)
718 {
719   chopstx_intr_t interrupt;
720   struct usb_dev dev;
721   int e;
722
723   (void)arg;
724   usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
725   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
726   goto event_handle;    /* For old SYS < 3.0 */
727
728   while (1)
729     {
730       chopstx_intr_wait (&interrupt);
731
732       if (interrupt.ready)
733         {
734           uint8_t ep_num;
735
736         event_handle:
737           e = usb_lld_event_handler (&dev);
738           ep_num = USB_EVENT_ENDP (e);
739
740           if (ep_num != 0)
741             {
742               if (USB_EVENT_TXRX (e))
743                 usb_tx_done (ep_num, USB_EVENT_LEN (e));
744               else
745                 usb_rx_ready (ep_num, USB_EVENT_LEN (e));
746             }
747           else
748             switch (USB_EVENT_ID (e))
749               {
750               case USB_EVENT_DEVICE_RESET:
751                 usb_device_reset (&dev);
752                 continue;
753
754               case USB_EVENT_DEVICE_ADDRESSED:
755                 chopstx_mutex_lock (&usb_mtx);
756                 bDeviceState = ADDRESSED;
757                 chopstx_cond_signal (&usb_cnd);
758                 chopstx_mutex_unlock (&usb_mtx);
759                 continue;
760
761               case USB_EVENT_GET_DESCRIPTOR:
762                 if (usb_get_descriptor (&dev) < 0)
763                   usb_lld_ctrl_error (&dev);
764                 continue;
765
766               case USB_EVENT_SET_CONFIGURATION:
767                 if (usb_set_configuration (&dev) < 0)
768                   usb_lld_ctrl_error (&dev);
769                 continue;
770
771               case USB_EVENT_SET_INTERFACE:
772                 if (usb_set_interface (&dev) < 0)
773                   usb_lld_ctrl_error (&dev);
774                 continue;
775
776               case USB_EVENT_CTRL_REQUEST:
777                 /* Device specific device request.  */
778                 if (usb_setup (&dev) < 0)
779                   usb_lld_ctrl_error (&dev);
780                 continue;
781
782               case USB_EVENT_GET_STATUS_INTERFACE:
783                 if (usb_get_status_interface (&dev) < 0)
784                   usb_lld_ctrl_error (&dev);
785                 continue;
786
787               case USB_EVENT_GET_INTERFACE:
788                 if (usb_get_interface (&dev) < 0)
789                   usb_lld_ctrl_error (&dev);
790                 continue;
791
792               case USB_EVENT_SET_FEATURE_DEVICE:
793               case USB_EVENT_SET_FEATURE_ENDPOINT:
794               case USB_EVENT_CLEAR_FEATURE_DEVICE:
795               case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
796                 usb_lld_ctrl_ack (&dev);
797                 continue;
798
799               case USB_EVENT_CTRL_WRITE_FINISH:
800                 /* Control WRITE transfer finished.  */
801                 usb_ctrl_write_finish (&dev);
802                 continue;
803
804               case USB_EVENT_OK:
805               case USB_EVENT_DEVICE_SUSPEND:
806               default:
807                 continue;
808               }
809         }
810     }
811
812   return NULL;
813 }
814
815 #define ID_OFFSET (2+SERIALNO_STR_LEN*2)
816 static void fill_serial_no_by_unique_id (void)
817 {
818   extern const uint8_t * unique_device_id (void);
819   uint8_t *p = &neug_string_serial[ID_OFFSET];
820   const uint8_t *u = unique_device_id () + 8;
821   int i;
822
823   for (i = 0; i < 4; i++)
824     {
825       uint8_t b = u[3-i];
826       uint8_t nibble;
827
828       nibble = (b >> 4);
829       nibble += (nibble >= 10 ? ('A' - 10) : '0');
830       p[i*4] = nibble;
831       p[i*4+1] = 0;
832       nibble = (b & 0x0f);
833       nibble += (nibble >= 10 ? ('A' - 10) : '0');
834       p[i*4+2] = nibble;
835       p[i*4+3] = 0;
836     }
837 }
838
839
840 static void
841 usb_tx_done (uint8_t ep_num, uint16_t len)
842 {
843   if (ep_num == ENDP1)
844     {
845       chopstx_mutex_lock (&usb_mtx);
846       chopstx_cond_signal (&usb_cnd);
847       chopstx_mutex_unlock (&usb_mtx);
848     }
849   else if (ep_num == ENDP2)
850     {
851       /* INTERRUPT Transfer done */
852     }
853 #ifdef FRAUCHEKY_SUPPORT
854   else if (ep_num == ENDP6)
855     EP6_IN_Callback (len);
856 #else
857   (void)len;
858 #endif
859 }
860
861 static void
862 usb_rx_ready (uint8_t ep_num, uint16_t len)
863 {
864   if (ep_num == ENDP3)
865     usb_lld_rx_enable (ENDP3);
866 #ifdef FRAUCHEKY_SUPPORT
867   else if (ep_num == ENDP6)
868     EP6_OUT_Callback (len);
869 #else
870   (void)len;
871 #endif
872 }
873 \f
874 typedef uint32_t eventmask_t;
875 #define ALL_EVENTS (~0)
876
877 struct event_flag {
878   chopstx_mutex_t mutex;
879   chopstx_cond_t cond;
880   eventmask_t flag;
881 };
882
883 static void event_flag_init (struct event_flag *ev)
884 {
885   ev->flag = 0;
886   chopstx_mutex_init (&ev->mutex);
887   chopstx_cond_init (&ev->cond);
888 }
889
890
891 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
892 {
893   int n;
894
895   chopstx_mutex_lock (&ev->mutex);
896   while (!(ev->flag & m))
897     chopstx_cond_wait (&ev->cond, &ev->mutex);
898
899   n = __builtin_ffs ((ev->flag & m));
900   ev->flag &= ~(1 << (n - 1));
901   chopstx_mutex_unlock (&ev->mutex);
902
903   return (1 << (n - 1));
904 }
905
906 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
907 {
908   chopstx_mutex_lock (&ev->mutex);
909   ev->flag |= m;
910   chopstx_cond_signal (&ev->cond);
911   chopstx_mutex_unlock (&ev->mutex);
912 }
913
914 extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
915 extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
916
917 #define STACK_ADDR_LED ((uint32_t)__process1_stack_base__)
918 #define STACK_SIZE_LED ((uint32_t)__process1_stack_size__)
919 #define STACK_ADDR_USB ((uint32_t)__process3_stack_base__)
920 #define STACK_SIZE_USB ((uint32_t)__process3_stack_size__)
921
922
923 #define PRIO_LED 3
924 static struct event_flag led_event;
925
926 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
927 #define LED_TWOSHOTS            ((eventmask_t)2)
928 #define LED_ONESHOT_LONG        ((eventmask_t)4)
929
930 /*
931  * LED blinker: When notified, let LED emit for 100ms.
932  */
933 static void *
934 led_blinker (void *arg)
935 {
936   (void)arg;
937
938   set_led (0);
939
940   while (1)
941     {
942       eventmask_t m;
943
944       m = event_flag_waitone (&led_event, ALL_EVENTS);
945
946       set_led (1);
947       if (m == LED_ONESHOT_SHORT)
948         chopstx_usec_wait (100*1000);
949       else if (m == LED_TWOSHOTS)
950         {
951           chopstx_usec_wait (50*1000);
952           set_led (0);
953           chopstx_usec_wait (50*1000);
954           set_led (1);
955           chopstx_usec_wait (50*1000);
956         }
957       else
958         chopstx_usec_wait (250*1000);
959       set_led (0);
960     }
961
962   return NULL;
963 }
964 \f
965 #define RANDOM_BYTES_LENGTH 64
966 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
967
968 static void copy_to_tx (uint32_t v, int i)
969 {
970   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
971 }
972
973 /*
974  * In Gnuk 1.0.[12], reGNUal was not relocatable.
975  * Now, it's relocatable, but we need to calculate its entry address
976  * based on it's pre-defined address.
977  */
978 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
979 static uint32_t
980 calculate_regnual_entry_address (const uint8_t *addr)
981 {
982   const uint8_t *p = addr + 4;
983   uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
984
985   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
986   v += (uint32_t)addr;
987   return v;
988 }
989
990
991 static int
992 check_usb_status (void *arg)
993 {
994   (void)arg;
995
996   return (connected || bDeviceState != CONFIGURED
997           || fsij_device_state != FSIJ_DEVICE_RUNNING);
998 }
999
1000 /*
1001  * Entry point.
1002  *
1003  * NOTE: the main function is already a thread in the system on entry.
1004  */
1005 int
1006 main (int argc, char **argv)
1007 {
1008   uint32_t entry;
1009   chopstx_t led_thread, usb_thd;
1010   unsigned int count;
1011
1012   (void)argc;
1013   (void)argv;
1014
1015   fill_serial_no_by_unique_id ();
1016
1017   adc_init ();
1018
1019   event_flag_init (&led_event);
1020
1021   chopstx_mutex_init (&usb_mtx);
1022   chopstx_cond_init (&usb_cnd);
1023
1024 #ifdef FRAUCHEKY_SUPPORT
1025   if (fraucheky_enabled ())
1026     {
1027     go_fraucheky:
1028       bDeviceState = UNCONNECTED;
1029       running_neug = 0;
1030       usb_thd = chopstx_create (PRIO_USB, STACK_ADDR_USB, STACK_SIZE_USB,
1031                                 usb_main, NULL);
1032       while (bDeviceState != CONFIGURED)
1033         chopstx_usec_wait (250*1000);
1034       set_led (1);
1035       fraucheky_main ();
1036       chopstx_cancel (usb_thd);
1037       chopstx_join (usb_thd, NULL);
1038       usb_lld_shutdown ();
1039       bDeviceState = UNCONNECTED;
1040     }
1041
1042   running_neug = 1;
1043 #endif
1044
1045   led_thread = chopstx_create (PRIO_LED, STACK_ADDR_LED, STACK_SIZE_LED,
1046                                led_blinker, NULL);
1047
1048   usb_thd = chopstx_create (PRIO_USB, STACK_ADDR_USB, STACK_SIZE_USB,
1049                             usb_main, NULL);
1050
1051   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
1052
1053   chopstx_mutex_lock (&usb_mtx);
1054
1055  not_configured:
1056   count = 0;
1057   /* Initial run-up */
1058   while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
1059     {
1060       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
1061         break;
1062
1063       chopstx_mutex_unlock (&usb_mtx);
1064       neug_wait_full ();
1065       neug_flush ();
1066
1067       if ((count & 0x0007) == 0)
1068         event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1069       chopstx_usec_wait (25*1000);
1070       count++;
1071       chopstx_mutex_lock (&usb_mtx);
1072     }
1073
1074   /* Holding USB_MTX...  */
1075   while (1)
1076     {
1077       int last_was_fullsizepacket = 0;
1078
1079       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
1080         break;
1081
1082       chopstx_mutex_unlock (&usb_mtx);
1083       while (1)
1084         {
1085           uint32_t usec = 5000*1000;
1086           chopstx_poll_cond_t poll_desc;
1087           struct chx_poll_head *pd_array[1] = {
1088             (struct chx_poll_head *)&poll_desc
1089           };
1090
1091           poll_desc.type = CHOPSTX_POLL_COND;
1092           poll_desc.ready = 0;
1093           poll_desc.cond = &usb_cnd;
1094           poll_desc.mutex = &usb_mtx;
1095           poll_desc.check = check_usb_status;
1096           poll_desc.arg = NULL;
1097
1098           if (chopstx_poll (&usec, 1, pd_array))
1099             break;
1100
1101           /* Timeout */
1102           neug_flush ();
1103           neug_mode_select (line_coding.paritytype);
1104           event_flag_signal (&led_event, LED_TWOSHOTS);
1105         }
1106
1107       chopstx_mutex_lock (&usb_mtx);
1108       if (bDeviceState != CONFIGURED)
1109         goto not_configured;
1110
1111       /* The connection opened.  */
1112       count = 0;
1113
1114       while (1)
1115         {
1116           int i;
1117
1118           chopstx_mutex_unlock (&usb_mtx);
1119           /*
1120            * No parity is standard.  It means providing conditioned output.
1121            * When parity enabled, it means to provide raw output
1122            * (CRC32 filtered when odd, direct sample of ADC when even).
1123            *
1124            * line_coding.paritytype:
1125            *   0: None, 1: Odd, 2: Even
1126            */
1127           neug_mode_select (line_coding.paritytype);
1128
1129           if ((count & 0x03ff) == 0)
1130             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1131
1132           i = neug_consume_random (copy_to_tx);
1133
1134           if (i == 0 && !last_was_fullsizepacket)
1135             {    /* Only send ZLP when the last packet was fullsize.  */
1136               neug_wait_full ();
1137
1138               chopstx_mutex_lock (&usb_mtx);
1139               if (bDeviceState != CONFIGURED || !connected
1140                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1141                 break;
1142             }
1143           else
1144             {
1145               if (i == 64/4)
1146                 last_was_fullsizepacket = 1;
1147               else
1148                 last_was_fullsizepacket = 0;
1149
1150               chopstx_mutex_lock (&usb_mtx);
1151               if (bDeviceState != CONFIGURED || !connected
1152                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1153                 break;
1154
1155               /* Prepare sending random data.  */
1156               usb_lld_tx_enable (ENDP1, i * 4);
1157               chopstx_cond_wait (&usb_cnd, &usb_mtx);
1158               count++;
1159             }
1160         }
1161     }
1162
1163   chopstx_mutex_unlock (&usb_mtx);
1164
1165   chopstx_cancel (led_thread);
1166   chopstx_join (led_thread, NULL);
1167
1168   /*
1169    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED
1170    * or FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED.
1171    */
1172   neug_fini ();
1173
1174   chopstx_mutex_lock (&usb_mtx);
1175 #ifdef FRAUCHEKY_SUPPORT
1176   if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
1177     {
1178       while (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
1179         {
1180           chopstx_mutex_unlock (&usb_mtx);
1181           set_led (1);
1182           chopstx_usec_wait (500*1000);
1183           set_led (0);
1184           chopstx_usec_wait (500*1000);
1185           chopstx_mutex_lock (&usb_mtx);
1186         }
1187
1188       usb_lld_prepare_shutdown ();
1189       chopstx_mutex_unlock (&usb_mtx);
1190       chopstx_cancel (usb_thd);
1191       chopstx_join (usb_thd, NULL);
1192       usb_lld_shutdown ();
1193       goto go_fraucheky;
1194     }
1195 #endif
1196
1197   fsij_device_state = FSIJ_DEVICE_EXITED;
1198
1199   while (fsij_device_state == FSIJ_DEVICE_EXITED)
1200     {
1201       chopstx_mutex_unlock (&usb_mtx);
1202       chopstx_usec_wait (500*1000);
1203       chopstx_mutex_lock (&usb_mtx);
1204     }
1205   chopstx_mutex_unlock (&usb_mtx);
1206
1207   flash_unlock ();              /* Flash unlock should be done here */
1208   set_led (1);
1209   usb_lld_shutdown ();
1210
1211   /* Finish application.  */
1212   chopstx_cancel (usb_thd);
1213   chopstx_join (usb_thd, NULL);
1214
1215   /* Set vector */
1216   SCB->VTOR = (uint32_t)&_regnual_start;
1217   entry = calculate_regnual_entry_address (&_regnual_start);
1218 #ifdef DFU_SUPPORT
1219 #define FLASH_SYS_START_ADDR 0x08000000
1220 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
1221 #define CHIP_ID_REG ((uint32_t *)0xE0042000)
1222   {
1223     extern uint8_t _sys;
1224     uint32_t addr;
1225     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
1226     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
1227     uint32_t flash_page_size = 1024; /* 1KiB default */
1228
1229    if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device.  */
1230      flash_page_size += 0x0400; /* It's 2KiB. */
1231
1232     /* Kill DFU */
1233     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
1234          addr += flash_page_size)
1235       flash_erase_page (addr);
1236
1237     /* copy system service routines */
1238     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
1239
1240     /* Leave NeuG to exec reGNUal */
1241     (*func) ((void (*)(void))entry);
1242     for (;;);
1243   }
1244 #else
1245   /* Leave NeuG to exec reGNUal */
1246   flash_erase_all_and_exec ((void (*)(void))entry);
1247 #endif
1248
1249   /* Never reached */
1250   return 0;
1251 }