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