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