7139b0d082eca357f8eb9b6dadaa68f1655d8104
[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 \f
42 #define ENDP0_RXADDR        (0x40)
43 #define ENDP0_TXADDR        (0x80)
44 #define ENDP1_TXADDR        (0xc0)
45 #define ENDP2_TXADDR        (0x100)
46 #define ENDP3_RXADDR        (0x140)
47
48 #define USB_CDC_REQ_SET_LINE_CODING             0x20
49 #define USB_CDC_REQ_GET_LINE_CODING             0x21
50 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE      0x22
51 #define USB_CDC_REQ_SEND_BREAK                  0x23
52
53 /* USB Device Descriptor */
54 static const uint8_t vcom_device_desc[18] = {
55   18,   /* bLength */
56   USB_DEVICE_DESCRIPTOR_TYPE,   /* bDescriptorType */
57   0x10, 0x01,                   /* bcdUSB = 1.1 */
58   0x02,                         /* bDeviceClass (CDC).              */
59   0x00,                         /* bDeviceSubClass.                 */
60   0x00,                         /* bDeviceProtocol.                 */
61   0x40,                         /* bMaxPacketSize.                  */
62   0x4b, 0x23,                   /* idVendor (FSIJ).                 */
63   0x01, 0x00,                   /* idProduct (NeoG).                */
64   0x00, 0x01,                   /* bcdDevice.                       */
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 /*
165  * Vendor string.
166  */
167 static const uint8_t vcom_string1[68] = {
168   68,                    /* bLength.                         */
169   USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType.                 */
170   /* Manufacturer: "Free Software Initiative of Japan" */
171   'F', 0, 'r', 0, 'e', 0, 'e', 0, ' ', 0, 'S', 0, 'o', 0, 'f', 0,
172   't', 0, 'w', 0, 'a', 0, 'r', 0, 'e', 0, ' ', 0, 'I', 0, 'n', 0,
173   'i', 0, 't', 0, 'i', 0, 'a', 0, 't', 0, 'i', 0, 'v', 0, 'e', 0,
174   ' ', 0, 'o', 0, 'f', 0, ' ', 0, 'J', 0, 'a', 0, 'p', 0, 'a', 0,
175   'n', 0
176 };
177
178 /*
179  * Device Description string.
180  */
181 static const uint8_t vcom_string2[18] = {
182   18,                    /* bLength.                         */
183   USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType.                 */
184   /* Product name: "NeuG RNG" */
185   'N', 0, 'e', 0, 'u', 0, 'G', 0, ' ', 0, 'R', 0, 'N', 0, 'G', 0,
186 };
187
188 /*
189  * Serial Number string.  NOTE: This does not have CONST qualifier.
190  */
191 static uint8_t vcom_string3[28] = {
192   28,                    /* bLength.                         */
193   USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType.                 */
194   '0', 0,  '.', 0,  '0', 0, '2', 0,    /* Version number of NeuG.          */
195   '-', 0,
196   0, 0, 0, 0,   /* Filled by Unique device ID.      */
197   0, 0, 0, 0,
198   0, 0, 0, 0,
199   0, 0, 0, 0,
200 };
201
202 static const struct Descriptor device_desc = {
203   vcom_device_desc,
204   sizeof (vcom_device_desc)
205 };
206
207 static const struct Descriptor config_desc = {
208   vcom_configuration_desc,
209   sizeof (vcom_configuration_desc)
210 };
211
212 static const struct Descriptor string_descs[] = {
213   {vcom_string0, sizeof vcom_string0},
214   {vcom_string1, sizeof vcom_string1},
215   {vcom_string2, sizeof vcom_string2},
216   {vcom_string3, sizeof vcom_string3}
217 };
218
219 #define NUM_STRING_DESC (sizeof (string_descs)/sizeof (struct Descriptor))
220
221 #define NUM_INTERFACES 2
222
223 uint32_t bDeviceState = UNCONNECTED; /* USB device status */
224
225
226 static void
227 neug_device_reset (void)
228 {
229   /* Set DEVICE as not configured */
230   usb_lld_set_configuration (0);
231
232   /* Current Feature initialization */
233   usb_lld_set_feature (config_desc.Descriptor[7]);
234
235   usb_lld_reset ();
236
237   /* Initialize Endpoint 0 */
238   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
239 }
240
241 #define USB_REGNUAL_MEMINFO     0
242 #define USB_REGNUAL_SEND        1
243 #define USB_REGNUAL_RESULT      2
244 #define USB_REGNUAL_FLASH       3
245 #define USB_REGNUAL_PROTECT     4
246 #define USB_REGNUAL_FINISH      5
247
248 static uint8_t mem[256];
249 static uint32_t result;
250
251 extern uint8_t __flash_start__,  __flash_end__;
252 static const uint8_t *const mem_info[] = { &__flash_start__,  &__flash_end__ };
253
254
255 static uint32_t rbit (uint32_t v)
256 {
257   uint32_t r;
258
259   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
260   return r;
261 }
262
263 static uint32_t fetch (int i)
264 {
265   uint32_t v;
266
267   v = *(uint32_t *)(&mem[i*4]);
268   return rbit (v);
269 }
270
271 static uint32_t calc_crc32 (void)
272 {
273   int i;
274
275   CRC->CR = CRC_CR_RESET;
276
277   for (i = 0; i < 256/4; i++)
278     CRC->DR = fetch (i);
279
280   return rbit (CRC->DR);
281 }
282
283
284 static void neug_ctrl_write_finish (uint8_t req, uint8_t req_no,
285                                     uint16_t value, uint16_t index,
286                                     uint16_t len)
287 {
288   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
289
290   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
291     {
292       if (req_no == USB_REGNUAL_SEND && value == 0)
293         result = calc_crc32 ();
294       else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
295         {
296           uint32_t dst_addr = (0x08000000 + value * 0x100);
297
298           result = flash_write (dst_addr, mem, 256);
299         }
300       else if (req_no == USB_REGNUAL_PROTECT && len == 0
301                && value == 0 && index == 0)
302         result = flash_protect ();
303       else if (req_no == USB_REGNUAL_FINISH && len == 0
304                && value == 0 && index == 0)
305         nvic_system_reset ();
306     }
307 }
308
309 struct line_coding
310 {
311   uint32_t bitrate;
312   uint8_t format;
313   uint8_t paritytype;
314   uint8_t datatype;
315 };
316
317 static struct line_coding line_coding = {
318   115200, /* baud rate: 115200    */
319   0x00,   /* stop bits: 1         */
320   0x00,   /* parity:    none      */
321   0x08    /* bits:      8         */
322 };
323
324 static uint8_t connected;
325
326 static int
327 vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
328 {
329   if (USB_SETUP_GET (req))
330     {
331       if (req_no == USB_CDC_REQ_GET_LINE_CODING)
332         {
333           usb_lld_set_data_to_send (&line_coding, sizeof(line_coding));
334           return USB_SUCCESS;
335         }
336     }
337   else  /* USB_SETUP_SET (req) */
338     {
339       if (req_no == USB_CDC_REQ_SET_LINE_CODING)
340         {
341           usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding));
342           return USB_SUCCESS;
343         }
344       else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
345         {
346           if (value != 0)
347             {
348               if ((connected & 1) == 0)
349                 /* It's Open call */
350                 connected++;
351             }
352           else
353             /* Close call */
354             connected++;
355
356           return USB_SUCCESS;
357         }
358     }
359
360   return USB_UNSUPPORT;
361 }
362
363 static int
364 neug_setup (uint8_t req, uint8_t req_no,
365                uint16_t value, uint16_t index, uint16_t len)
366 {
367   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
368
369   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
370     {
371       if (USB_SETUP_GET (req))
372         {
373           if (req_no == USB_REGNUAL_MEMINFO)
374             {
375               usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
376               return USB_SUCCESS;
377             }
378           else if (req_no == USB_REGNUAL_RESULT)
379             {
380               usb_lld_set_data_to_send (&result, sizeof (uint32_t));
381               return USB_SUCCESS;
382             }
383         }
384       else /* SETUP_SET */
385         {
386           if (req_no == USB_REGNUAL_SEND)
387             {
388               if (value != 0 || index + len > 256)
389                 return USB_UNSUPPORT;
390
391               if (index + len < 256)
392                 memset (mem + index + len, 0xff, 256 - (index + len));
393
394               usb_lld_set_data_to_recv (mem + index, len);
395               return USB_SUCCESS;
396             }
397           else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
398             {
399               uint32_t dst_addr = (0x08000000 + value * 0x100);
400
401               if (dst_addr + 256 <= (uint32_t)&__flash_end__)
402                 return USB_SUCCESS;
403             }
404           else if (req_no == USB_REGNUAL_PROTECT && len == 0
405                    && value == 0 && index == 0)
406             return USB_SUCCESS;
407           else if (req_no == USB_REGNUAL_FINISH && len == 0
408                    && value == 0 && index == 0)
409             return USB_SUCCESS;
410         }
411     }
412   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
413     if (index == 0)
414       return vcom_port_data_setup (req, req_no, value);
415
416   return USB_UNSUPPORT;
417 }
418
419 static int
420 neug_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
421 {
422   (void)index;
423   if (desc_type == DEVICE_DESCRIPTOR)
424     {
425       usb_lld_set_data_to_send (device_desc.Descriptor,
426                                 device_desc.Descriptor_Size);
427       return USB_SUCCESS;
428     }
429   else if (desc_type == CONFIG_DESCRIPTOR)
430     {
431       usb_lld_set_data_to_send (config_desc.Descriptor,
432                                 config_desc.Descriptor_Size);
433       return USB_SUCCESS;
434     }
435   else if (desc_type == STRING_DESCRIPTOR)
436     {
437       uint8_t desc_index = value & 0xff;
438
439       if (desc_index < NUM_STRING_DESC)
440         {
441           usb_lld_set_data_to_send (string_descs[desc_index].Descriptor,
442                                     string_descs[desc_index].Descriptor_Size);
443           return USB_SUCCESS;
444         }
445     }
446
447   return USB_UNSUPPORT;
448 }
449
450 static void
451 neug_setup_endpoints_for_interface (uint16_t interface, int stop)
452 {
453   if (interface == 0)
454     {
455       if (!stop)
456         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
457       else
458         usb_lld_stall_tx (ENDP2);
459     }
460   else if (interface == 1)
461     {
462       if (!stop)
463         {
464           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
465           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
466         }
467       else
468         {
469           usb_lld_stall_tx (ENDP1);
470           usb_lld_stall_rx (ENDP3);
471         }
472     }
473 }
474
475 static int neug_usb_event (uint8_t event_type, uint16_t value)
476 {
477   int i;
478   uint8_t current_conf;
479
480   switch (event_type)
481     {
482     case USB_EVENT_ADDRESS:
483       bDeviceState = ADDRESSED;
484       return USB_SUCCESS;
485     case USB_EVENT_CONFIG:
486       current_conf = usb_lld_current_configuration ();
487       if (current_conf == 0)
488         {
489           if (value != 1)
490             return USB_UNSUPPORT;
491
492           usb_lld_set_configuration (1);
493           for (i = 0; i < NUM_INTERFACES; i++)
494             neug_setup_endpoints_for_interface (i, 0);
495           bDeviceState = CONFIGURED;
496         }
497       else if (current_conf != value)
498         {
499           if (value != 0)
500             return USB_UNSUPPORT;
501
502           usb_lld_set_configuration (0);
503           for (i = 0; i < NUM_INTERFACES; i++)
504             neug_setup_endpoints_for_interface (i, 1);
505           bDeviceState = ADDRESSED;
506         }
507       /* Do nothing when current_conf == value */
508       return USB_SUCCESS;
509
510       return USB_SUCCESS;
511     default:
512       break;
513     }
514
515   return USB_UNSUPPORT;
516 }
517
518
519 static int neug_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
520 {
521   static uint8_t zero = 0;
522
523   if (interface >= NUM_INTERFACES)
524     return USB_UNSUPPORT;
525
526   switch (cmd)
527     {
528     case USB_SET_INTERFACE:
529       if (alt != 0)
530         return USB_UNSUPPORT;
531       else
532         {
533           neug_setup_endpoints_for_interface (interface, 0);
534           return USB_SUCCESS;
535         }
536
537     case USB_GET_INTERFACE:
538       usb_lld_set_data_to_send (&zero, 1);
539       return USB_SUCCESS;
540
541     default:
542     case USB_QUERY_INTERFACE:
543       return USB_SUCCESS;
544     }
545 }
546
547 const struct usb_device_method Device_Method = {
548   neug_device_reset,
549   neug_ctrl_write_finish,
550   neug_setup,
551   neug_get_descriptor,
552   neug_usb_event,
553   neug_interface,
554 };
555
556
557
558 static void fill_serial_no_by_unique_id (void)
559 {
560   extern const uint8_t * unique_device_id (void);
561   uint8_t *p = &vcom_string3[12];
562   const uint8_t *u = unique_device_id ();
563   int i;
564
565   for (i = 0; i < 4; i++)
566     {
567       uint8_t b = u[i];
568       uint8_t nibble; 
569
570       nibble = (b >> 4);
571       nibble += (nibble >= 10 ? ('A' - 10) : '0');
572       p[i*4] = nibble;
573       nibble = (b & 0x0f);
574       nibble += (nibble >= 10 ? ('A' - 10) : '0');
575       p[i*4+2] = nibble;
576     }
577 }
578 \f
579 static Thread *main_thread = NULL;
580
581 CH_IRQ_HANDLER (Vector90)
582 {
583   CH_IRQ_PROLOGUE();
584   chSysLockFromIsr();
585
586   usb_interrupt_handler ();
587
588   chSysUnlockFromIsr();
589   CH_IRQ_EPILOGUE();
590 }
591
592 void
593 EP1_IN_Callback (void)
594 {
595   if (main_thread != NULL)
596     {
597       chSysLockFromIsr ();
598       main_thread->p_u.rdymsg = RDY_OK;
599       chSchReadyI (main_thread);
600       chSysUnlockFromIsr ();
601     }
602 }
603
604 void
605 EP2_IN_Callback (void)
606 {
607 }
608
609 void
610 EP3_OUT_Callback (void)
611 {
612   usb_lld_rx_enable (ENDP3);
613 }
614 \f
615 static WORKING_AREA(wa_led, 64);
616
617 #define LED_ONESHOT_SHORT ((eventmask_t)1)
618 #define LED_ONESHOT_LONG  ((eventmask_t)2)
619 static Thread *led_thread;
620
621 /*
622  * LED blinker: When notified, let LED emit for 100ms.
623  */
624 static msg_t led_blinker (void *arg)
625 {
626   (void)arg;
627
628   led_thread = chThdSelf ();
629   set_led (0);
630
631   while (1)
632     {
633       eventmask_t m;
634
635       m = chEvtWaitOne (ALL_EVENTS);
636       set_led (1);
637       if (m == LED_ONESHOT_SHORT)
638         chThdSleep (MS2ST (100));
639       else
640         chThdSleep (MS2ST (250));
641       set_led (0);
642     }
643
644   return 0;
645 }
646 \f
647 #define RANDOM_BYTES_LENGTH 60
648 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
649
650 /*
651  * Entry point.
652  *
653  * NOTE: the main function is already a thread in the system on entry.
654  */
655 int
656 main (int argc, char **argv)
657 {
658   (void)argc;
659   (void)argv;
660
661   fill_serial_no_by_unique_id ();
662
663   halInit();
664   chSysInit();
665
666   main_thread = chThdSelf ();
667
668   usb_lld_init (config_desc.Descriptor[7]);
669
670   chThdCreateStatic (wa_led, sizeof (wa_led), NORMALPRIO, led_blinker, NULL);
671
672   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
673
674   while (1)
675     {
676       unsigned int count = 0;
677
678       connected = 0;
679       while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
680         {
681           (void)neug_get (NEUG_KICK_FILLING);
682           if ((count & 0x000f) == 0)
683             chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
684           chThdSleep (MS2ST (25));
685           count++;
686         }
687
688     waiting_connection:
689       while ((connected & 1) == 0)
690         {
691           neug_flush ();
692           chEvtSignalFlags (led_thread, LED_ONESHOT_LONG);
693           chThdSleep (MS2ST (2500));
694         }
695
696       /* The connection opened.  */
697       count = 0;
698
699       while (1)
700         {
701           if ((connected & 1) == 0)
702             goto waiting_connection;
703
704           if (bDeviceState != CONFIGURED)
705             break;
706
707           neug_wait_full ();
708
709           if ((count & 0x00ff) == 0)
710             chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
711
712           usb_lld_txcpy (random_word, ENDP1, 0, RANDOM_BYTES_LENGTH);
713           neug_flush ();
714
715           chSysLock ();
716           usb_lld_tx_enable (ENDP1, RANDOM_BYTES_LENGTH);
717           chSchGoSleepS (THD_STATE_SUSPENDED);
718           chSysUnlock();
719
720           count++;
721         }
722     }
723
724   return 0;
725 }