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