SET_CONTROL_LINE_STATE request
[gnuk/neug.git] / src / main.c
1 /*
2  * main.c - main routine of neug
3  *
4  * Main routine:
5  * Copyright (C) 2011, 2012, 2013, 2015
6  *               Free Software Initiative of Japan
7  * Author: NIIBE Yutaka <gniibe@fsij.org>
8  *
9  * This file is a part of NeuG, a True Random Number Generator
10  * implementation.
11  *
12  * NeuG is free software: you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * NeuG is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26
27
28 #include <stdint.h>
29 #include <string.h>
30 #include <chopstx.h>
31
32 #include "config.h"
33 #include "neug.h"
34 #include "usb_lld.h"
35 #include "sys.h"
36 #include "stm32f103.h"
37 #include "adc.h"
38
39 enum {
40   FSIJ_DEVICE_RUNNING = 0,
41   FSIJ_DEVICE_EXITED,
42   FSIJ_DEVICE_EXEC_REQUESTED,
43   /**/
44   FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED = 254,
45   FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
46 }; 
47
48 #ifdef FRAUCHEKY_SUPPORT
49 static uint8_t running_neug;
50 #endif
51
52 static chopstx_mutex_t usb_mtx;
53 static chopstx_cond_t cnd_usb;
54 static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
55 static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
56 static uint8_t connected;
57 static uint32_t wait_usb_connection; /* Timer variable.  */
58
59
60 extern uint8_t __process0_stack_end__;
61 static chopstx_t main_thd = (uint32_t)(&__process0_stack_end__ - 60);
62
63 #define ENDP0_RXADDR        (0x40)
64 #define ENDP0_TXADDR        (0x80)
65 #define ENDP1_TXADDR        (0xc0)
66 #define ENDP2_TXADDR        (0x100)
67 #define ENDP3_RXADDR        (0x140)
68
69 #define USB_CDC_REQ_SET_LINE_CODING             0x20
70 #define USB_CDC_REQ_GET_LINE_CODING             0x21
71 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE      0x22
72 #define USB_CDC_REQ_SEND_BREAK                  0x23
73
74 /* USB Device Descriptor */
75 static const uint8_t vcom_device_desc[18] = {
76   18,   /* bLength */
77   USB_DEVICE_DESCRIPTOR_TYPE,   /* bDescriptorType */
78   0x10, 0x01,                   /* bcdUSB = 1.1 */
79   0x02,                         /* bDeviceClass (CDC).              */
80   0x00,                         /* bDeviceSubClass.                 */
81   0x00,                         /* bDeviceProtocol.                 */
82   0x40,                         /* bMaxPacketSize.                  */
83 #include "usb-vid-pid-ver.c.inc"
84   1,                            /* iManufacturer.                   */
85   2,                            /* iProduct.                        */
86   3,                            /* iSerialNumber.                   */
87   1                             /* bNumConfigurations.              */
88 };
89
90 /* Configuration Descriptor tree for a CDC.*/
91 static const uint8_t vcom_config_desc[67] = {
92   9,
93   USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
94   /* Configuration Descriptor.*/
95   67, 0x00,                     /* wTotalLength.                    */
96   0x02,                         /* bNumInterfaces.                  */
97   0x01,                         /* bConfigurationValue.             */
98   0,                            /* iConfiguration.                  */
99   0x80,                         /* bmAttributes (bus powered).      */
100   50,                           /* bMaxPower (100mA).               */
101   /* Interface Descriptor.*/
102   9,
103   USB_INTERFACE_DESCRIPTOR_TYPE,
104   0x00,            /* bInterfaceNumber.                */
105   0x00,            /* bAlternateSetting.               */
106   0x01,            /* bNumEndpoints.                   */
107   0x02,            /* bInterfaceClass (Communications Interface Class,
108                       CDC section 4.2).  */
109   0x02,            /* bInterfaceSubClass (Abstract Control Model, CDC
110                       section 4.3).  */
111   0x01,            /* bInterfaceProtocol (AT commands, CDC section
112                       4.4).  */
113   0,               /* iInterface.                      */
114   /* Header Functional Descriptor (CDC section 5.2.3).*/
115   5,          /* bLength.                         */
116   0x24,       /* bDescriptorType (CS_INTERFACE).  */
117   0x00,       /* bDescriptorSubtype (Header Functional Descriptor). */
118   0x10, 0x01, /* bcdCDC.                          */
119   /* Call Management Functional Descriptor. */
120   5,            /* bFunctionLength.                 */
121   0x24,         /* bDescriptorType (CS_INTERFACE).  */
122   0x01,         /* bDescriptorSubtype (Call Management Functional
123                    Descriptor). */
124   0x03,         /* bmCapabilities (D0+D1).          */
125   0x01,         /* bDataInterface.                  */
126   /* ACM Functional Descriptor.*/
127   4,            /* bFunctionLength.                 */
128   0x24,         /* bDescriptorType (CS_INTERFACE).  */
129   0x02,         /* bDescriptorSubtype (Abstract Control Management
130                    Descriptor).  */
131   0x02,         /* bmCapabilities.                  */
132   /* Union Functional Descriptor.*/
133   5,            /* bFunctionLength.                 */
134   0x24,         /* bDescriptorType (CS_INTERFACE).  */
135   0x06,         /* bDescriptorSubtype (Union Functional
136                    Descriptor).  */
137   0x00,         /* bMasterInterface (Communication Class
138                    Interface).  */
139   0x01,         /* bSlaveInterface0 (Data Class Interface).  */
140   /* Endpoint 2 Descriptor.*/
141   7,
142   USB_ENDPOINT_DESCRIPTOR_TYPE,
143   ENDP2|0x80,    /* bEndpointAddress.    */
144   0x03,          /* bmAttributes (Interrupt).        */
145   0x08, 0x00,    /* wMaxPacketSize.                  */
146   0xFF,          /* bInterval.                       */
147   /* Interface Descriptor.*/
148   9,
149   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
150   0x01,          /* bInterfaceNumber.                */
151   0x00,          /* bAlternateSetting.               */
152   0x02,          /* bNumEndpoints.                   */
153   0x0A,          /* bInterfaceClass (Data Class Interface, CDC section 4.5). */
154   0x00,          /* bInterfaceSubClass (CDC section 4.6). */
155   0x00,          /* bInterfaceProtocol (CDC section 4.7). */
156   0x00,          /* iInterface.                      */
157   /* Endpoint 3 Descriptor.*/
158   7,
159   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
160   ENDP3,    /* bEndpointAddress. */
161   0x02,                         /* bmAttributes (Bulk).             */
162   0x40, 0x00,                   /* wMaxPacketSize.                  */
163   0x00,                         /* bInterval.                       */
164   /* Endpoint 1 Descriptor.*/
165   7,
166   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
167   ENDP1|0x80,                   /* bEndpointAddress. */
168   0x02,                         /* bmAttributes (Bulk).             */
169   0x40, 0x00,                   /* wMaxPacketSize.                  */
170   0x00                          /* bInterval.                       */
171 };
172
173
174 /*
175  * U.S. English language identifier.
176  */
177 static const uint8_t vcom_string0[4] = {
178   4,                            /* bLength */
179   USB_STRING_DESCRIPTOR_TYPE,
180   0x09, 0x04                    /* LangID = 0x0409: US-English */
181 };
182
183 #include "usb-strings.c.inc"
184
185 #ifdef FRAUCHEKY_SUPPORT
186 extern int fraucheky_enabled (void);
187 extern void fraucheky_main (void);
188
189 extern void fraucheky_setup_endpoints_for_interface (int stop);
190 extern int fraucheky_setup (uint8_t req, uint8_t req_no,
191                             struct control_info *detail);
192 extern int fraucheky_get_descriptor (uint8_t rcp, uint8_t desc_type,
193                                      uint8_t desc_index,
194                                      struct control_info *detail);
195 #endif
196
197 #define NUM_INTERFACES 2
198
199 void
200 usb_cb_device_reset (void)
201 {
202   /* Set DEVICE as not configured */
203   usb_lld_set_configuration (0);
204
205   /* Current Feature initialization */
206   usb_lld_set_feature (vcom_config_desc[7]);
207
208   usb_lld_reset ();
209
210   /* Initialize Endpoint 0 */
211   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
212 }
213
214 extern uint8_t _regnual_start, __heap_end__;
215
216 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
217
218 /* USB vendor requests to control pipe */
219 #define USB_FSIJ_MEMINFO          0
220 #define USB_FSIJ_DOWNLOAD         1
221 #define USB_FSIJ_EXEC             2
222 #define USB_NEUG_SET_PASSWD     253
223 #define USB_NEUG_GET_INFO       254
224 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
225
226 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
227   0xff,
228   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
229   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
230   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
231 };
232 static uint8_t usbbuf[64];
233
234 #define DEFAULT_PASSWD "12345678"
235 #define DEFAULT_PASSWD_LEN 8
236
237 static void set_passwd (void)
238 {
239   flash_unlock ();
240   if (neug_passwd[0] != 0xff)
241     flash_erase_page ((uint32_t)neug_passwd);
242   if (usbbuf[0] == DEFAULT_PASSWD_LEN
243       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
244     return;
245   flash_write ((uint32_t)neug_passwd, usbbuf, usbbuf[0] + 1);
246 }
247
248 static uint32_t rbit (uint32_t v)
249 {
250   uint32_t r;
251
252   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
253   return r;
254 }
255
256 /* After calling this function, CRC module remain enabled.  */
257 static int download_check_crc32 (const uint32_t *end_p)
258 {
259   uint32_t crc32 = *end_p;
260   const uint32_t *p;
261
262   RCC->AHBENR |= RCC_AHBENR_CRCEN;
263   CRC->CR = CRC_CR_RESET;
264
265   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
266     CRC->DR = rbit (*p);
267
268   if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
269     return USB_SUCCESS;
270
271   return USB_UNSUPPORT;
272 }
273
274
275 #define NEUG_SPECIAL_BITRATE 110
276
277 struct line_coding
278 {
279   uint32_t bitrate;
280   uint8_t format;
281   uint8_t paritytype;
282   uint8_t datatype;
283 } __attribute__((packed));
284
285 static struct line_coding line_coding = {
286   115200, /* baud rate: 115200    */
287   0x00,   /* stop bits: 1         */
288   0x00,   /* parity:    none      */
289   0x08    /* bits:      8         */
290 };
291
292 #define CDC_CTRL_DTR            0x0001
293
294 void
295 usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
296 {
297   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
298
299   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
300     {
301       if (req_no == USB_FSIJ_EXEC)
302         {
303           chopstx_mutex_lock (&usb_mtx);
304           if (fsij_device_state == FSIJ_DEVICE_EXITED)
305             {
306               usb_lld_prepare_shutdown (); /* No further USB communication */
307               fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
308             }
309           chopstx_mutex_unlock (&usb_mtx);
310         }
311       else if (req_no == USB_NEUG_SET_PASSWD)
312         set_passwd ();
313       else if (req_no == USB_NEUG_EXIT)
314         {
315           if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
316                && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
317               || (neug_passwd[0] == usbbuf[0]
318                   && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0])))
319             {
320               chopstx_mutex_lock (&usb_mtx);
321               fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
322               chopstx_wakeup_usec_wait (main_thd);
323               chopstx_cond_signal (&cnd_usb);
324               chopstx_mutex_unlock (&usb_mtx);
325             }
326         }
327     }
328   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
329            && USB_SETUP_SET (req))
330     {
331       if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
332         {
333           /* Open/close the connection.  */
334           chopstx_mutex_lock (&usb_mtx);
335           connected = (value & CDC_CTRL_DTR)? 1 : 0;
336           if (wait_usb_connection)
337             {                   /* It is waiting a connection.  */
338               if (connected)    /* It's now connected.  */
339                 chopstx_wakeup_usec_wait (main_thd);
340             }
341           else
342             chopstx_cond_signal (&cnd_usb);
343           chopstx_mutex_unlock (&usb_mtx);
344         }
345 #ifdef FRAUCHEKY_SUPPORT
346       else if (req_no == USB_CDC_REQ_SET_LINE_CODING)
347         {
348           chopstx_mutex_lock (&usb_mtx);
349           if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
350             {
351               fsij_device_state = FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED;
352               chopstx_wakeup_usec_wait (main_thd);
353               chopstx_cond_signal (&cnd_usb);
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 control_info *detail)
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), detail);
371     }
372   else  /* USB_SETUP_SET (req) */
373     {
374       if (req_no == USB_CDC_REQ_SET_LINE_CODING
375           && detail->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 control_info *detail)
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), detail);
406               return USB_SUCCESS;
407             }
408           else if (req_no == USB_NEUG_GET_INFO)
409             {
410               if (detail->index == 0)
411                 usb_lld_reply_request (&neug_mode, sizeof (uint8_t), detail);
412               else if (detail->index == 1)
413                 usb_lld_reply_request (&neug_err_cnt, sizeof (uint16_t), detail);
414               else if (detail->index == 2)
415                 usb_lld_reply_request (&neug_err_cnt_rc, sizeof (uint16_t), detail);
416               else if (detail->index == 3)
417                 usb_lld_reply_request (&neug_err_cnt_p64, sizeof (uint16_t), detail);
418               else if (detail->index == 4)
419                 usb_lld_reply_request (&neug_err_cnt_p4k, sizeof (uint16_t), detail);
420               else if (detail->index == 5)
421                 usb_lld_reply_request (&neug_rc_max, sizeof (uint16_t), detail);
422               else if (detail->index == 6)
423                 usb_lld_reply_request (&neug_p64_max, sizeof (uint16_t), detail);
424               else if (detail->index == 7)
425                 usb_lld_reply_request (&neug_p4k_max, sizeof (uint16_t), detail);
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 + detail->value * 0x100 + detail->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 + detail->len > &__heap_end__)
447                 return USB_UNSUPPORT;
448
449               if (detail->index + detail->len < 256)
450                 memset (addr + detail->index + detail->len, 0, 256 - (detail->index + detail->len));
451
452               usb_lld_set_data_to_recv (addr, detail->len);
453               return USB_SUCCESS;
454             }
455           else if (req_no == USB_FSIJ_EXEC && detail->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 && detail->len <= 32)
471             {
472               usbbuf[0] = detail->len;
473               usb_lld_set_data_to_recv (usbbuf + 1, detail->len);
474               return USB_SUCCESS;
475             }
476           else if (req_no == USB_NEUG_EXIT && detail->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] = detail->len;
487               usb_lld_set_data_to_recv (usbbuf + 1, detail->len);
488               return USB_SUCCESS;
489             }
490         }
491     }
492   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
493            && detail->index == 0)
494     {
495 #ifdef FRAUCHEKY_SUPPORT
496       if (running_neug)
497         return vcom_port_data_setup (req, req_no, detail);
498       else
499         fraucheky_setup (req, req_no, detail);
500 #else
501       return vcom_port_data_setup (req, req_no, detail);
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 control_info *detail)
511 {
512 #ifdef FRAUCHEKY_SUPPORT
513   if (!running_neug)
514     return fraucheky_get_descriptor (rcp, desc_type, desc_index, detail);
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                                   detail);
523   else if (desc_type == CONFIG_DESCRIPTOR)
524     return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
525                                   detail);
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] = USB_STRING_DESCRIPTOR_TYPE;
575             size = i*2 + 2;
576           }
577           break;
578         default:
579           return USB_UNSUPPORT;
580         }
581
582       return usb_lld_reply_request (str, size, detail);
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         }
617       else
618         {
619           usb_lld_stall_tx (ENDP1);
620           usb_lld_stall_rx (ENDP3);
621         }
622     }
623 }
624
625 int usb_cb_handle_event (uint8_t event_type, uint16_t value)
626 {
627   int i;
628   uint8_t current_conf;
629
630   switch (event_type)
631     {
632     case USB_EVENT_ADDRESS:
633       chopstx_mutex_lock (&usb_mtx);
634       bDeviceState = ADDRESSED;
635       chopstx_mutex_unlock (&usb_mtx);
636       return USB_SUCCESS;
637     case USB_EVENT_CONFIG:
638       current_conf = usb_lld_current_configuration ();
639       if (current_conf == 0)
640         {
641           if (value != 1)
642             return USB_UNSUPPORT;
643
644           usb_lld_set_configuration (1);
645           for (i = 0; i < NUM_INTERFACES; i++)
646             neug_setup_endpoints_for_interface (i, 0);
647           chopstx_mutex_lock (&usb_mtx);
648           bDeviceState = CONFIGURED;
649           chopstx_mutex_unlock (&usb_mtx);
650         }
651       else if (current_conf != value)
652         {
653           if (value != 0)
654             return USB_UNSUPPORT;
655
656           usb_lld_set_configuration (0);
657           for (i = 0; i < NUM_INTERFACES; i++)
658             neug_setup_endpoints_for_interface (i, 1);
659           chopstx_mutex_lock (&usb_mtx);
660           bDeviceState = ADDRESSED;
661           chopstx_mutex_unlock (&usb_mtx);
662         }
663       /* Do nothing when current_conf == value */
664       return USB_SUCCESS;
665
666       return USB_SUCCESS;
667     default:
668       break;
669     }
670
671   return USB_UNSUPPORT;
672 }
673
674
675 int usb_cb_interface (uint8_t cmd, struct control_info *detail)
676 {
677   const uint8_t zero = 0;
678   uint16_t interface = detail->index;
679   uint16_t alt = detail->value;
680
681   if (interface >= NUM_INTERFACES)
682     return USB_UNSUPPORT;
683
684   switch (cmd)
685     {
686     case USB_SET_INTERFACE:
687       if (alt != 0)
688         return USB_UNSUPPORT;
689       else
690         {
691           neug_setup_endpoints_for_interface (interface, 0);
692           return USB_SUCCESS;
693         }
694
695     case USB_GET_INTERFACE:
696       usb_lld_reply_request (&zero, 1, detail);
697       return USB_SUCCESS;
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_config_desc[7]);
715   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
716   usb_interrupt_handler ();
717
718   while (1)
719     {
720       chopstx_intr_wait (&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 \f
753 void
754 EP1_IN_Callback (void)
755 {
756   chopstx_mutex_lock (&usb_mtx);
757   chopstx_cond_signal (&cnd_usb);
758   chopstx_mutex_unlock (&usb_mtx);
759 }
760
761 void
762 EP2_IN_Callback (void)
763 {
764 }
765
766 void
767 EP3_OUT_Callback (void)
768 {
769   usb_lld_rx_enable (ENDP3);
770 }
771 \f
772 typedef uint32_t eventmask_t;
773 #define ALL_EVENTS (~0)
774
775 struct event_flag {
776   chopstx_mutex_t mutex;
777   chopstx_cond_t cond;
778   eventmask_t flag;
779 };
780
781 static void event_flag_init (struct event_flag *ev)
782 {
783   ev->flag = 0;
784   chopstx_mutex_init (&ev->mutex);
785   chopstx_cond_init (&ev->cond);
786 }
787
788
789 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
790 {
791   int n;
792
793   chopstx_mutex_lock (&ev->mutex);
794   while (!(ev->flag & m))
795     chopstx_cond_wait (&ev->cond, &ev->mutex);
796
797   n = __builtin_ffs ((ev->flag & m));
798   ev->flag &= ~(1 << (n - 1));
799   chopstx_mutex_unlock (&ev->mutex);
800
801   return (1 << (n - 1));
802 }
803
804 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
805 {
806   chopstx_mutex_lock (&ev->mutex);
807   ev->flag |= m;
808   chopstx_cond_signal (&ev->cond);
809   chopstx_mutex_unlock (&ev->mutex);
810 }
811
812 extern uint8_t __process1_stack_base__, __process1_stack_size__;
813 extern uint8_t __process3_stack_base__, __process3_stack_size__;
814
815 const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
816 const size_t __stacksize_led = (size_t)&__process1_stack_size__;
817 const uint32_t __stackaddr_usb = (uint32_t)&__process3_stack_base__;
818 const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
819
820
821 #define PRIO_LED 3
822 static struct event_flag led_event;
823
824 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
825 #define LED_TWOSHOTS            ((eventmask_t)2)
826 #define LED_ONESHOT_LONG        ((eventmask_t)4)
827
828 /*
829  * LED blinker: When notified, let LED emit for 100ms.
830  */
831 static void *
832 led_blinker (void *arg)
833 {
834   (void)arg;
835
836   set_led (0);
837
838   while (1)
839     {
840       eventmask_t m;
841
842       m = event_flag_waitone (&led_event, ALL_EVENTS);
843
844       set_led (1);
845       if (m == LED_ONESHOT_SHORT)
846         chopstx_usec_wait (100*1000);
847       else if (m == LED_TWOSHOTS)
848         {
849           chopstx_usec_wait (50*1000);
850           set_led (0);
851           chopstx_usec_wait (50*1000);
852           set_led (1);
853           chopstx_usec_wait (50*1000);
854         }
855       else
856         chopstx_usec_wait (250*1000);
857       set_led (0);
858     }
859
860   return NULL;
861 }
862 \f
863 #define RANDOM_BYTES_LENGTH 64
864 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
865
866 static void copy_to_tx (uint32_t v, int i)
867 {
868   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
869 }
870
871 /*
872  * In Gnuk 1.0.[12], reGNUal was not relocatable.
873  * Now, it's relocatable, but we need to calculate its entry address
874  * based on it's pre-defined address.
875  */
876 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
877 static uint32_t
878 calculate_regnual_entry_address (const uint8_t *addr)
879 {
880   const uint8_t *p = addr + 4;
881   uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
882
883   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
884   v += (uint32_t)addr;
885   return v;
886 }
887
888
889 /*
890  * Entry point.
891  *
892  * NOTE: the main function is already a thread in the system on entry.
893  */
894 int
895 main (int argc, char **argv)
896 {
897   uint32_t entry;
898   chopstx_t led_thread, usb_thd;
899   unsigned int count;
900
901   (void)argc;
902   (void)argv;
903
904   fill_serial_no_by_unique_id ();
905
906   adc_init ();
907
908   event_flag_init (&led_event);
909   
910   chopstx_mutex_init (&usb_mtx);
911   chopstx_cond_init (&cnd_usb);
912
913 #ifdef FRAUCHEKY_SUPPORT
914   if (fraucheky_enabled ())
915     {
916     go_fraucheky:
917       running_neug = 0;
918       usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
919                                 usb_intr, NULL);
920       set_led (1);
921       fraucheky_main ();
922       chopstx_cancel (usb_thd);
923       chopstx_join (usb_thd, NULL);
924       usb_lld_shutdown ();
925     }
926
927   running_neug = 1;
928 #endif
929
930   led_thread = chopstx_create (PRIO_LED, __stackaddr_led, __stacksize_led,
931                                led_blinker, NULL);
932
933   usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
934                             usb_intr, NULL);
935
936   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
937
938   chopstx_mutex_lock (&usb_mtx);
939
940  not_configured:
941   count = 0;
942   /* A run-up */
943   while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
944     {
945       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
946         break;
947
948       chopstx_mutex_unlock (&usb_mtx);
949       neug_wait_full ();
950       neug_flush ();
951
952       if ((count & 0x0007) == 0)
953         event_flag_signal (&led_event, LED_ONESHOT_SHORT);
954       chopstx_usec_wait (25*1000);
955       count++;
956       chopstx_mutex_lock (&usb_mtx);
957     }
958
959   /* Holding USB_MTX.  */
960   while (1)
961     {
962       int last_was_fullsizepacket = 0;
963
964       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
965         break;
966
967       while (1)
968         {
969           wait_usb_connection = 5000*1000;
970           if (connected || bDeviceState != CONFIGURED
971               || fsij_device_state != FSIJ_DEVICE_RUNNING)
972             break;
973
974           chopstx_mutex_unlock (&usb_mtx);
975           neug_flush ();
976           neug_mode_select (line_coding.paritytype);
977           event_flag_signal (&led_event, LED_TWOSHOTS);
978           chopstx_usec_wait_var (&wait_usb_connection);
979           chopstx_mutex_lock (&usb_mtx);
980         }
981
982       if (bDeviceState != CONFIGURED)
983         goto not_configured;
984
985       /* The connection opened.  */
986       count = 0;
987
988       while (1)
989         {
990           int i;
991
992           chopstx_mutex_unlock (&usb_mtx);
993           /*
994            * No parity is standard.  It means providing conditioned output.
995            * When parity enabled, it means to provide raw output
996            * (CRC32 filtered when odd, direct sample of ADC when even).
997            *
998            * line_coding.paritytype:
999            *   0: None, 1: Odd, 2: Even
1000            */
1001           neug_mode_select (line_coding.paritytype);
1002
1003           if ((count & 0x03ff) == 0)
1004             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1005
1006           i = neug_consume_random (copy_to_tx);
1007
1008           if (i == 0 && !last_was_fullsizepacket)
1009             {    /* Only send ZLP when the last packet was fullsize.  */
1010               neug_wait_full ();
1011
1012               chopstx_mutex_lock (&usb_mtx);
1013               if (bDeviceState != CONFIGURED || !connected
1014                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1015                 break;
1016             }
1017           else
1018             {
1019               if (i == 64/4)
1020                 last_was_fullsizepacket = 1;
1021               else
1022                 last_was_fullsizepacket = 0;
1023
1024               chopstx_mutex_lock (&usb_mtx);
1025               if (bDeviceState != CONFIGURED || !connected
1026                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1027                 break;
1028
1029               /* Prepare sending random data.  */
1030               usb_lld_tx_enable (ENDP1, i * 4);
1031               chopstx_cond_wait (&cnd_usb, &usb_mtx);
1032               count++;
1033             }
1034         }
1035     }
1036
1037   chopstx_mutex_unlock (&usb_mtx);
1038
1039   chopstx_cancel (led_thread);
1040   chopstx_join (led_thread, NULL);
1041
1042   /*
1043    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED
1044    * or FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED.
1045    */
1046   neug_fini ();
1047
1048   chopstx_mutex_lock (&usb_mtx);
1049 #ifdef FRAUCHEKY_SUPPORT
1050   if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
1051     {
1052       while (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
1053         {
1054           chopstx_mutex_unlock (&usb_mtx);
1055           set_led (1);
1056           chopstx_usec_wait (500*1000);
1057           set_led (0);
1058           chopstx_usec_wait (500*1000);
1059           chopstx_mutex_lock (&usb_mtx);
1060         }
1061
1062       usb_lld_prepare_shutdown ();
1063       chopstx_mutex_unlock (&usb_mtx);
1064       chopstx_cancel (usb_thd);
1065       chopstx_join (usb_thd, NULL);
1066       usb_lld_shutdown ();
1067       goto go_fraucheky;
1068     }
1069 #endif
1070
1071   fsij_device_state = FSIJ_DEVICE_EXITED;
1072
1073   while (fsij_device_state == FSIJ_DEVICE_EXITED)
1074     {
1075       chopstx_mutex_unlock (&usb_mtx);
1076       chopstx_usec_wait (500*1000);
1077       chopstx_mutex_lock (&usb_mtx);
1078     }
1079   chopstx_mutex_unlock (&usb_mtx);
1080
1081   flash_unlock ();              /* Flash unlock should be done here */
1082   set_led (1);
1083   usb_lld_shutdown ();
1084
1085   /* Finish application.  */
1086   chopstx_cancel (usb_thd);
1087   chopstx_join (usb_thd, NULL);
1088
1089   /* Set vector */
1090   SCB->VTOR = (uint32_t)&_regnual_start;
1091   entry = calculate_regnual_entry_address (&_regnual_start);
1092 #ifdef DFU_SUPPORT
1093 #define FLASH_SYS_START_ADDR 0x08000000
1094 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
1095 #define CHIP_ID_REG ((uint32_t *)0xE0042000)
1096   {
1097     extern uint8_t _sys;
1098     uint32_t addr;
1099     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
1100     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
1101     uint32_t flash_page_size = 1024; /* 1KiB default */
1102
1103    if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device.  */
1104      flash_page_size += 0x0400; /* It's 2KiB. */
1105
1106     /* Kill DFU */
1107     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
1108          addr += flash_page_size)
1109       flash_erase_page (addr);
1110
1111     /* copy system service routines */
1112     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
1113
1114     /* Leave NeuG to exec reGNUal */
1115     (*func) ((void (*)(void))entry);
1116     for (;;);
1117   }
1118 #else
1119   /* Leave NeuG to exec reGNUal */
1120   flash_erase_all_and_exec ((void (*)(void))entry);
1121 #endif
1122
1123   /* Never reached */
1124   return 0;
1125 }