More fixes for new Chopstx and Fraucheky
[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 (uint16_t len);
51 extern void EP6_OUT_Callback (uint16_t len);
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 #define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
188 extern int fraucheky_enabled (void);
189 extern void fraucheky_main (void);
190
191 extern void fraucheky_setup_endpoints_for_interface (int stop);
192 extern int fraucheky_setup (struct usb_dev *dev);
193 extern int fraucheky_get_descriptor (struct usb_dev *dev);
194 #endif
195
196 #define NUM_INTERFACES 2
197
198 static void
199 usb_device_reset (struct usb_dev *dev)
200 {
201   int i;
202
203   usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
204
205   /* Initialize Endpoint 0.  */
206   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
207
208   /* Stop the interface */
209   for (i = 0; i < NUM_INTERFACES; i++)
210     neug_setup_endpoints_for_interface (i, 1);
211
212   /* Notify upper layer.  */
213   chopstx_mutex_lock (&usb_mtx);
214   bDeviceState = ATTACHED;
215   connected = 0;
216   chopstx_cond_signal (&usb_cnd);
217   chopstx_mutex_unlock (&usb_mtx);
218 }
219
220 extern uint8_t _regnual_start, __heap_end__;
221
222 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
223
224 /* USB vendor requests to control pipe */
225 #define USB_FSIJ_MEMINFO          0
226 #define USB_FSIJ_DOWNLOAD         1
227 #define USB_FSIJ_EXEC             2
228 #define USB_NEUG_SET_PASSWD     253
229 #define USB_NEUG_GET_INFO       254
230 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
231
232 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
233   0xff,
234   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
235   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
236   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
237 };
238 static uint8_t usbbuf[64];
239
240 #define DEFAULT_PASSWD "12345678"
241 #define DEFAULT_PASSWD_LEN 8
242
243 static void set_passwd (void)
244 {
245   flash_unlock ();
246   if (neug_passwd[0] != 0xff)
247     flash_erase_page ((uint32_t)neug_passwd);
248   if (usbbuf[0] == DEFAULT_PASSWD_LEN
249       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
250     return;
251   flash_write ((uint32_t)neug_passwd, usbbuf, usbbuf[0] + 1);
252 }
253
254 static uint32_t rbit (uint32_t v)
255 {
256   uint32_t r;
257
258   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
259   return r;
260 }
261
262 /* After calling this function, CRC module remain enabled.  */
263 static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
264 {
265   uint32_t crc32 = *end_p;
266   const uint32_t *p;
267
268   RCC->AHBENR |= RCC_AHBENR_CRCEN;
269   CRC->CR = CRC_CR_RESET;
270
271   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
272     CRC->DR = rbit (*p);
273
274   if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
275     return usb_lld_ctrl_ack (dev);
276
277   return -1;
278 }
279
280
281 #define NEUG_SPECIAL_BITRATE 110
282
283 struct line_coding
284 {
285   uint32_t bitrate;
286   uint8_t format;
287   uint8_t paritytype;
288   uint8_t datatype;
289 } __attribute__((packed));
290
291 static struct line_coding line_coding = {
292   115200, /* baud rate: 115200    */
293   0x00,   /* stop bits: 1         */
294   0x00,   /* parity:    none      */
295   0x08    /* bits:      8         */
296 };
297
298 #define CDC_CTRL_DTR            0x0001
299
300 static void
301 usb_ctrl_write_finish (struct usb_dev *dev)
302 {
303   struct device_req *arg = &dev->dev_req;
304   uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
305
306   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
307       && USB_SETUP_SET (arg->type))
308     {
309       if (arg->request == 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 (arg->request == USB_NEUG_SET_PASSWD)
320         set_passwd ();
321       else if (arg->request == 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 (arg->type))
337     {
338       if (arg->request == 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 (running_neug && arg->request == 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       else if (!running_neug && arg->request == MSC_MASS_STORAGE_RESET_COMMAND)
360         fraucheky_setup_endpoints_for_interface (0);
361 #endif
362     }
363 }
364
365
366 static int
367 vcom_port_data_setup (struct usb_dev *dev)
368 {
369   struct device_req *arg = &dev->dev_req;
370
371   if (USB_SETUP_GET (arg->type))
372     {
373       if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
374         return usb_lld_ctrl_send (dev, &line_coding, sizeof(line_coding));
375     }
376   else  /* USB_SETUP_SET (req) */
377     {
378       if (arg->request == USB_CDC_REQ_SET_LINE_CODING
379           && arg->len == sizeof (line_coding))
380         return usb_lld_ctrl_recv (dev, &line_coding, sizeof (line_coding));
381       else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
382         return usb_lld_ctrl_ack (dev);
383     }
384
385   return -1;
386 }
387
388 static int
389 usb_setup (struct usb_dev *dev)
390 {
391   struct device_req *arg = &dev->dev_req;
392   uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
393
394   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
395     {
396       if (USB_SETUP_GET (arg->type))
397         {
398           if (arg->request == USB_FSIJ_MEMINFO)
399             {
400               chopstx_mutex_lock (&usb_mtx);
401               if (fsij_device_state != FSIJ_DEVICE_EXITED)
402                 {
403                   chopstx_mutex_unlock (&usb_mtx);
404                   return -1;
405                 }
406               chopstx_mutex_unlock (&usb_mtx);
407               return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
408             }
409           else if (arg->request == USB_NEUG_GET_INFO)
410             {
411               if (arg->index == 0)
412                 return usb_lld_ctrl_send (dev, &neug_mode, sizeof (uint8_t));
413               else if (arg->index == 1)
414                 return usb_lld_ctrl_send (dev, &neug_err_cnt, sizeof (uint16_t));
415               else if (arg->index == 2)
416                 return usb_lld_ctrl_send (dev, &neug_err_cnt_rc, sizeof (uint16_t));
417               else if (arg->index == 3)
418                 return usb_lld_ctrl_send (dev, &neug_err_cnt_p64, sizeof (uint16_t));
419               else if (arg->index == 4)
420                 return usb_lld_ctrl_send (dev, &neug_err_cnt_p4k, sizeof (uint16_t));
421               else if (arg->index == 5)
422                 return usb_lld_ctrl_send (dev, &neug_rc_max, sizeof (uint16_t));
423               else if (arg->index == 6)
424                 return usb_lld_ctrl_send (dev, &neug_p64_max, sizeof (uint16_t));
425               else if (arg->index == 7)
426                 return usb_lld_ctrl_send (dev, &neug_p4k_max, sizeof (uint16_t));
427               else
428                 return -1;
429             }
430         }
431       else /* SETUP_SET */
432         {
433           uint8_t *addr = (uint8_t *)(0x20000000 + arg->value * 0x100 + arg->index);
434
435           if (arg->request == USB_FSIJ_DOWNLOAD)
436             {
437               chopstx_mutex_lock (&usb_mtx);
438               if (fsij_device_state != FSIJ_DEVICE_EXITED)
439                 {
440                   chopstx_mutex_unlock (&usb_mtx);
441                   return -1;
442                 }
443               chopstx_mutex_unlock (&usb_mtx);
444
445               if (addr < &_regnual_start || addr + arg->len > &__heap_end__)
446                 return -1;
447
448               if (arg->index + arg->len < 256)
449                 memset (addr + arg->index + arg->len, 0, 256 - (arg->index + arg->len));
450
451               return usb_lld_ctrl_recv (dev, addr, arg->len);
452             }
453           else if (arg->request == USB_FSIJ_EXEC && arg->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 -1;
460                 }
461               chopstx_mutex_unlock (&usb_mtx);
462
463               if (((uint32_t)addr & 0x03))
464                 return -1;
465
466               return download_check_crc32 (dev, (uint32_t *)addr);
467             }
468           else if (arg->request == USB_NEUG_SET_PASSWD && arg->len <= 32)
469             {
470               usbbuf[0] = arg->len;
471               return usb_lld_ctrl_recv (dev, usbbuf + 1, arg->len);
472             }
473           else if (arg->request == USB_NEUG_EXIT && arg->len <= 32)
474             {
475               chopstx_mutex_lock (&usb_mtx);
476               if (fsij_device_state != FSIJ_DEVICE_RUNNING)
477                 {
478                   chopstx_mutex_unlock (&usb_mtx);
479                   return -1;
480                 }
481               chopstx_mutex_unlock (&usb_mtx);
482
483               usbbuf[0] = arg->len;
484               return usb_lld_ctrl_recv (dev, usbbuf + 1, arg->len);
485             }
486         }
487     }
488   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
489            && arg->index == 0)
490     {
491 #ifdef FRAUCHEKY_SUPPORT
492       if (running_neug)
493         return vcom_port_data_setup (dev);
494       else
495         return fraucheky_setup (dev);
496 #else
497       return vcom_port_data_setup (dev);
498 #endif
499     }
500
501   return -1;
502 }
503
504 static int
505 usb_get_descriptor (struct usb_dev *dev)
506 {
507   struct device_req *arg = &dev->dev_req;
508   uint8_t rcp = arg->type & RECIPIENT;
509   uint8_t desc_type = (arg->value >> 8);
510   uint8_t desc_index = (arg->value & 0xff);
511
512 #ifdef FRAUCHEKY_SUPPORT
513   if (!running_neug)
514     return fraucheky_get_descriptor (dev);
515 #endif
516
517   if (rcp != DEVICE_RECIPIENT)
518     return -1;
519
520   if (desc_type == DEVICE_DESCRIPTOR)
521     return usb_lld_ctrl_send (dev,
522                               vcom_device_desc, sizeof (vcom_device_desc));
523   else if (desc_type == CONFIG_DESCRIPTOR)
524     return usb_lld_ctrl_send (dev,
525                               vcom_config_desc, sizeof (vcom_config_desc));
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 -1;
582         }
583
584       return usb_lld_ctrl_send (dev, str, size);
585     }
586
587   return -1;
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 static int
629 usb_set_configuration (struct usb_dev *dev)
630 {
631   int i;
632   uint8_t current_conf;
633
634   current_conf = usb_lld_current_configuration (dev);
635   if (current_conf == 0)
636     {
637       if (dev->dev_req.value != 1)
638         return -1;
639
640       usb_lld_set_configuration (dev, 1);
641       for (i = 0; i < NUM_INTERFACES; i++)
642         neug_setup_endpoints_for_interface (i, 0);
643       chopstx_mutex_lock (&usb_mtx);
644       bDeviceState = CONFIGURED;
645       chopstx_mutex_unlock (&usb_mtx);
646     }
647   else if (current_conf != dev->dev_req.value)
648     {
649       if (dev->dev_req.value != 0)
650         return -1;
651
652       usb_lld_set_configuration (dev, 0);
653       for (i = 0; i < NUM_INTERFACES; i++)
654         neug_setup_endpoints_for_interface (i, 1);
655       chopstx_mutex_lock (&usb_mtx);
656       bDeviceState = ADDRESSED;
657       chopstx_cond_signal (&usb_cnd);
658       chopstx_mutex_unlock (&usb_mtx);
659     }
660
661   /* Do nothing when current_conf == value */
662   usb_lld_ctrl_ack (dev);
663   return 0;
664 }
665
666
667 static int
668 usb_set_interface (struct usb_dev *dev)
669 {
670   uint16_t interface = dev->dev_req.index;
671   uint16_t alt = dev->dev_req.value;
672
673   if (interface >= NUM_INTERFACES)
674     return -1;
675
676   if (alt != 0)
677     return -1;
678   else
679     {
680       neug_setup_endpoints_for_interface (interface, 0);
681       usb_lld_ctrl_ack (dev);
682       return 0;
683     }
684 }
685
686 static int
687 usb_get_interface (struct usb_dev *dev)
688 {
689   const uint8_t zero = 0;
690   uint16_t interface = dev->dev_req.index;
691
692   if (interface >= NUM_INTERFACES)
693     return -1;
694
695   return usb_lld_ctrl_send (dev, &zero, 1);
696 }
697
698
699 static int
700 usb_get_status_interface (struct usb_dev *dev)
701 {
702   const uint16_t status_info = 0;
703   uint16_t interface = dev->dev_req.index;
704
705   if (interface >= NUM_INTERFACES)
706     return -1;
707
708   return usb_lld_ctrl_send (dev, &status_info, 2);
709 }
710
711 static void usb_tx_done (uint8_t ep_num, uint16_t len);
712 static void usb_rx_ready (uint8_t ep_num, uint16_t len);
713
714
715 #define INTR_REQ_USB 20
716 #define PRIO_USB 3
717
718 static void *
719 usb_main (void *arg)
720 {
721   chopstx_intr_t interrupt;
722   struct usb_dev dev;
723   int e;
724
725   (void)arg;
726   usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
727   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
728   goto event_handle;    /* For old SYS < 3.0 */
729
730   while (1)
731     {
732       chopstx_poll (NULL, 1, &interrupt);
733
734       if (interrupt.ready)
735         {
736           uint8_t ep_num;
737
738         event_handle:
739           e = usb_lld_event_handler (&dev);
740           ep_num = USB_EVENT_ENDP (e);
741
742           if (ep_num != 0)
743             {
744               if (USB_EVENT_TXRX (e))
745                 usb_tx_done (ep_num, USB_EVENT_LEN (e));
746               else
747                 usb_rx_ready (ep_num, USB_EVENT_LEN (e));
748             }
749           else
750             switch (USB_EVENT_ID (e))
751               {
752               case USB_EVENT_DEVICE_RESET:
753                 usb_device_reset (&dev);
754                 continue;
755
756               case USB_EVENT_DEVICE_ADDRESSED:
757                 chopstx_mutex_lock (&usb_mtx);
758                 bDeviceState = ADDRESSED;
759                 chopstx_cond_signal (&usb_cnd);
760                 chopstx_mutex_unlock (&usb_mtx);
761                 continue;
762
763               case USB_EVENT_GET_DESCRIPTOR:
764                 if (usb_get_descriptor (&dev) < 0)
765                   usb_lld_ctrl_error (&dev);
766                 continue;
767
768               case USB_EVENT_SET_CONFIGURATION:
769                 if (usb_set_configuration (&dev) < 0)
770                   usb_lld_ctrl_error (&dev);
771                 continue;
772
773               case USB_EVENT_SET_INTERFACE:
774                 if (usb_set_interface (&dev) < 0)
775                   usb_lld_ctrl_error (&dev);
776                 continue;
777
778               case USB_EVENT_CTRL_REQUEST:
779                 /* Device specific device request.  */
780                 if (usb_setup (&dev) < 0)
781                   usb_lld_ctrl_error (&dev);
782                 continue;
783
784               case USB_EVENT_GET_STATUS_INTERFACE:
785                 if (usb_get_status_interface (&dev) < 0)
786                   usb_lld_ctrl_error (&dev);
787                 continue;
788
789               case USB_EVENT_GET_INTERFACE:
790                 if (usb_get_interface (&dev) < 0)
791                   usb_lld_ctrl_error (&dev);
792                 continue;
793
794               case USB_EVENT_SET_FEATURE_DEVICE:
795               case USB_EVENT_SET_FEATURE_ENDPOINT:
796               case USB_EVENT_CLEAR_FEATURE_DEVICE:
797               case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
798                 usb_lld_ctrl_ack (&dev);
799                 continue;
800
801               case USB_EVENT_CTRL_WRITE_FINISH:
802                 /* Control WRITE transfer finished.  */
803                 usb_ctrl_write_finish (&dev);
804                 continue;
805
806               case USB_EVENT_OK:
807               case USB_EVENT_DEVICE_SUSPEND:
808               default:
809                 continue;
810               }
811         }
812     }
813
814   return NULL;
815 }
816
817 #define ID_OFFSET (2+SERIALNO_STR_LEN*2)
818 static void fill_serial_no_by_unique_id (void)
819 {
820   extern const uint8_t * unique_device_id (void);
821   uint8_t *p = &neug_string_serial[ID_OFFSET];
822   const uint8_t *u = unique_device_id () + 8;
823   int i;
824
825   for (i = 0; i < 4; i++)
826     {
827       uint8_t b = u[3-i];
828       uint8_t nibble;
829
830       nibble = (b >> 4);
831       nibble += (nibble >= 10 ? ('A' - 10) : '0');
832       p[i*4] = nibble;
833       p[i*4+1] = 0;
834       nibble = (b & 0x0f);
835       nibble += (nibble >= 10 ? ('A' - 10) : '0');
836       p[i*4+2] = nibble;
837       p[i*4+3] = 0;
838     }
839 }
840
841
842 static void
843 usb_tx_done (uint8_t ep_num, uint16_t len)
844 {
845   if (ep_num == ENDP1)
846     {
847       chopstx_mutex_lock (&usb_mtx);
848       chopstx_cond_signal (&usb_cnd);
849       chopstx_mutex_unlock (&usb_mtx);
850     }
851   else if (ep_num == ENDP2)
852     {
853       /* INTERRUPT Transfer done */
854     }
855 #ifdef FRAUCHEKY_SUPPORT
856   else if (ep_num == ENDP6)
857     EP6_IN_Callback (len);
858 #else
859   (void)len;
860 #endif
861 }
862
863 static void
864 usb_rx_ready (uint8_t ep_num, uint16_t len)
865 {
866   if (ep_num == ENDP3)
867     usb_lld_rx_enable (ENDP3);
868 #ifdef FRAUCHEKY_SUPPORT
869   else if (ep_num == ENDP6)
870     EP6_OUT_Callback (len);
871 #else
872   (void)len;
873 #endif
874 }
875 \f
876 typedef uint32_t eventmask_t;
877 #define ALL_EVENTS (~0)
878
879 struct event_flag {
880   chopstx_mutex_t mutex;
881   chopstx_cond_t cond;
882   eventmask_t flag;
883 };
884
885 static void event_flag_init (struct event_flag *ev)
886 {
887   ev->flag = 0;
888   chopstx_mutex_init (&ev->mutex);
889   chopstx_cond_init (&ev->cond);
890 }
891
892
893 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
894 {
895   int n;
896
897   chopstx_mutex_lock (&ev->mutex);
898   while (!(ev->flag & m))
899     chopstx_cond_wait (&ev->cond, &ev->mutex);
900
901   n = __builtin_ffs ((ev->flag & m));
902   ev->flag &= ~(1 << (n - 1));
903   chopstx_mutex_unlock (&ev->mutex);
904
905   return (1 << (n - 1));
906 }
907
908 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
909 {
910   chopstx_mutex_lock (&ev->mutex);
911   ev->flag |= m;
912   chopstx_cond_signal (&ev->cond);
913   chopstx_mutex_unlock (&ev->mutex);
914 }
915
916 extern uint8_t __process1_stack_base__, __process1_stack_size__;
917 extern uint8_t __process3_stack_base__, __process3_stack_size__;
918
919 const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
920 const size_t __stacksize_led = (size_t)&__process1_stack_size__;
921 const uint32_t __stackaddr_usb = (uint32_t)&__process3_stack_base__;
922 const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
923
924
925 #define PRIO_LED 3
926 static struct event_flag led_event;
927
928 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
929 #define LED_TWOSHOTS            ((eventmask_t)2)
930 #define LED_ONESHOT_LONG        ((eventmask_t)4)
931
932 /*
933  * LED blinker: When notified, let LED emit for 100ms.
934  */
935 static void *
936 led_blinker (void *arg)
937 {
938   (void)arg;
939
940   set_led (0);
941
942   while (1)
943     {
944       eventmask_t m;
945
946       m = event_flag_waitone (&led_event, ALL_EVENTS);
947
948       set_led (1);
949       if (m == LED_ONESHOT_SHORT)
950         chopstx_usec_wait (100*1000);
951       else if (m == LED_TWOSHOTS)
952         {
953           chopstx_usec_wait (50*1000);
954           set_led (0);
955           chopstx_usec_wait (50*1000);
956           set_led (1);
957           chopstx_usec_wait (50*1000);
958         }
959       else
960         chopstx_usec_wait (250*1000);
961       set_led (0);
962     }
963
964   return NULL;
965 }
966 \f
967 #define RANDOM_BYTES_LENGTH 64
968 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
969
970 static void copy_to_tx (uint32_t v, int i)
971 {
972   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
973 }
974
975 /*
976  * In Gnuk 1.0.[12], reGNUal was not relocatable.
977  * Now, it's relocatable, but we need to calculate its entry address
978  * based on it's pre-defined address.
979  */
980 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
981 static uint32_t
982 calculate_regnual_entry_address (const uint8_t *addr)
983 {
984   const uint8_t *p = addr + 4;
985   uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
986
987   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
988   v += (uint32_t)addr;
989   return v;
990 }
991
992
993 static int
994 check_usb_status (void *arg)
995 {
996   (void)arg;
997
998   return (connected || bDeviceState != CONFIGURED
999           || fsij_device_state != FSIJ_DEVICE_RUNNING);
1000 }
1001
1002 /*
1003  * Entry point.
1004  *
1005  * NOTE: the main function is already a thread in the system on entry.
1006  */
1007 int
1008 main (int argc, char **argv)
1009 {
1010   uint32_t entry;
1011   chopstx_t led_thread, usb_thd;
1012   unsigned int count;
1013
1014   (void)argc;
1015   (void)argv;
1016
1017   fill_serial_no_by_unique_id ();
1018
1019   adc_init ();
1020
1021   event_flag_init (&led_event);
1022
1023   chopstx_mutex_init (&usb_mtx);
1024   chopstx_cond_init (&usb_cnd);
1025
1026 #ifdef FRAUCHEKY_SUPPORT
1027   if (fraucheky_enabled ())
1028     {
1029     go_fraucheky:
1030       bDeviceState = UNCONNECTED;
1031       running_neug = 0;
1032       usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
1033                                 usb_main, NULL);
1034       while (bDeviceState != CONFIGURED)
1035         chopstx_usec_wait (250*1000);
1036       set_led (1);
1037       fraucheky_main ();
1038       chopstx_cancel (usb_thd);
1039       chopstx_join (usb_thd, NULL);
1040       usb_lld_shutdown ();
1041       bDeviceState = UNCONNECTED;
1042     }
1043
1044   running_neug = 1;
1045 #endif
1046
1047   led_thread = chopstx_create (PRIO_LED, __stackaddr_led, __stacksize_led,
1048                                led_blinker, NULL);
1049
1050   usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
1051                             usb_main, NULL);
1052
1053   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
1054
1055   chopstx_mutex_lock (&usb_mtx);
1056
1057  not_configured:
1058   count = 0;
1059   /* Initial run-up */
1060   while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
1061     {
1062       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
1063         break;
1064
1065       chopstx_mutex_unlock (&usb_mtx);
1066       neug_wait_full ();
1067       neug_flush ();
1068
1069       if ((count & 0x0007) == 0)
1070         event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1071       chopstx_usec_wait (25*1000);
1072       count++;
1073       chopstx_mutex_lock (&usb_mtx);
1074     }
1075
1076   /* Holding USB_MTX...  */
1077   while (1)
1078     {
1079       int last_was_fullsizepacket = 0;
1080
1081       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
1082         break;
1083
1084       chopstx_mutex_unlock (&usb_mtx);
1085       while (1)
1086         {
1087           chopstx_poll_cond_t poll_desc;
1088           uint32_t usec = 5000*1000;
1089
1090           poll_desc.type = CHOPSTX_POLL_COND;
1091           poll_desc.ready = 0;
1092           poll_desc.cond = &usb_cnd;
1093           poll_desc.mutex = &usb_mtx;
1094           poll_desc.check = check_usb_status;
1095           poll_desc.arg = NULL;
1096
1097           if (chopstx_poll (&usec, 1, &poll_desc))
1098             break;
1099
1100           /* Timeout */
1101           neug_flush ();
1102           neug_mode_select (line_coding.paritytype);
1103           event_flag_signal (&led_event, LED_TWOSHOTS);
1104         }
1105
1106       chopstx_mutex_lock (&usb_mtx);
1107       if (bDeviceState != CONFIGURED)
1108         goto not_configured;
1109
1110       /* The connection opened.  */
1111       count = 0;
1112
1113       while (1)
1114         {
1115           int i;
1116
1117           chopstx_mutex_unlock (&usb_mtx);
1118           /*
1119            * No parity is standard.  It means providing conditioned output.
1120            * When parity enabled, it means to provide raw output
1121            * (CRC32 filtered when odd, direct sample of ADC when even).
1122            *
1123            * line_coding.paritytype:
1124            *   0: None, 1: Odd, 2: Even
1125            */
1126           neug_mode_select (line_coding.paritytype);
1127
1128           if ((count & 0x03ff) == 0)
1129             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1130
1131           i = neug_consume_random (copy_to_tx);
1132
1133           if (i == 0 && !last_was_fullsizepacket)
1134             {    /* Only send ZLP when the last packet was fullsize.  */
1135               neug_wait_full ();
1136
1137               chopstx_mutex_lock (&usb_mtx);
1138               if (bDeviceState != CONFIGURED || !connected
1139                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1140                 break;
1141             }
1142           else
1143             {
1144               if (i == 64/4)
1145                 last_was_fullsizepacket = 1;
1146               else
1147                 last_was_fullsizepacket = 0;
1148
1149               chopstx_mutex_lock (&usb_mtx);
1150               if (bDeviceState != CONFIGURED || !connected
1151                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1152                 break;
1153
1154               /* Prepare sending random data.  */
1155               usb_lld_tx_enable (ENDP1, i * 4);
1156               chopstx_cond_wait (&usb_cnd, &usb_mtx);
1157               count++;
1158             }
1159         }
1160     }
1161
1162   chopstx_mutex_unlock (&usb_mtx);
1163
1164   chopstx_cancel (led_thread);
1165   chopstx_join (led_thread, NULL);
1166
1167   /*
1168    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED
1169    * or FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED.
1170    */
1171   neug_fini ();
1172
1173   chopstx_mutex_lock (&usb_mtx);
1174 #ifdef FRAUCHEKY_SUPPORT
1175   if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
1176     {
1177       while (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
1178         {
1179           chopstx_mutex_unlock (&usb_mtx);
1180           set_led (1);
1181           chopstx_usec_wait (500*1000);
1182           set_led (0);
1183           chopstx_usec_wait (500*1000);
1184           chopstx_mutex_lock (&usb_mtx);
1185         }
1186
1187       usb_lld_prepare_shutdown ();
1188       chopstx_mutex_unlock (&usb_mtx);
1189       chopstx_cancel (usb_thd);
1190       chopstx_join (usb_thd, NULL);
1191       usb_lld_shutdown ();
1192       goto go_fraucheky;
1193     }
1194 #endif
1195
1196   fsij_device_state = FSIJ_DEVICE_EXITED;
1197
1198   while (fsij_device_state == FSIJ_DEVICE_EXITED)
1199     {
1200       chopstx_mutex_unlock (&usb_mtx);
1201       chopstx_usec_wait (500*1000);
1202       chopstx_mutex_lock (&usb_mtx);
1203     }
1204   chopstx_mutex_unlock (&usb_mtx);
1205
1206   flash_unlock ();              /* Flash unlock should be done here */
1207   set_led (1);
1208   usb_lld_shutdown ();
1209
1210   /* Finish application.  */
1211   chopstx_cancel (usb_thd);
1212   chopstx_join (usb_thd, NULL);
1213
1214   /* Set vector */
1215   SCB->VTOR = (uint32_t)&_regnual_start;
1216   entry = calculate_regnual_entry_address (&_regnual_start);
1217 #ifdef DFU_SUPPORT
1218 #define FLASH_SYS_START_ADDR 0x08000000
1219 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
1220 #define CHIP_ID_REG ((uint32_t *)0xE0042000)
1221   {
1222     extern uint8_t _sys;
1223     uint32_t addr;
1224     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
1225     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
1226     uint32_t flash_page_size = 1024; /* 1KiB default */
1227
1228    if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device.  */
1229      flash_page_size += 0x0400; /* It's 2KiB. */
1230
1231     /* Kill DFU */
1232     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
1233          addr += flash_page_size)
1234       flash_erase_page (addr);
1235
1236     /* copy system service routines */
1237     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
1238
1239     /* Leave NeuG to exec reGNUal */
1240     (*func) ((void (*)(void))entry);
1241     for (;;);
1242   }
1243 #else
1244   /* Leave NeuG to exec reGNUal */
1245   flash_erase_all_and_exec ((void (*)(void))entry);
1246 #endif
1247
1248   /* Never reached */
1249   return 0;
1250 }