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