add error count request
[gnuk/neug.git] / src / main.c
1 /*
2  * main.c - main routine of neug
3  *
4  * Main routine:
5  * Copyright (C) 2011, 2012 Free Software Initiative of Japan
6  * Author: NIIBE Yutaka <gniibe@fsij.org>
7  *
8  * This file is a part of NeuG, a Random Number Generator
9  * implementation.
10  *
11  * NeuG is free software: you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19  * License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25
26 #include "config.h"
27 #include "ch.h"
28 #include "hal.h"
29 #include "board.h"
30 #include "neug.h"
31 #include "usb_lld.h"
32 #include "sys.h"
33
34 /*
35  * We are trying to avoid dependency to C library. 
36  * GCC built-in function(s) are declared here.
37  */
38 extern void *memcpy(void *dest, const void *src, size_t n);
39 extern void *memset (void *s, int c, size_t n);
40
41 static Thread *main_thread = NULL;
42
43 \f
44 #define ENDP0_RXADDR        (0x40)
45 #define ENDP0_TXADDR        (0x80)
46 #define ENDP1_TXADDR        (0xc0)
47 #define ENDP2_TXADDR        (0x100)
48 #define ENDP3_RXADDR        (0x140)
49
50 #define USB_CDC_REQ_SET_LINE_CODING             0x20
51 #define USB_CDC_REQ_GET_LINE_CODING             0x21
52 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE      0x22
53 #define USB_CDC_REQ_SEND_BREAK                  0x23
54
55 /* USB Device Descriptor */
56 static const uint8_t vcom_device_desc[18] = {
57   18,   /* bLength */
58   USB_DEVICE_DESCRIPTOR_TYPE,   /* bDescriptorType */
59   0x10, 0x01,                   /* bcdUSB = 1.1 */
60   0x02,                         /* bDeviceClass (CDC).              */
61   0x00,                         /* bDeviceSubClass.                 */
62   0x00,                         /* bDeviceProtocol.                 */
63   0x40,                         /* bMaxPacketSize.                  */
64 #include "usb-vid-pid-ver.c.inc"
65   1,                            /* iManufacturer.                   */
66   2,                            /* iProduct.                        */
67   3,                            /* iSerialNumber.                   */
68   1                             /* bNumConfigurations.              */
69 };
70
71 /* Configuration Descriptor tree for a CDC.*/
72 static const uint8_t vcom_configuration_desc[67] = {
73   9,
74   USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
75   /* Configuration Descriptor.*/
76   67, 0x00,                     /* wTotalLength.                    */
77   0x02,                         /* bNumInterfaces.                  */
78   0x01,                         /* bConfigurationValue.             */
79   0,                            /* iConfiguration.                  */
80   0x80,                         /* bmAttributes (bus powered).      */
81   50,                           /* bMaxPower (100mA).               */
82   /* Interface Descriptor.*/
83   9,
84   USB_INTERFACE_DESCRIPTOR_TYPE,
85   0x00,            /* bInterfaceNumber.                */
86   0x00,            /* bAlternateSetting.               */
87   0x01,            /* bNumEndpoints.                   */
88   0x02,            /* bInterfaceClass (Communications Interface Class,
89                       CDC section 4.2).  */
90   0x02,            /* bInterfaceSubClass (Abstract Control Model, CDC
91                       section 4.3).  */
92   0x01,            /* bInterfaceProtocol (AT commands, CDC section
93                       4.4).  */
94   0,               /* iInterface.                      */
95   /* Header Functional Descriptor (CDC section 5.2.3).*/
96   5,          /* bLength.                         */
97   0x24,       /* bDescriptorType (CS_INTERFACE).  */
98   0x00,       /* bDescriptorSubtype (Header Functional Descriptor). */
99   0x10, 0x01, /* bcdCDC.                          */
100   /* Call Management Functional Descriptor. */
101   5,            /* bFunctionLength.                 */
102   0x24,         /* bDescriptorType (CS_INTERFACE).  */
103   0x01,         /* bDescriptorSubtype (Call Management Functional
104                    Descriptor). */
105   0x03,         /* bmCapabilities (D0+D1).          */
106   0x01,         /* bDataInterface.                  */
107   /* ACM Functional Descriptor.*/
108   4,            /* bFunctionLength.                 */
109   0x24,         /* bDescriptorType (CS_INTERFACE).  */
110   0x02,         /* bDescriptorSubtype (Abstract Control Management
111                    Descriptor).  */
112   0x02,         /* bmCapabilities.                  */
113   /* Union Functional Descriptor.*/
114   5,            /* bFunctionLength.                 */
115   0x24,         /* bDescriptorType (CS_INTERFACE).  */
116   0x06,         /* bDescriptorSubtype (Union Functional
117                    Descriptor).  */
118   0x00,         /* bMasterInterface (Communication Class
119                    Interface).  */
120   0x01,         /* bSlaveInterface0 (Data Class Interface).  */
121   /* Endpoint 2 Descriptor.*/
122   7,
123   USB_ENDPOINT_DESCRIPTOR_TYPE,
124   ENDP2|0x80,    /* bEndpointAddress.    */
125   0x03,          /* bmAttributes (Interrupt).        */
126   0x08, 0x00,    /* wMaxPacketSize.                  */
127   0xFF,          /* bInterval.                       */
128   /* Interface Descriptor.*/
129   9,
130   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
131   0x01,          /* bInterfaceNumber.                */
132   0x00,          /* bAlternateSetting.               */
133   0x02,          /* bNumEndpoints.                   */
134   0x0A,          /* bInterfaceClass (Data Class Interface, CDC section 4.5). */
135   0x00,          /* bInterfaceSubClass (CDC section 4.6). */
136   0x00,          /* bInterfaceProtocol (CDC section 4.7). */
137   0x00,          /* iInterface.                      */
138   /* Endpoint 3 Descriptor.*/
139   7,
140   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
141   ENDP3,    /* bEndpointAddress. */
142   0x02,                         /* bmAttributes (Bulk).             */
143   0x40, 0x00,                   /* wMaxPacketSize.                  */
144   0x00,                         /* bInterval.                       */
145   /* Endpoint 1 Descriptor.*/
146   7,
147   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
148   ENDP1|0x80,                   /* bEndpointAddress. */
149   0x02,                         /* bmAttributes (Bulk).             */
150   0x40, 0x00,                   /* wMaxPacketSize.                  */
151   0x00                          /* bInterval.                       */
152 };
153
154
155 /*
156  * U.S. English language identifier.
157  */
158 static const uint8_t vcom_string0[4] = {
159   4,                            /* bLength */
160   USB_STRING_DESCRIPTOR_TYPE,
161   0x09, 0x04                    /* LangID = 0x0409: US-English */
162 };
163
164 #define USB_STRINGS_FOR_NEUG 1
165 #include "usb-strings.c.inc"
166
167 /*
168  * Serial Number string.  NOTE: This does not have CONST qualifier.
169  */
170 static uint8_t vcom_string3[28] = {
171   28,                    /* bLength.                         */
172   USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType.                 */
173   '0', 0,  '.', 0,  '0', 0, '2', 0,    /* Version number of NeuG.          */
174   '-', 0,
175   0, 0, 0, 0,   /* Filled by Unique device ID.      */
176   0, 0, 0, 0,
177   0, 0, 0, 0,
178   0, 0, 0, 0,
179 };
180
181 static const struct Descriptor device_desc = {
182   vcom_device_desc,
183   sizeof (vcom_device_desc)
184 };
185
186 static const struct Descriptor config_desc = {
187   vcom_configuration_desc,
188   sizeof (vcom_configuration_desc)
189 };
190
191 static const struct Descriptor string_descs[] = {
192   {vcom_string0, sizeof vcom_string0},
193   {neug_string_vendor, sizeof (neug_string_vendor)},
194   {neug_string_product, sizeof (neug_string_product)},
195   {vcom_string3, sizeof (vcom_string3)},
196   {neug_revision_detail, sizeof (neug_revision_detail)},
197   {neug_config_options, sizeof (neug_config_options)},
198   {sys_version, sizeof (sys_version)},
199 };
200
201 #define NUM_STRING_DESC (sizeof (string_descs)/sizeof (struct Descriptor))
202
203 #define NUM_INTERFACES 2
204
205 uint32_t bDeviceState = UNCONNECTED; /* USB device status */
206
207 #define NEUG_WAIT_FOR_TX_READY 1
208 static uint8_t neug_state;
209
210 static void
211 neug_device_reset (void)
212 {
213   /* Set DEVICE as not configured */
214   usb_lld_set_configuration (0);
215
216   /* Current Feature initialization */
217   usb_lld_set_feature (config_desc.Descriptor[7]);
218
219   usb_lld_reset ();
220
221   /* Initialize Endpoint 0 */
222   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
223 }
224
225 extern uint8_t _regnual_start, __heap_end__;
226
227 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
228
229 /* USB vendor requests to control pipe */
230 #define USB_FSIJ_MEMINFO          0
231 #define USB_FSIJ_DOWNLOAD         1
232 #define USB_FSIJ_EXEC             2
233 #define USB_NEUG_GET_ERR_COUNT  254
234 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
235
236 enum {
237   FSIJ_DEVICE_RUNNING = 0,
238   FSIJ_DEVICE_EXITED,
239   FSIJ_DEVICE_EXEC_REQUESTED,
240   /**/
241   FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
242 }; 
243
244 static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
245
246 static uint32_t rbit (uint32_t v)
247 {
248   uint32_t r;
249
250   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
251   return r;
252 }
253
254 /* After calling this function, CRC module remain enabled.  */
255 static int download_check_crc32 (const uint32_t *end_p)
256 {
257   uint32_t crc32 = *end_p;
258   const uint32_t *p;
259
260   RCC->AHBENR |= RCC_AHBENR_CRCEN;
261   CRC->CR = CRC_CR_RESET;
262
263   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
264     CRC->DR = rbit (*p);
265
266   if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
267     return USB_SUCCESS;
268
269   return USB_UNSUPPORT;
270 }
271
272 static void neug_ctrl_write_finish (uint8_t req, uint8_t req_no,
273                                     uint16_t value, uint16_t index,
274                                     uint16_t len)
275 {
276   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
277
278   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
279       && USB_SETUP_SET (req) && len == 0)
280     {
281       if (req_no == USB_FSIJ_EXEC)
282         {
283           if (fsij_device_state != FSIJ_DEVICE_EXITED)
284             return;
285
286           (void)value; (void)index;
287           usb_lld_prepare_shutdown (); /* No further USB communication */
288           fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
289         }
290       else if (req_no == USB_NEUG_EXIT)
291         {
292           if (neug_state == NEUG_WAIT_FOR_TX_READY)
293             {
294               chSysLockFromIsr ();
295               main_thread->p_u.rdymsg = RDY_OK;
296               chSchReadyI (main_thread);
297               chSysUnlockFromIsr ();
298             }
299           else
300             chEvtSignalFlagsI (main_thread, 1);
301         }
302     }
303 }
304
305 struct line_coding
306 {
307   uint32_t bitrate;
308   uint8_t format;
309   uint8_t paritytype;
310   uint8_t datatype;
311 };
312
313 static struct line_coding line_coding = {
314   115200, /* baud rate: 115200    */
315   0x00,   /* stop bits: 1         */
316   0x00,   /* parity:    none      */
317   0x08    /* bits:      8         */
318 };
319
320 static uint8_t connected;
321
322 static int
323 vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
324 {
325   if (USB_SETUP_GET (req))
326     {
327       if (req_no == USB_CDC_REQ_GET_LINE_CODING)
328         {
329           usb_lld_set_data_to_send (&line_coding, sizeof(line_coding));
330           return USB_SUCCESS;
331         }
332     }
333   else  /* USB_SETUP_SET (req) */
334     {
335       if (req_no == USB_CDC_REQ_SET_LINE_CODING)
336         {
337           usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding));
338           return USB_SUCCESS;
339         }
340       else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
341         {
342           if (value != 0)
343             {
344               if (connected == 0)
345                 /* It's Open call */
346                 connected++;
347             }
348           else
349             {
350               if (connected)
351                 {
352                   /* Close call */
353                   connected = 0;
354                   if (neug_state == NEUG_WAIT_FOR_TX_READY)
355                     {
356                       chSysLockFromIsr ();
357                       main_thread->p_u.rdymsg = RDY_OK;
358                       chSchReadyI (main_thread);
359                       chSysUnlockFromIsr ();
360                     }
361                 }
362             }
363
364           return USB_SUCCESS;
365         }
366     }
367
368   return USB_UNSUPPORT;
369 }
370
371 static int
372 neug_setup (uint8_t req, uint8_t req_no,
373                uint16_t value, uint16_t index, uint16_t len)
374 {
375   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
376
377   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
378     {
379       if (USB_SETUP_GET (req))
380         {
381           if (req_no == USB_FSIJ_MEMINFO)
382             {
383               usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
384               return USB_SUCCESS;
385             }
386           else if (req_no == USB_NEUG_GET_ERR_COUNT)
387             {
388               extern uint16_t neug_err_count;
389
390               usb_lld_set_data_to_send (&neug_err_count, sizeof (uint16_t));
391               return USB_SUCCESS;
392             }
393         }
394       else /* SETUP_SET */
395         {
396           uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index);
397
398           if (req_no == USB_FSIJ_DOWNLOAD)
399             {
400               if (fsij_device_state != FSIJ_DEVICE_EXITED)
401                 return USB_UNSUPPORT;
402
403               if (addr < &_regnual_start || addr + len > &__heap_end__)
404                 return USB_UNSUPPORT;
405
406               if (index + len < 256)
407                 memset (addr + index + len, 0, 256 - (index + len));
408
409               usb_lld_set_data_to_recv (addr, len);
410               return USB_SUCCESS;
411             }
412           else if (req_no == USB_FSIJ_EXEC && len == 0)
413             {
414               if (fsij_device_state != FSIJ_DEVICE_EXITED)
415                 return USB_UNSUPPORT;
416
417               if (((uint32_t)addr & 0x03))
418                 return USB_UNSUPPORT;
419
420               return download_check_crc32 ((uint32_t *)addr);
421             }
422           else if (req_no == USB_NEUG_EXIT && len == 0)
423             {
424               if (fsij_device_state != FSIJ_DEVICE_RUNNING)
425                 return USB_UNSUPPORT;
426
427               fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
428               return USB_SUCCESS;
429             }
430         }
431     }
432   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
433     if (index == 0)
434       return vcom_port_data_setup (req, req_no, value);
435
436   return USB_UNSUPPORT;
437 }
438
439 static int
440 neug_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
441 {
442   (void)index;
443   if (desc_type == DEVICE_DESCRIPTOR)
444     {
445       usb_lld_set_data_to_send (device_desc.Descriptor,
446                                 device_desc.Descriptor_Size);
447       return USB_SUCCESS;
448     }
449   else if (desc_type == CONFIG_DESCRIPTOR)
450     {
451       usb_lld_set_data_to_send (config_desc.Descriptor,
452                                 config_desc.Descriptor_Size);
453       return USB_SUCCESS;
454     }
455   else if (desc_type == STRING_DESCRIPTOR)
456     {
457       uint8_t desc_index = value & 0xff;
458
459       if (desc_index < NUM_STRING_DESC)
460         {
461           usb_lld_set_data_to_send (string_descs[desc_index].Descriptor,
462                                     string_descs[desc_index].Descriptor_Size);
463           return USB_SUCCESS;
464         }
465     }
466
467   return USB_UNSUPPORT;
468 }
469
470 static void
471 neug_setup_endpoints_for_interface (uint16_t interface, int stop)
472 {
473   if (interface == 0)
474     {
475       if (!stop)
476         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
477       else
478         usb_lld_stall_tx (ENDP2);
479     }
480   else if (interface == 1)
481     {
482       if (!stop)
483         {
484           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
485           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
486         }
487       else
488         {
489           usb_lld_stall_tx (ENDP1);
490           usb_lld_stall_rx (ENDP3);
491         }
492     }
493 }
494
495 static int neug_usb_event (uint8_t event_type, uint16_t value)
496 {
497   int i;
498   uint8_t current_conf;
499
500   switch (event_type)
501     {
502     case USB_EVENT_ADDRESS:
503       bDeviceState = ADDRESSED;
504       return USB_SUCCESS;
505     case USB_EVENT_CONFIG:
506       current_conf = usb_lld_current_configuration ();
507       if (current_conf == 0)
508         {
509           if (value != 1)
510             return USB_UNSUPPORT;
511
512           usb_lld_set_configuration (1);
513           for (i = 0; i < NUM_INTERFACES; i++)
514             neug_setup_endpoints_for_interface (i, 0);
515           bDeviceState = CONFIGURED;
516         }
517       else if (current_conf != value)
518         {
519           if (value != 0)
520             return USB_UNSUPPORT;
521
522           usb_lld_set_configuration (0);
523           for (i = 0; i < NUM_INTERFACES; i++)
524             neug_setup_endpoints_for_interface (i, 1);
525           bDeviceState = ADDRESSED;
526         }
527       /* Do nothing when current_conf == value */
528       return USB_SUCCESS;
529
530       return USB_SUCCESS;
531     default:
532       break;
533     }
534
535   return USB_UNSUPPORT;
536 }
537
538
539 static int neug_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
540 {
541   static uint8_t zero = 0;
542
543   if (interface >= NUM_INTERFACES)
544     return USB_UNSUPPORT;
545
546   switch (cmd)
547     {
548     case USB_SET_INTERFACE:
549       if (alt != 0)
550         return USB_UNSUPPORT;
551       else
552         {
553           neug_setup_endpoints_for_interface (interface, 0);
554           return USB_SUCCESS;
555         }
556
557     case USB_GET_INTERFACE:
558       usb_lld_set_data_to_send (&zero, 1);
559       return USB_SUCCESS;
560
561     default:
562     case USB_QUERY_INTERFACE:
563       return USB_SUCCESS;
564     }
565 }
566
567 const struct usb_device_method Device_Method = {
568   neug_device_reset,
569   neug_ctrl_write_finish,
570   neug_setup,
571   neug_get_descriptor,
572   neug_usb_event,
573   neug_interface,
574 };
575
576
577
578 static void fill_serial_no_by_unique_id (void)
579 {
580   extern const uint8_t * unique_device_id (void);
581   uint8_t *p = &vcom_string3[12];
582   const uint8_t *u = unique_device_id ();
583   int i;
584
585   for (i = 0; i < 4; i++)
586     {
587       uint8_t b = u[i];
588       uint8_t nibble; 
589
590       nibble = (b >> 4);
591       nibble += (nibble >= 10 ? ('A' - 10) : '0');
592       p[i*4] = nibble;
593       nibble = (b & 0x0f);
594       nibble += (nibble >= 10 ? ('A' - 10) : '0');
595       p[i*4+2] = nibble;
596     }
597 }
598 \f
599 CH_IRQ_HANDLER (Vector90)
600 {
601   CH_IRQ_PROLOGUE();
602   chSysLockFromIsr();
603
604   usb_interrupt_handler ();
605
606   chSysUnlockFromIsr();
607   CH_IRQ_EPILOGUE();
608 }
609
610 void
611 EP1_IN_Callback (void)
612 {
613   if (main_thread != NULL)
614     {
615       chSysLockFromIsr ();
616       main_thread->p_u.rdymsg = RDY_OK;
617       chSchReadyI (main_thread);
618       chSysUnlockFromIsr ();
619     }
620 }
621
622 void
623 EP2_IN_Callback (void)
624 {
625 }
626
627 void
628 EP3_OUT_Callback (void)
629 {
630   usb_lld_rx_enable (ENDP3);
631 }
632 \f
633 static WORKING_AREA(wa_led, 64);
634
635 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
636 #define LED_TWOSHOTS            ((eventmask_t)2)
637 #define LED_ONESHOT_LONG        ((eventmask_t)4)
638 static Thread *led_thread;
639
640 /*
641  * LED blinker: When notified, let LED emit for 100ms.
642  */
643 static msg_t led_blinker (void *arg)
644 {
645   (void)arg;
646
647   led_thread = chThdSelf ();
648   set_led (0);
649
650   while (1)
651     {
652       eventmask_t m;
653
654       m = chEvtWaitOne (ALL_EVENTS);
655       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
656         break;
657
658       set_led (1);
659       if (m == LED_ONESHOT_SHORT)
660         chThdSleep (MS2ST (100));
661       else if (m == LED_TWOSHOTS)
662         {
663           chThdSleep (MS2ST (50));
664           set_led (0);
665           chThdSleep (MS2ST (50));
666           set_led (1);
667           chThdSleep (MS2ST (50));
668         }
669       else
670         chThdSleep (MS2ST (250));
671       set_led (0);
672     }
673
674   return 0;
675 }
676 \f
677 #define RANDOM_BYTES_LENGTH 32
678 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
679
680 extern void adc2_init (void);
681
682 /*
683  * Entry point.
684  *
685  * NOTE: the main function is already a thread in the system on entry.
686  */
687 int
688 main (int argc, char **argv)
689 {
690   (void)argc;
691   (void)argv;
692
693   fill_serial_no_by_unique_id ();
694
695   halInit ();
696   adc2_init ();
697   chSysInit ();
698
699   main_thread = chThdSelf ();
700
701   chThdCreateStatic (wa_led, sizeof (wa_led), NORMALPRIO, led_blinker, NULL);
702
703   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
704
705   usb_lld_init (config_desc.Descriptor[7]);
706
707   while (1)
708     {
709       unsigned int count = 0;
710
711       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
712         break;
713
714       while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
715         {
716           if (fsij_device_state != FSIJ_DEVICE_RUNNING)
717             break;
718
719           neug_wait_full ();
720           neug_flush ();
721
722           if ((count & 0x0007) == 0)
723             chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
724           chEvtWaitOneTimeout (ALL_EVENTS, MS2ST (25));
725           count++;
726         }
727
728     waiting_connection:
729       while (connected == 0)
730         {
731           if (fsij_device_state != FSIJ_DEVICE_RUNNING)
732             break;
733
734           neug_flush ();
735           chEvtSignalFlags (led_thread, LED_TWOSHOTS);
736           chEvtWaitOneTimeout (ALL_EVENTS, MS2ST (5000));
737         }
738
739       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
740         break;
741
742       /* The connection opened.  */
743       count = 0;
744       /*
745        * No parity is standard.  It means to provide conditioned output.
746        * When parity enabled, it means to provide raw output.
747        */
748       neug_mode_select (line_coding.paritytype); /* 0: None, 1: Odd, 2: Even */
749
750       while (1)
751         {
752           if (fsij_device_state != FSIJ_DEVICE_RUNNING)
753             break;
754
755           if (bDeviceState != CONFIGURED)
756             break;
757
758           neug_wait_full ();
759
760           if ((count & 0x03ff) == 0)
761             chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
762
763           usb_lld_txcpy (random_word, ENDP1, 0, RANDOM_BYTES_LENGTH);
764           neug_flush ();
765
766           chSysLock ();
767           if (connected == 0)
768             {
769               chSysUnlock();
770               goto waiting_connection;
771             }
772           else
773             {
774               neug_state = NEUG_WAIT_FOR_TX_READY;
775               usb_lld_tx_enable (ENDP1, RANDOM_BYTES_LENGTH);
776               chSchGoSleepS (THD_STATE_SUSPENDED);
777               neug_state = 0;
778             }
779           chSysUnlock();
780
781           count++;
782         }
783     }
784
785   chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
786   chThdWait (led_thread);
787
788   /*
789    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED.
790    */
791   neug_fini ();
792
793   fsij_device_state = FSIJ_DEVICE_EXITED;
794
795   while (fsij_device_state == FSIJ_DEVICE_EXITED)
796     chThdSleep (MS2ST (500));
797
798   flash_unlock ();              /* Flash unlock should be done here */
799   set_led (1);
800   usb_lld_shutdown ();
801   /* Disable SysTick */
802   SysTick->CTRL = 0;
803   /* Disable all interrupts */
804   port_disable ();
805   /* Set vector */
806   SCB->VTOR = (uint32_t)&_regnual_start;
807 #ifdef DFU_SUPPORT
808 #define FLASH_SYS_START_ADDR 0x08000000
809 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
810   {
811     extern uint8_t _sys;
812     uint32_t addr;
813     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
814     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10];
815
816     /* Kill DFU */
817     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
818          addr += FLASH_PAGE_SIZE)
819       flash_erase_page (addr);
820
821     /* copy system service routines */
822     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
823
824     /* Leave NeuG to exec reGNUal */
825     (*func) (*((void (**)(void))(&_regnual_start+4)));
826     for (;;);
827   }
828 #else
829   /* Leave NeuG to exec reGNUal */
830   flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4)));
831 #endif
832
833   /* Never reached */
834   return 0;
835 }