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