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