Update SYS&USB API
[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 "mcu/sys-stm32f103.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         case 7:
562           {
563             int i;
564             str = usbbuf;
565             for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
566               {
567                 if (sys_board_name[i] == 0)
568                   break;
569
570                 usbbuf[i*2+2] = sys_board_name[i];
571                 usbbuf[i*2+3] = 0;
572               }
573             usbbuf[0] = i*2 + 2;
574             usbbuf[1] = STRING_DESCRIPTOR;
575             size = i*2 + 2;
576           }
577           break;
578         default:
579           return USB_UNSUPPORT;
580         }
581
582       return usb_lld_reply_request (str, size, arg);
583     }
584
585   return USB_UNSUPPORT;
586 }
587
588 static void
589 neug_setup_endpoints_for_interface (uint16_t interface, int stop)
590 {
591   if (interface == 0)
592     {
593 #ifdef FRAUCHEKY_SUPPORT
594       if (running_neug)
595         {
596           if (!stop)
597             usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
598           else
599             usb_lld_stall_tx (ENDP2);
600         }
601       else
602         fraucheky_setup_endpoints_for_interface (stop);
603 #else
604       if (!stop)
605         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
606       else
607         usb_lld_stall_tx (ENDP2);
608 #endif
609     }
610   else if (interface == 1)
611     {
612       if (!stop)
613         {
614           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
615           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
616           /* Start with no data receiving (ENDP3 not enabled) */
617         }
618       else
619         {
620           usb_lld_stall_tx (ENDP1);
621           usb_lld_stall_rx (ENDP3);
622         }
623     }
624 }
625
626 int usb_cb_handle_event (uint8_t event_type, uint16_t value)
627 {
628   int i;
629   uint8_t current_conf;
630
631   switch (event_type)
632     {
633     case USB_EVENT_ADDRESS:
634       chopstx_mutex_lock (&usb_mtx);
635       bDeviceState = ADDRESSED;
636       chopstx_mutex_unlock (&usb_mtx);
637       return USB_SUCCESS;
638     case USB_EVENT_CONFIG:
639       current_conf = usb_lld_current_configuration ();
640       if (current_conf == 0)
641         {
642           if (value != 1)
643             return USB_UNSUPPORT;
644
645           usb_lld_set_configuration (1);
646           for (i = 0; i < NUM_INTERFACES; i++)
647             neug_setup_endpoints_for_interface (i, 0);
648           chopstx_mutex_lock (&usb_mtx);
649           bDeviceState = CONFIGURED;
650           chopstx_mutex_unlock (&usb_mtx);
651         }
652       else if (current_conf != value)
653         {
654           if (value != 0)
655             return USB_UNSUPPORT;
656
657           usb_lld_set_configuration (0);
658           for (i = 0; i < NUM_INTERFACES; i++)
659             neug_setup_endpoints_for_interface (i, 1);
660           chopstx_mutex_lock (&usb_mtx);
661           bDeviceState = ADDRESSED;
662           chopstx_mutex_unlock (&usb_mtx);
663         }
664       /* Do nothing when current_conf == value */
665       return USB_SUCCESS;
666     default:
667       break;
668     }
669
670   return USB_UNSUPPORT;
671 }
672
673
674 int usb_cb_interface (uint8_t cmd, struct req_args *arg)
675 {
676   const uint8_t zero = 0;
677   uint16_t interface = arg->index;
678   uint16_t alt = arg->value;
679
680   if (interface >= NUM_INTERFACES)
681     return USB_UNSUPPORT;
682
683   switch (cmd)
684     {
685     case USB_SET_INTERFACE:
686       if (alt != 0)
687         return USB_UNSUPPORT;
688       else
689         {
690           neug_setup_endpoints_for_interface (interface, 0);
691           return USB_SUCCESS;
692         }
693
694     case USB_GET_INTERFACE:
695       return usb_lld_reply_request (&zero, 1, arg);
696
697     default:
698     case USB_QUERY_INTERFACE:
699       return USB_SUCCESS;
700     }
701 }
702
703 #define INTR_REQ_USB 20
704 #define PRIO_USB 3
705
706 static void *
707 usb_intr (void *arg)
708 {
709   chopstx_intr_t interrupt;
710
711   (void)arg;
712   usb_lld_init (VCOM_FEATURE_BUS_POWERED);
713   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
714   usb_interrupt_handler ();     /* For old SYS < 3.0 */
715
716   while (1)
717     {
718       chopstx_poll (NULL, 1, &interrupt);
719
720       /* Process interrupt. */
721       usb_interrupt_handler ();
722     }
723
724   return NULL;
725 }
726
727 #define ID_OFFSET (2+SERIALNO_STR_LEN*2)
728 static void fill_serial_no_by_unique_id (void)
729 {
730   extern const uint8_t * unique_device_id (void);
731   uint8_t *p = &neug_string_serial[ID_OFFSET];
732   const uint8_t *u = unique_device_id () + 8;
733   int i;
734
735   for (i = 0; i < 4; i++)
736     {
737       uint8_t b = u[3-i];
738       uint8_t nibble;
739
740       nibble = (b >> 4);
741       nibble += (nibble >= 10 ? ('A' - 10) : '0');
742       p[i*4] = nibble;
743       p[i*4+1] = 0;
744       nibble = (b & 0x0f);
745       nibble += (nibble >= 10 ? ('A' - 10) : '0');
746       p[i*4+2] = nibble;
747       p[i*4+3] = 0;
748     }
749 }
750
751
752 void
753 usb_cb_tx_done (uint8_t ep_num, uint32_t len, int success)
754 {
755   (void)len;
756   (void)success;
757
758   if (ep_num == ENDP1)
759     {
760       chopstx_mutex_lock (&usb_mtx);
761       chopstx_cond_signal (&usb_cnd);
762       chopstx_mutex_unlock (&usb_mtx);
763     }
764   else if (ep_num == ENDP2)
765     {
766       /* INTERRUPT Transfer done */
767     }
768 #ifdef FRAUCHEKY_SUPPORT
769   else if (ep_num == ENDP6)
770     EP6_IN_Callback (len);
771 #endif
772 }
773
774 void
775 usb_cb_rx_ready (uint8_t ep_num)
776 {
777   if (ep_num == ENDP3)
778     usb_lld_rx_enable (ENDP3);
779 #ifdef FRAUCHEKY_SUPPORT
780   else if (ep_num == ENDP6)
781     EP6_OUT_Callback ();
782 #endif
783 }
784 \f
785 typedef uint32_t eventmask_t;
786 #define ALL_EVENTS (~0)
787
788 struct event_flag {
789   chopstx_mutex_t mutex;
790   chopstx_cond_t cond;
791   eventmask_t flag;
792 };
793
794 static void event_flag_init (struct event_flag *ev)
795 {
796   ev->flag = 0;
797   chopstx_mutex_init (&ev->mutex);
798   chopstx_cond_init (&ev->cond);
799 }
800
801
802 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
803 {
804   int n;
805
806   chopstx_mutex_lock (&ev->mutex);
807   while (!(ev->flag & m))
808     chopstx_cond_wait (&ev->cond, &ev->mutex);
809
810   n = __builtin_ffs ((ev->flag & m));
811   ev->flag &= ~(1 << (n - 1));
812   chopstx_mutex_unlock (&ev->mutex);
813
814   return (1 << (n - 1));
815 }
816
817 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
818 {
819   chopstx_mutex_lock (&ev->mutex);
820   ev->flag |= m;
821   chopstx_cond_signal (&ev->cond);
822   chopstx_mutex_unlock (&ev->mutex);
823 }
824
825 extern uint8_t __process1_stack_base__, __process1_stack_size__;
826 extern uint8_t __process3_stack_base__, __process3_stack_size__;
827
828 const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
829 const size_t __stacksize_led = (size_t)&__process1_stack_size__;
830 const uint32_t __stackaddr_usb = (uint32_t)&__process3_stack_base__;
831 const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
832
833
834 #define PRIO_LED 3
835 static struct event_flag led_event;
836
837 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
838 #define LED_TWOSHOTS            ((eventmask_t)2)
839 #define LED_ONESHOT_LONG        ((eventmask_t)4)
840
841 /*
842  * LED blinker: When notified, let LED emit for 100ms.
843  */
844 static void *
845 led_blinker (void *arg)
846 {
847   (void)arg;
848
849   set_led (0);
850
851   while (1)
852     {
853       eventmask_t m;
854
855       m = event_flag_waitone (&led_event, ALL_EVENTS);
856
857       set_led (1);
858       if (m == LED_ONESHOT_SHORT)
859         chopstx_usec_wait (100*1000);
860       else if (m == LED_TWOSHOTS)
861         {
862           chopstx_usec_wait (50*1000);
863           set_led (0);
864           chopstx_usec_wait (50*1000);
865           set_led (1);
866           chopstx_usec_wait (50*1000);
867         }
868       else
869         chopstx_usec_wait (250*1000);
870       set_led (0);
871     }
872
873   return NULL;
874 }
875 \f
876 #define RANDOM_BYTES_LENGTH 64
877 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
878
879 static void copy_to_tx (uint32_t v, int i)
880 {
881   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
882 }
883
884 /*
885  * In Gnuk 1.0.[12], reGNUal was not relocatable.
886  * Now, it's relocatable, but we need to calculate its entry address
887  * based on it's pre-defined address.
888  */
889 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
890 static uint32_t
891 calculate_regnual_entry_address (const uint8_t *addr)
892 {
893   const uint8_t *p = addr + 4;
894   uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
895
896   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
897   v += (uint32_t)addr;
898   return v;
899 }
900
901
902 static int
903 check_usb_status (void *arg)
904 {
905   (void)arg;
906
907   return (connected || bDeviceState != CONFIGURED
908           || fsij_device_state != FSIJ_DEVICE_RUNNING);
909 }
910
911 /*
912  * Entry point.
913  *
914  * NOTE: the main function is already a thread in the system on entry.
915  */
916 int
917 main (int argc, char **argv)
918 {
919   uint32_t entry;
920   chopstx_t led_thread, usb_thd;
921   unsigned int count;
922
923   (void)argc;
924   (void)argv;
925
926   fill_serial_no_by_unique_id ();
927
928   adc_init ();
929
930   event_flag_init (&led_event);
931
932   chopstx_mutex_init (&usb_mtx);
933   chopstx_cond_init (&usb_cnd);
934
935 #ifdef FRAUCHEKY_SUPPORT
936   if (fraucheky_enabled ())
937     {
938     go_fraucheky:
939       running_neug = 0;
940       usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
941                                 usb_intr, NULL);
942       set_led (1);
943       fraucheky_main ();
944       chopstx_cancel (usb_thd);
945       chopstx_join (usb_thd, NULL);
946       usb_lld_shutdown ();
947     }
948
949   running_neug = 1;
950 #endif
951
952   led_thread = chopstx_create (PRIO_LED, __stackaddr_led, __stacksize_led,
953                                led_blinker, NULL);
954
955   usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
956                             usb_intr, NULL);
957
958   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
959
960   chopstx_mutex_lock (&usb_mtx);
961
962  not_configured:
963   count = 0;
964   /* Initial run-up */
965   while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
966     {
967       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
968         break;
969
970       chopstx_mutex_unlock (&usb_mtx);
971       neug_wait_full ();
972       neug_flush ();
973
974       if ((count & 0x0007) == 0)
975         event_flag_signal (&led_event, LED_ONESHOT_SHORT);
976       chopstx_usec_wait (25*1000);
977       count++;
978       chopstx_mutex_lock (&usb_mtx);
979     }
980
981   /* Holding USB_MTX...  */
982   while (1)
983     {
984       int last_was_fullsizepacket = 0;
985
986       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
987         break;
988
989       chopstx_mutex_unlock (&usb_mtx);
990       while (1)
991         {
992           chopstx_poll_cond_t poll_desc;
993           uint32_t usec = 5000*1000;
994
995           poll_desc.type = CHOPSTX_POLL_COND;
996           poll_desc.ready = 0;
997           poll_desc.cond = &usb_cnd;
998           poll_desc.mutex = &usb_mtx;
999           poll_desc.check = check_usb_status;
1000           poll_desc.arg = NULL;
1001
1002           if (chopstx_poll (&usec, 1, &poll_desc))
1003             break;
1004
1005           /* Timeout */
1006           neug_flush ();
1007           neug_mode_select (line_coding.paritytype);
1008           event_flag_signal (&led_event, LED_TWOSHOTS);
1009         }
1010
1011       chopstx_mutex_lock (&usb_mtx);
1012       if (bDeviceState != CONFIGURED)
1013         goto not_configured;
1014
1015       /* The connection opened.  */
1016       count = 0;
1017
1018       while (1)
1019         {
1020           int i;
1021
1022           chopstx_mutex_unlock (&usb_mtx);
1023           /*
1024            * No parity is standard.  It means providing conditioned output.
1025            * When parity enabled, it means to provide raw output
1026            * (CRC32 filtered when odd, direct sample of ADC when even).
1027            *
1028            * line_coding.paritytype:
1029            *   0: None, 1: Odd, 2: Even
1030            */
1031           neug_mode_select (line_coding.paritytype);
1032
1033           if ((count & 0x03ff) == 0)
1034             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1035
1036           i = neug_consume_random (copy_to_tx);
1037
1038           if (i == 0 && !last_was_fullsizepacket)
1039             {    /* Only send ZLP when the last packet was fullsize.  */
1040               neug_wait_full ();
1041
1042               chopstx_mutex_lock (&usb_mtx);
1043               if (bDeviceState != CONFIGURED || !connected
1044                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1045                 break;
1046             }
1047           else
1048             {
1049               if (i == 64/4)
1050                 last_was_fullsizepacket = 1;
1051               else
1052                 last_was_fullsizepacket = 0;
1053
1054               chopstx_mutex_lock (&usb_mtx);
1055               if (bDeviceState != CONFIGURED || !connected
1056                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1057                 break;
1058
1059               /* Prepare sending random data.  */
1060               usb_lld_tx_enable (ENDP1, i * 4);
1061               chopstx_cond_wait (&usb_cnd, &usb_mtx);
1062               count++;
1063             }
1064         }
1065     }
1066
1067   chopstx_mutex_unlock (&usb_mtx);
1068
1069   chopstx_cancel (led_thread);
1070   chopstx_join (led_thread, NULL);
1071
1072   /*
1073    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED
1074    * or FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED.
1075    */
1076   neug_fini ();
1077
1078   chopstx_mutex_lock (&usb_mtx);
1079 #ifdef FRAUCHEKY_SUPPORT
1080   if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
1081     {
1082       while (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
1083         {
1084           chopstx_mutex_unlock (&usb_mtx);
1085           set_led (1);
1086           chopstx_usec_wait (500*1000);
1087           set_led (0);
1088           chopstx_usec_wait (500*1000);
1089           chopstx_mutex_lock (&usb_mtx);
1090         }
1091
1092       usb_lld_prepare_shutdown ();
1093       chopstx_mutex_unlock (&usb_mtx);
1094       chopstx_cancel (usb_thd);
1095       chopstx_join (usb_thd, NULL);
1096       usb_lld_shutdown ();
1097       goto go_fraucheky;
1098     }
1099 #endif
1100
1101   fsij_device_state = FSIJ_DEVICE_EXITED;
1102
1103   while (fsij_device_state == FSIJ_DEVICE_EXITED)
1104     {
1105       chopstx_mutex_unlock (&usb_mtx);
1106       chopstx_usec_wait (500*1000);
1107       chopstx_mutex_lock (&usb_mtx);
1108     }
1109   chopstx_mutex_unlock (&usb_mtx);
1110
1111   flash_unlock ();              /* Flash unlock should be done here */
1112   set_led (1);
1113   usb_lld_shutdown ();
1114
1115   /* Finish application.  */
1116   chopstx_cancel (usb_thd);
1117   chopstx_join (usb_thd, NULL);
1118
1119   /* Set vector */
1120   SCB->VTOR = (uint32_t)&_regnual_start;
1121   entry = calculate_regnual_entry_address (&_regnual_start);
1122 #ifdef DFU_SUPPORT
1123 #define FLASH_SYS_START_ADDR 0x08000000
1124 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
1125 #define CHIP_ID_REG ((uint32_t *)0xE0042000)
1126   {
1127     extern uint8_t _sys;
1128     uint32_t addr;
1129     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
1130     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
1131     uint32_t flash_page_size = 1024; /* 1KiB default */
1132
1133    if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device.  */
1134      flash_page_size += 0x0400; /* It's 2KiB. */
1135
1136     /* Kill DFU */
1137     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
1138          addr += flash_page_size)
1139       flash_erase_page (addr);
1140
1141     /* copy system service routines */
1142     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
1143
1144     /* Leave NeuG to exec reGNUal */
1145     (*func) ((void (*)(void))entry);
1146     for (;;);
1147   }
1148 #else
1149   /* Leave NeuG to exec reGNUal */
1150   flash_erase_all_and_exec ((void (*)(void))entry);
1151 #endif
1152
1153   /* Never reached */
1154   return 0;
1155 }