update USB driver
[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
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 "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_EXIT_REQUESTED = 255
45 }; 
46
47 #ifdef FRAUCHEKY_SUPPORT
48 static uint8_t running_neug;
49 #endif
50
51 static chopstx_mutex_t usb_mtx;
52 static chopstx_cond_t cnd_usb;
53 static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
54 static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
55 static uint8_t connected;
56 static uint32_t wait_usb_connection; /* Timer variable.  */
57
58
59 extern uint8_t __process0_stack_end__;
60 static chopstx_t main_thd = (uint32_t)(&__process0_stack_end__ - 60);
61
62 #define ENDP0_RXADDR        (0x40)
63 #define ENDP0_TXADDR        (0x80)
64 #define ENDP1_TXADDR        (0xc0)
65 #define ENDP2_TXADDR        (0x100)
66 #define ENDP3_RXADDR        (0x140)
67
68 #define USB_CDC_REQ_SET_LINE_CODING             0x20
69 #define USB_CDC_REQ_GET_LINE_CODING             0x21
70 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE      0x22
71 #define USB_CDC_REQ_SEND_BREAK                  0x23
72
73 /* USB Device Descriptor */
74 static const uint8_t vcom_device_desc[18] = {
75   18,   /* bLength */
76   USB_DEVICE_DESCRIPTOR_TYPE,   /* bDescriptorType */
77   0x10, 0x01,                   /* bcdUSB = 1.1 */
78   0x02,                         /* bDeviceClass (CDC).              */
79   0x00,                         /* bDeviceSubClass.                 */
80   0x00,                         /* bDeviceProtocol.                 */
81   0x40,                         /* bMaxPacketSize.                  */
82 #include "usb-vid-pid-ver.c.inc"
83   1,                            /* iManufacturer.                   */
84   2,                            /* iProduct.                        */
85   3,                            /* iSerialNumber.                   */
86   1                             /* bNumConfigurations.              */
87 };
88
89 /* Configuration Descriptor tree for a CDC.*/
90 static const uint8_t vcom_config_desc[67] = {
91   9,
92   USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
93   /* Configuration Descriptor.*/
94   67, 0x00,                     /* wTotalLength.                    */
95   0x02,                         /* bNumInterfaces.                  */
96   0x01,                         /* bConfigurationValue.             */
97   0,                            /* iConfiguration.                  */
98   0x80,                         /* bmAttributes (bus powered).      */
99   50,                           /* bMaxPower (100mA).               */
100   /* Interface Descriptor.*/
101   9,
102   USB_INTERFACE_DESCRIPTOR_TYPE,
103   0x00,            /* bInterfaceNumber.                */
104   0x00,            /* bAlternateSetting.               */
105   0x01,            /* bNumEndpoints.                   */
106   0x02,            /* bInterfaceClass (Communications Interface Class,
107                       CDC section 4.2).  */
108   0x02,            /* bInterfaceSubClass (Abstract Control Model, CDC
109                       section 4.3).  */
110   0x01,            /* bInterfaceProtocol (AT commands, CDC section
111                       4.4).  */
112   0,               /* iInterface.                      */
113   /* Header Functional Descriptor (CDC section 5.2.3).*/
114   5,          /* bLength.                         */
115   0x24,       /* bDescriptorType (CS_INTERFACE).  */
116   0x00,       /* bDescriptorSubtype (Header Functional Descriptor). */
117   0x10, 0x01, /* bcdCDC.                          */
118   /* Call Management Functional Descriptor. */
119   5,            /* bFunctionLength.                 */
120   0x24,         /* bDescriptorType (CS_INTERFACE).  */
121   0x01,         /* bDescriptorSubtype (Call Management Functional
122                    Descriptor). */
123   0x03,         /* bmCapabilities (D0+D1).          */
124   0x01,         /* bDataInterface.                  */
125   /* ACM Functional Descriptor.*/
126   4,            /* bFunctionLength.                 */
127   0x24,         /* bDescriptorType (CS_INTERFACE).  */
128   0x02,         /* bDescriptorSubtype (Abstract Control Management
129                    Descriptor).  */
130   0x02,         /* bmCapabilities.                  */
131   /* Union Functional Descriptor.*/
132   5,            /* bFunctionLength.                 */
133   0x24,         /* bDescriptorType (CS_INTERFACE).  */
134   0x06,         /* bDescriptorSubtype (Union Functional
135                    Descriptor).  */
136   0x00,         /* bMasterInterface (Communication Class
137                    Interface).  */
138   0x01,         /* bSlaveInterface0 (Data Class Interface).  */
139   /* Endpoint 2 Descriptor.*/
140   7,
141   USB_ENDPOINT_DESCRIPTOR_TYPE,
142   ENDP2|0x80,    /* bEndpointAddress.    */
143   0x03,          /* bmAttributes (Interrupt).        */
144   0x08, 0x00,    /* wMaxPacketSize.                  */
145   0xFF,          /* bInterval.                       */
146   /* Interface Descriptor.*/
147   9,
148   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
149   0x01,          /* bInterfaceNumber.                */
150   0x00,          /* bAlternateSetting.               */
151   0x02,          /* bNumEndpoints.                   */
152   0x0A,          /* bInterfaceClass (Data Class Interface, CDC section 4.5). */
153   0x00,          /* bInterfaceSubClass (CDC section 4.6). */
154   0x00,          /* bInterfaceProtocol (CDC section 4.7). */
155   0x00,          /* iInterface.                      */
156   /* Endpoint 3 Descriptor.*/
157   7,
158   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
159   ENDP3,    /* bEndpointAddress. */
160   0x02,                         /* bmAttributes (Bulk).             */
161   0x40, 0x00,                   /* wMaxPacketSize.                  */
162   0x00,                         /* bInterval.                       */
163   /* Endpoint 1 Descriptor.*/
164   7,
165   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
166   ENDP1|0x80,                   /* bEndpointAddress. */
167   0x02,                         /* bmAttributes (Bulk).             */
168   0x40, 0x00,                   /* wMaxPacketSize.                  */
169   0x00                          /* bInterval.                       */
170 };
171
172
173 /*
174  * U.S. English language identifier.
175  */
176 static const uint8_t vcom_string0[4] = {
177   4,                            /* bLength */
178   USB_STRING_DESCRIPTOR_TYPE,
179   0x09, 0x04                    /* LangID = 0x0409: US-English */
180 };
181
182 #include "usb-strings.c.inc"
183
184 #ifdef FRAUCHEKY_SUPPORT
185 extern int fraucheky_enabled (void);
186 extern void fraucheky_main (void);
187
188 extern void fraucheky_setup_endpoints_for_interface (int stop);
189 extern int fraucheky_setup (uint8_t req, uint8_t req_no,
190                             struct control_info *detail);
191 extern int fraucheky_get_descriptor (uint8_t rcp, uint8_t desc_type,
192                                      uint8_t desc_index,
193                                      struct control_info *detail);
194 #endif
195
196 #define NUM_INTERFACES 2
197
198 void
199 usb_cb_device_reset (void)
200 {
201   /* Set DEVICE as not configured */
202   usb_lld_set_configuration (0);
203
204   /* Current Feature initialization */
205   usb_lld_set_feature (vcom_config_desc[7]);
206
207   usb_lld_reset ();
208
209   /* Initialize Endpoint 0 */
210   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
211 }
212
213 extern uint8_t _regnual_start, __heap_end__;
214
215 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
216
217 /* USB vendor requests to control pipe */
218 #define USB_FSIJ_MEMINFO          0
219 #define USB_FSIJ_DOWNLOAD         1
220 #define USB_FSIJ_EXEC             2
221 #define USB_NEUG_SET_PASSWD     253
222 #define USB_NEUG_GET_INFO       254
223 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
224
225 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
226   0xff,
227   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
228   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
229   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
230 };
231 static uint8_t usbbuf[64];
232
233 #define DEFAULT_PASSWD "12345678"
234 #define DEFAULT_PASSWD_LEN 8
235
236 static void set_passwd (void)
237 {
238   flash_unlock ();
239   if (neug_passwd[0] != 0xff)
240     flash_erase_page ((uint32_t)neug_passwd);
241   if (usbbuf[0] == DEFAULT_PASSWD_LEN
242       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
243     return;
244   flash_write ((uint32_t)neug_passwd, usbbuf, usbbuf[0] + 1);
245 }
246
247 static uint32_t rbit (uint32_t v)
248 {
249   uint32_t r;
250
251   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
252   return r;
253 }
254
255 /* After calling this function, CRC module remain enabled.  */
256 static int download_check_crc32 (const uint32_t *end_p)
257 {
258   uint32_t crc32 = *end_p;
259   const uint32_t *p;
260
261   RCC->AHBENR |= RCC_AHBENR_CRCEN;
262   CRC->CR = CRC_CR_RESET;
263
264   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
265     CRC->DR = rbit (*p);
266
267   if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
268     return USB_SUCCESS;
269
270   return USB_UNSUPPORT;
271 }
272
273 void
274 usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
275 {
276   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
277
278   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
279     {
280       if (req_no == USB_FSIJ_EXEC)
281         {
282           chopstx_mutex_lock (&usb_mtx);
283           if (fsij_device_state == FSIJ_DEVICE_EXITED)
284             {
285               usb_lld_prepare_shutdown (); /* No further USB communication */
286               fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
287             }
288           chopstx_mutex_unlock (&usb_mtx);
289         }
290       else if (req_no == USB_NEUG_SET_PASSWD)
291         set_passwd ();
292       else if (req_no == USB_NEUG_EXIT)
293         {
294           if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
295                && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
296               || (neug_passwd[0] == usbbuf[0]
297                   && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0])))
298             {
299               chopstx_mutex_lock (&usb_mtx);
300               fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
301               chopstx_wakeup_usec_wait (main_thd);
302               chopstx_cond_signal (&cnd_usb);
303               chopstx_mutex_unlock (&usb_mtx);
304             }
305         }
306     }
307   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
308            && USB_SETUP_SET (req)
309            && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
310     {
311       /* Open/close the connection.  */
312       chopstx_mutex_lock (&usb_mtx);
313       connected = (value != 0)? 1 : 0;
314       if (wait_usb_connection)
315         {                       /* It is waiting a connection.  */
316           if (connected)        /* It's now connected.  */
317             chopstx_wakeup_usec_wait (main_thd);
318         }
319       else
320         chopstx_cond_signal (&cnd_usb);
321       chopstx_mutex_unlock (&usb_mtx);
322     }
323 }
324
325 struct line_coding
326 {
327   uint32_t bitrate;
328   uint8_t format;
329   uint8_t paritytype;
330   uint8_t datatype;
331 } __attribute__((packed));
332
333 static struct line_coding line_coding = {
334   115200, /* baud rate: 115200    */
335   0x00,   /* stop bits: 1         */
336   0x00,   /* parity:    none      */
337   0x08    /* bits:      8         */
338 };
339
340
341 static int
342 vcom_port_data_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
343 {
344   if (USB_SETUP_GET (req))
345     {
346       if (req_no == USB_CDC_REQ_GET_LINE_CODING)
347         return usb_lld_reply_request (&line_coding, sizeof(line_coding), detail);
348     }
349   else  /* USB_SETUP_SET (req) */
350     {
351       if (req_no == USB_CDC_REQ_SET_LINE_CODING
352           && detail->len == sizeof (line_coding))
353         {
354           usb_lld_set_data_to_recv (&line_coding, sizeof (line_coding));
355           return USB_SUCCESS;
356         }
357       else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
358         return USB_SUCCESS;
359     }
360
361   return USB_UNSUPPORT;
362 }
363
364 int
365 usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
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_FSIJ_MEMINFO)
374             {
375               chopstx_mutex_lock (&usb_mtx);
376               if (fsij_device_state != FSIJ_DEVICE_EXITED)
377                 {
378                   chopstx_mutex_unlock (&usb_mtx);
379                   return USB_UNSUPPORT;
380                 }
381               chopstx_mutex_unlock (&usb_mtx);
382               usb_lld_reply_request (mem_info, sizeof (mem_info), detail);
383               return USB_SUCCESS;
384             }
385           else if (req_no == USB_NEUG_GET_INFO)
386             {
387               if (detail->index == 0)
388                 usb_lld_reply_request (&neug_mode, sizeof (uint8_t), detail);
389               else if (detail->index == 1)
390                 usb_lld_reply_request (&neug_err_cnt, sizeof (uint16_t), detail);
391               else if (detail->index == 2)
392                 usb_lld_reply_request (&neug_err_cnt_rc, sizeof (uint16_t), detail);
393               else if (detail->index == 3)
394                 usb_lld_reply_request (&neug_err_cnt_p64, sizeof (uint16_t), detail);
395               else if (detail->index == 4)
396                 usb_lld_reply_request (&neug_err_cnt_p4k, sizeof (uint16_t), detail);
397               else if (detail->index == 5)
398                 usb_lld_reply_request (&neug_rc_max, sizeof (uint16_t), detail);
399               else if (detail->index == 6)
400                 usb_lld_reply_request (&neug_p64_max, sizeof (uint16_t), detail);
401               else if (detail->index == 7)
402                 usb_lld_reply_request (&neug_p4k_max, sizeof (uint16_t), detail);
403               else
404                 return USB_UNSUPPORT;
405
406               return USB_SUCCESS;
407             }
408         }
409       else /* SETUP_SET */
410         {
411           uint8_t *addr = (uint8_t *)(0x20000000 + detail->value * 0x100 + detail->index);
412
413           if (req_no == USB_FSIJ_DOWNLOAD)
414             {
415               chopstx_mutex_lock (&usb_mtx);
416               if (fsij_device_state != FSIJ_DEVICE_EXITED)
417                 {
418                   chopstx_mutex_unlock (&usb_mtx);
419                   return USB_UNSUPPORT;
420                 }
421               chopstx_mutex_unlock (&usb_mtx);
422
423               if (addr < &_regnual_start || addr + detail->len > &__heap_end__)
424                 return USB_UNSUPPORT;
425
426               if (detail->index + detail->len < 256)
427                 memset (addr + detail->index + detail->len, 0, 256 - (detail->index + detail->len));
428
429               usb_lld_set_data_to_recv (addr, detail->len);
430               return USB_SUCCESS;
431             }
432           else if (req_no == USB_FSIJ_EXEC && detail->len == 0)
433             {
434               chopstx_mutex_lock (&usb_mtx);
435               if (fsij_device_state != FSIJ_DEVICE_EXITED)
436                 {
437                   chopstx_mutex_unlock (&usb_mtx);
438                   return USB_UNSUPPORT;
439                 }
440               chopstx_mutex_unlock (&usb_mtx);
441
442               if (((uint32_t)addr & 0x03))
443                 return USB_UNSUPPORT;
444
445               return download_check_crc32 ((uint32_t *)addr);
446             }
447           else if (req_no == USB_NEUG_SET_PASSWD && detail->len <= 32)
448             {
449               usbbuf[0] = detail->len;
450               usb_lld_set_data_to_recv (usbbuf + 1, detail->len);
451               return USB_SUCCESS;
452             }
453           else if (req_no == USB_NEUG_EXIT && detail->len <= 32)
454             {
455               chopstx_mutex_lock (&usb_mtx);
456               if (fsij_device_state != FSIJ_DEVICE_RUNNING)
457                 {
458                   chopstx_mutex_unlock (&usb_mtx);
459                   return USB_UNSUPPORT;
460                 }
461               chopstx_mutex_unlock (&usb_mtx);
462
463               usbbuf[0] = detail->len;
464               usb_lld_set_data_to_recv (usbbuf + 1, detail->len);
465               return USB_SUCCESS;
466             }
467         }
468     }
469   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
470            && detail->index == 0)
471     {
472 #ifdef FRAUCHEKY_SUPPORT
473       if (running_neug)
474         return vcom_port_data_setup (req, req_no, detail);
475       else
476         fraucheky_setup (req, req_no, detail);
477 #else
478       return vcom_port_data_setup (req, req_no, detail);
479 #endif
480     }
481
482   return USB_UNSUPPORT;
483 }
484
485 int
486 usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
487                        struct control_info *detail)
488 {
489 #ifdef FRAUCHEKY_SUPPORT
490   if (!running_neug)
491     return fraucheky_get_descriptor (rcp, desc_type, desc_index, detail);
492 #endif
493
494   if (rcp != DEVICE_RECIPIENT)
495     return USB_UNSUPPORT;
496
497   if (desc_type == DEVICE_DESCRIPTOR)
498     return usb_lld_reply_request (vcom_device_desc, sizeof (vcom_device_desc),
499                                   detail);
500   else if (desc_type == CONFIG_DESCRIPTOR)
501     return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
502                                   detail);
503   else if (desc_type == STRING_DESCRIPTOR)
504     {
505       const uint8_t *str;
506       int size;
507
508       switch (desc_index)
509         {
510         case 0:
511           str = vcom_string0;
512           size = sizeof (vcom_string0);
513           break;
514         case 1:
515           str = neug_string_vendor;
516           size = sizeof (neug_string_vendor);
517           break;
518         case 2:
519           str = neug_string_product;
520           size = sizeof (neug_string_product);
521           break;
522         case 3:
523           str = neug_string_serial;
524           size = sizeof (neug_string_serial);
525           break;
526         case 4:
527           str = neug_revision_detail;
528           size = sizeof (neug_revision_detail);
529           break;
530         case 5:
531           str = neug_config_options;
532           size = sizeof (neug_config_options);
533           break;
534         case 6:
535           str = sys_version;
536           size = sizeof (sys_version);
537           break;
538         case 7:
539           {
540             int i;
541             str = usbbuf;
542             for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
543               {
544                 if (sys_board_name[i] == 0)
545                   break;
546
547                 usbbuf[i*2+2] = sys_board_name[i];
548                 usbbuf[i*2+3] = 0;
549               }
550             usbbuf[0] = i*2 + 2;
551             usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
552             size = i*2 + 2;
553           }
554           break;
555         default:
556           return USB_UNSUPPORT;
557         }
558
559       return usb_lld_reply_request (str, size, detail);
560     }
561
562   return USB_UNSUPPORT;
563 }
564
565 static void
566 neug_setup_endpoints_for_interface (uint16_t interface, int stop)
567 {
568   if (interface == 0)
569     {
570 #ifdef FRAUCHEKY_SUPPORT
571       if (running_neug)
572         {
573           if (!stop)
574             usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
575           else
576             usb_lld_stall_tx (ENDP2);
577         }
578       else
579         fraucheky_setup_endpoints_for_interface (stop);
580 #else
581       if (!stop)
582         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
583       else
584         usb_lld_stall_tx (ENDP2);
585 #endif
586     }
587   else if (interface == 1)
588     {
589       if (!stop)
590         {
591           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
592           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
593         }
594       else
595         {
596           usb_lld_stall_tx (ENDP1);
597           usb_lld_stall_rx (ENDP3);
598         }
599     }
600 }
601
602 int usb_cb_handle_event (uint8_t event_type, uint16_t value)
603 {
604   int i;
605   uint8_t current_conf;
606
607   switch (event_type)
608     {
609     case USB_EVENT_ADDRESS:
610       chopstx_mutex_lock (&usb_mtx);
611       bDeviceState = ADDRESSED;
612       chopstx_mutex_unlock (&usb_mtx);
613       return USB_SUCCESS;
614     case USB_EVENT_CONFIG:
615       current_conf = usb_lld_current_configuration ();
616       if (current_conf == 0)
617         {
618           if (value != 1)
619             return USB_UNSUPPORT;
620
621           usb_lld_set_configuration (1);
622           for (i = 0; i < NUM_INTERFACES; i++)
623             neug_setup_endpoints_for_interface (i, 0);
624           chopstx_mutex_lock (&usb_mtx);
625           bDeviceState = CONFIGURED;
626           chopstx_mutex_unlock (&usb_mtx);
627         }
628       else if (current_conf != value)
629         {
630           if (value != 0)
631             return USB_UNSUPPORT;
632
633           usb_lld_set_configuration (0);
634           for (i = 0; i < NUM_INTERFACES; i++)
635             neug_setup_endpoints_for_interface (i, 1);
636           chopstx_mutex_lock (&usb_mtx);
637           bDeviceState = ADDRESSED;
638           chopstx_mutex_unlock (&usb_mtx);
639         }
640       /* Do nothing when current_conf == value */
641       return USB_SUCCESS;
642
643       return USB_SUCCESS;
644     default:
645       break;
646     }
647
648   return USB_UNSUPPORT;
649 }
650
651
652 int usb_cb_interface (uint8_t cmd, struct control_info *detail)
653 {
654   const uint8_t zero = 0;
655   uint16_t interface = detail->index;
656   uint16_t alt = detail->value;
657
658   if (interface >= NUM_INTERFACES)
659     return USB_UNSUPPORT;
660
661   switch (cmd)
662     {
663     case USB_SET_INTERFACE:
664       if (alt != 0)
665         return USB_UNSUPPORT;
666       else
667         {
668           neug_setup_endpoints_for_interface (interface, 0);
669           return USB_SUCCESS;
670         }
671
672     case USB_GET_INTERFACE:
673       usb_lld_reply_request (&zero, 1, detail);
674       return USB_SUCCESS;
675
676     default:
677     case USB_QUERY_INTERFACE:
678       return USB_SUCCESS;
679     }
680 }
681
682 #define INTR_REQ_USB 20
683 #define PRIO_USB 3
684
685 static void *
686 usb_intr (void *arg)
687 {
688   chopstx_intr_t interrupt;
689
690   (void)arg;
691   usb_lld_init (vcom_config_desc[7]);
692   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
693   usb_interrupt_handler ();
694
695   while (1)
696     {
697       chopstx_intr_wait (&interrupt);
698
699       /* Process interrupt. */
700       usb_interrupt_handler ();
701     }
702
703   return NULL;
704 }
705
706 #define ID_OFFSET (2+SERIALNO_STR_LEN*2)
707 static void fill_serial_no_by_unique_id (void)
708 {
709   extern const uint8_t * unique_device_id (void);
710   uint8_t *p = &neug_string_serial[ID_OFFSET];
711   const uint8_t *u = unique_device_id () + 8;
712   int i;
713
714   for (i = 0; i < 4; i++)
715     {
716       uint8_t b = u[3-i];
717       uint8_t nibble; 
718
719       nibble = (b >> 4);
720       nibble += (nibble >= 10 ? ('A' - 10) : '0');
721       p[i*4] = nibble;
722       p[i*4+1] = 0;
723       nibble = (b & 0x0f);
724       nibble += (nibble >= 10 ? ('A' - 10) : '0');
725       p[i*4+2] = nibble;
726       p[i*4+3] = 0;
727     }
728 }
729 \f
730 void
731 EP1_IN_Callback (void)
732 {
733   chopstx_mutex_lock (&usb_mtx);
734   chopstx_cond_signal (&cnd_usb);
735   chopstx_mutex_unlock (&usb_mtx);
736 }
737
738 void
739 EP2_IN_Callback (void)
740 {
741 }
742
743 void
744 EP3_OUT_Callback (void)
745 {
746   usb_lld_rx_enable (ENDP3);
747 }
748 \f
749 typedef uint32_t eventmask_t;
750 #define ALL_EVENTS (~0)
751
752 struct event_flag {
753   chopstx_mutex_t mutex;
754   chopstx_cond_t cond;
755   eventmask_t flag;
756 };
757
758 static void event_flag_init (struct event_flag *ev)
759 {
760   ev->flag = 0;
761   chopstx_mutex_init (&ev->mutex);
762   chopstx_cond_init (&ev->cond);
763 }
764
765
766 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
767 {
768   int n;
769
770   chopstx_mutex_lock (&ev->mutex);
771   while (!(ev->flag & m))
772     chopstx_cond_wait (&ev->cond, &ev->mutex);
773
774   n = __builtin_ffs ((ev->flag & m));
775   ev->flag &= ~(1 << (n - 1));
776   chopstx_mutex_unlock (&ev->mutex);
777
778   return (1 << (n - 1));
779 }
780
781 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
782 {
783   chopstx_mutex_lock (&ev->mutex);
784   ev->flag |= m;
785   chopstx_cond_signal (&ev->cond);
786   chopstx_mutex_unlock (&ev->mutex);
787 }
788
789 extern uint8_t __process1_stack_base__, __process1_stack_size__;
790 extern uint8_t __process3_stack_base__, __process3_stack_size__;
791
792 const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
793 const size_t __stacksize_led = (size_t)&__process1_stack_size__;
794 const uint32_t __stackaddr_usb = (uint32_t)&__process3_stack_base__;
795 const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
796
797
798 #define PRIO_LED 3
799 static struct event_flag led_event;
800
801 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
802 #define LED_TWOSHOTS            ((eventmask_t)2)
803 #define LED_ONESHOT_LONG        ((eventmask_t)4)
804
805 /*
806  * LED blinker: When notified, let LED emit for 100ms.
807  */
808 static void *
809 led_blinker (void *arg)
810 {
811   (void)arg;
812
813   set_led (0);
814
815   while (1)
816     {
817       eventmask_t m;
818
819       m = event_flag_waitone (&led_event, ALL_EVENTS);
820       if (fsij_device_state != FSIJ_DEVICE_RUNNING) /* No usb_mtx lock.  */
821         break;
822
823       set_led (1);
824       if (m == LED_ONESHOT_SHORT)
825         chopstx_usec_wait (100*1000);
826       else if (m == LED_TWOSHOTS)
827         {
828           chopstx_usec_wait (50*1000);
829           set_led (0);
830           chopstx_usec_wait (50*1000);
831           set_led (1);
832           chopstx_usec_wait (50*1000);
833         }
834       else
835         chopstx_usec_wait (250*1000);
836       set_led (0);
837     }
838
839   return NULL;
840 }
841 \f
842 #define RANDOM_BYTES_LENGTH 64
843 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
844
845 static void copy_to_tx (uint32_t v, int i)
846 {
847   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
848 }
849
850 /*
851  * In Gnuk 1.0.[12], reGNUal was not relocatable.
852  * Now, it's relocatable, but we need to calculate its entry address
853  * based on it's pre-defined address.
854  */
855 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
856 static uint32_t
857 calculate_regnual_entry_address (const uint8_t *addr)
858 {
859   const uint8_t *p = addr + 4;
860   uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
861
862   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
863   v += (uint32_t)addr;
864   return v;
865 }
866
867
868 /*
869  * Entry point.
870  *
871  * NOTE: the main function is already a thread in the system on entry.
872  */
873 int
874 main (int argc, char **argv)
875 {
876   uint32_t entry;
877   chopstx_t led_thread, usb_thd;
878   unsigned int count;
879
880   (void)argc;
881   (void)argv;
882
883   fill_serial_no_by_unique_id ();
884
885   adc_init ();
886
887   event_flag_init (&led_event);
888   
889   chopstx_mutex_init (&usb_mtx);
890   chopstx_cond_init (&cnd_usb);
891
892   led_thread = chopstx_create (PRIO_LED, __stackaddr_led, __stacksize_led,
893                                led_blinker, NULL);
894
895 #ifdef FRAUCHEKY_SUPPORT
896   if (fraucheky_enabled ())
897     {
898       usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
899                                 usb_intr, NULL);
900       fraucheky_main ();
901       chopstx_cancel (usb_thd);
902       chopstx_join (usb_thd, NULL);
903       usb_lld_shutdown ();
904     }
905
906   running_neug = 1;
907 #endif
908
909   usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
910                             usb_intr, NULL);
911
912   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
913
914   chopstx_mutex_lock (&usb_mtx);
915
916  not_configured:
917   count = 0;
918   /* A run-up */
919   while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
920     {
921       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
922         break;
923
924       chopstx_mutex_unlock (&usb_mtx);
925       neug_wait_full ();
926       neug_flush ();
927
928       if ((count & 0x0007) == 0)
929         event_flag_signal (&led_event, LED_ONESHOT_SHORT);
930       chopstx_usec_wait (25*1000);
931       count++;
932       chopstx_mutex_lock (&usb_mtx);
933     }
934
935   /* Holding USB_MTX.  */
936   while (1)
937     {
938       int last_was_fullsizepacket = 0;
939
940       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
941         break;
942
943       while (1)
944         {
945           wait_usb_connection = 5000*1000;
946           if (connected || bDeviceState != CONFIGURED
947               || fsij_device_state != FSIJ_DEVICE_RUNNING)
948             break;
949
950           chopstx_mutex_unlock (&usb_mtx);
951           neug_flush ();
952           neug_mode_select (line_coding.paritytype);
953           event_flag_signal (&led_event, LED_TWOSHOTS);
954           chopstx_usec_wait_var (&wait_usb_connection);
955           chopstx_mutex_lock (&usb_mtx);
956         }
957
958       if (bDeviceState != CONFIGURED)
959         goto not_configured;
960
961       /* The connection opened.  */
962       count = 0;
963
964       while (1)
965         {
966           int i;
967
968           chopstx_mutex_unlock (&usb_mtx);
969           /*
970            * No parity is standard.  It means providing conditioned output.
971            * When parity enabled, it means to provide raw output
972            * (CRC32 filtered when odd, direct sample of ADC when even).
973            *
974            * line_coding.paritytype:
975            *   0: None, 1: Odd, 2: Even
976            */
977           neug_mode_select (line_coding.paritytype);
978
979           if ((count & 0x03ff) == 0)
980             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
981
982           i = neug_consume_random (copy_to_tx);
983
984           if (i == 0 && !last_was_fullsizepacket)
985             {    /* Only send ZLP when the last packet was fullsize.  */
986               neug_wait_full ();
987
988               chopstx_mutex_lock (&usb_mtx);
989               if (bDeviceState != CONFIGURED || !connected
990                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
991                 break;
992             }
993           else
994             {
995               if (i == 64/4)
996                 last_was_fullsizepacket = 1;
997               else
998                 last_was_fullsizepacket = 0;
999
1000               chopstx_mutex_lock (&usb_mtx);
1001               if (bDeviceState != CONFIGURED || !connected
1002                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1003                 break;
1004
1005               /* Prepare sending random data.  */
1006               usb_lld_tx_enable (ENDP1, i * 4);
1007               chopstx_cond_wait (&cnd_usb, &usb_mtx);
1008               count++;
1009             }
1010         }
1011     }
1012
1013   chopstx_mutex_unlock (&usb_mtx);
1014
1015   chopstx_cancel (led_thread);
1016   chopstx_join (led_thread, NULL);
1017
1018   /*
1019    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED.
1020    */
1021   neug_fini ();
1022
1023   chopstx_mutex_lock (&usb_mtx);
1024   fsij_device_state = FSIJ_DEVICE_EXITED;
1025
1026   while (fsij_device_state == FSIJ_DEVICE_EXITED)
1027     {
1028       chopstx_mutex_unlock (&usb_mtx);
1029       chopstx_usec_wait (500*1000);
1030       chopstx_mutex_lock (&usb_mtx);
1031     }
1032   chopstx_mutex_unlock (&usb_mtx);
1033
1034   flash_unlock ();              /* Flash unlock should be done here */
1035   set_led (1);
1036   usb_lld_shutdown ();
1037
1038   /* Finish application.  */
1039   chopstx_cancel (usb_thd);
1040   chopstx_join (usb_thd, NULL);
1041
1042   /* Set vector */
1043   SCB->VTOR = (uint32_t)&_regnual_start;
1044   entry = calculate_regnual_entry_address (&_regnual_start);
1045 #ifdef DFU_SUPPORT
1046 #define FLASH_SYS_START_ADDR 0x08000000
1047 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
1048 #define CHIP_ID_REG ((uint32_t *)0xE0042000)
1049   {
1050     extern uint8_t _sys;
1051     uint32_t addr;
1052     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
1053     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
1054     uint32_t flash_page_size = 1024; /* 1KiB default */
1055
1056    if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device.  */
1057      flash_page_size += 0x0400; /* It's 2KiB. */
1058
1059     /* Kill DFU */
1060     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
1061          addr += flash_page_size)
1062       flash_erase_page (addr);
1063
1064     /* copy system service routines */
1065     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
1066
1067     /* Leave NeuG to exec reGNUal */
1068     (*func) ((void (*)(void))entry);
1069     for (;;);
1070   }
1071 #else
1072   /* Leave NeuG to exec reGNUal */
1073   flash_erase_all_and_exec ((void (*)(void))entry);
1074 #endif
1075
1076   /* Never reached */
1077   return 0;
1078 }