update chopstx
[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   /* Notify upper layer.  */
214   chopstx_mutex_lock (&usb_mtx);
215   bDeviceState = ATTACHED;
216   connected = 0;
217   if (!wait_usb_connection)
218     chopstx_cond_signal (&cnd_usb);
219   chopstx_mutex_unlock (&usb_mtx);
220 }
221
222 extern uint8_t _regnual_start, __heap_end__;
223
224 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
225
226 /* USB vendor requests to control pipe */
227 #define USB_FSIJ_MEMINFO          0
228 #define USB_FSIJ_DOWNLOAD         1
229 #define USB_FSIJ_EXEC             2
230 #define USB_NEUG_SET_PASSWD     253
231 #define USB_NEUG_GET_INFO       254
232 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
233
234 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
235   0xff,
236   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
237   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
238   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
239 };
240 static uint8_t usbbuf[64];
241
242 #define DEFAULT_PASSWD "12345678"
243 #define DEFAULT_PASSWD_LEN 8
244
245 static void set_passwd (void)
246 {
247   flash_unlock ();
248   if (neug_passwd[0] != 0xff)
249     flash_erase_page ((uint32_t)neug_passwd);
250   if (usbbuf[0] == DEFAULT_PASSWD_LEN
251       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
252     return;
253   flash_write ((uint32_t)neug_passwd, usbbuf, usbbuf[0] + 1);
254 }
255
256 static uint32_t rbit (uint32_t v)
257 {
258   uint32_t r;
259
260   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
261   return r;
262 }
263
264 /* After calling this function, CRC module remain enabled.  */
265 static int download_check_crc32 (const uint32_t *end_p)
266 {
267   uint32_t crc32 = *end_p;
268   const uint32_t *p;
269
270   RCC->AHBENR |= RCC_AHBENR_CRCEN;
271   CRC->CR = CRC_CR_RESET;
272
273   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
274     CRC->DR = rbit (*p);
275
276   if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
277     return USB_SUCCESS;
278
279   return USB_UNSUPPORT;
280 }
281
282
283 #define NEUG_SPECIAL_BITRATE 110
284
285 struct line_coding
286 {
287   uint32_t bitrate;
288   uint8_t format;
289   uint8_t paritytype;
290   uint8_t datatype;
291 } __attribute__((packed));
292
293 static struct line_coding line_coding = {
294   115200, /* baud rate: 115200    */
295   0x00,   /* stop bits: 1         */
296   0x00,   /* parity:    none      */
297   0x08    /* bits:      8         */
298 };
299
300 #define CDC_CTRL_DTR            0x0001
301
302 void
303 usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
304 {
305   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
306
307   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
308     {
309       if (req_no == USB_FSIJ_EXEC)
310         {
311           chopstx_mutex_lock (&usb_mtx);
312           if (fsij_device_state == FSIJ_DEVICE_EXITED)
313             {
314               usb_lld_prepare_shutdown (); /* No further USB communication */
315               fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
316             }
317           chopstx_mutex_unlock (&usb_mtx);
318         }
319       else if (req_no == USB_NEUG_SET_PASSWD)
320         set_passwd ();
321       else if (req_no == USB_NEUG_EXIT)
322         {
323           if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
324                && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
325               || (neug_passwd[0] == usbbuf[0]
326                   && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0])))
327             {
328               chopstx_mutex_lock (&usb_mtx);
329               fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
330               chopstx_wakeup_usec_wait (main_thd);
331               chopstx_cond_signal (&cnd_usb);
332               chopstx_mutex_unlock (&usb_mtx);
333             }
334         }
335     }
336   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
337            && USB_SETUP_SET (req))
338     {
339       if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
340         {
341           /* Open/close the connection.  */
342           chopstx_mutex_lock (&usb_mtx);
343           connected = (value & CDC_CTRL_DTR)? 1 : 0;
344           if (wait_usb_connection)
345             {                   /* It is waiting a connection.  */
346               if (connected)    /* It's now connected.  */
347                 chopstx_wakeup_usec_wait (main_thd);
348             }
349           else
350             chopstx_cond_signal (&cnd_usb);
351           chopstx_mutex_unlock (&usb_mtx);
352         }
353 #ifdef FRAUCHEKY_SUPPORT
354       else if (req_no == USB_CDC_REQ_SET_LINE_CODING)
355         {
356           chopstx_mutex_lock (&usb_mtx);
357           if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
358             {
359               fsij_device_state = FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED;
360               chopstx_wakeup_usec_wait (main_thd);
361               chopstx_cond_signal (&cnd_usb);
362             }
363           else if (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
364             fsij_device_state = FSIJ_DEVICE_RUNNING;
365           chopstx_mutex_unlock (&usb_mtx);
366         }
367 #endif
368     }
369 }
370
371
372 static int
373 vcom_port_data_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
374 {
375   if (USB_SETUP_GET (req))
376     {
377       if (req_no == USB_CDC_REQ_GET_LINE_CODING)
378         return usb_lld_reply_request (&line_coding, sizeof(line_coding), detail);
379     }
380   else  /* USB_SETUP_SET (req) */
381     {
382       if (req_no == USB_CDC_REQ_SET_LINE_CODING
383           && detail->len == sizeof (line_coding))
384         {
385           usb_lld_set_data_to_recv (&line_coding, sizeof (line_coding));
386           return USB_SUCCESS;
387         }
388       else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
389         return USB_SUCCESS;
390     }
391
392   return USB_UNSUPPORT;
393 }
394
395 int
396 usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
397 {
398   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
399
400   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
401     {
402       if (USB_SETUP_GET (req))
403         {
404           if (req_no == USB_FSIJ_MEMINFO)
405             {
406               chopstx_mutex_lock (&usb_mtx);
407               if (fsij_device_state != FSIJ_DEVICE_EXITED)
408                 {
409                   chopstx_mutex_unlock (&usb_mtx);
410                   return USB_UNSUPPORT;
411                 }
412               chopstx_mutex_unlock (&usb_mtx);
413               usb_lld_reply_request (mem_info, sizeof (mem_info), detail);
414               return USB_SUCCESS;
415             }
416           else if (req_no == USB_NEUG_GET_INFO)
417             {
418               if (detail->index == 0)
419                 usb_lld_reply_request (&neug_mode, sizeof (uint8_t), detail);
420               else if (detail->index == 1)
421                 usb_lld_reply_request (&neug_err_cnt, sizeof (uint16_t), detail);
422               else if (detail->index == 2)
423                 usb_lld_reply_request (&neug_err_cnt_rc, sizeof (uint16_t), detail);
424               else if (detail->index == 3)
425                 usb_lld_reply_request (&neug_err_cnt_p64, sizeof (uint16_t), detail);
426               else if (detail->index == 4)
427                 usb_lld_reply_request (&neug_err_cnt_p4k, sizeof (uint16_t), detail);
428               else if (detail->index == 5)
429                 usb_lld_reply_request (&neug_rc_max, sizeof (uint16_t), detail);
430               else if (detail->index == 6)
431                 usb_lld_reply_request (&neug_p64_max, sizeof (uint16_t), detail);
432               else if (detail->index == 7)
433                 usb_lld_reply_request (&neug_p4k_max, sizeof (uint16_t), detail);
434               else
435                 return USB_UNSUPPORT;
436
437               return USB_SUCCESS;
438             }
439         }
440       else /* SETUP_SET */
441         {
442           uint8_t *addr = (uint8_t *)(0x20000000 + detail->value * 0x100 + detail->index);
443
444           if (req_no == USB_FSIJ_DOWNLOAD)
445             {
446               chopstx_mutex_lock (&usb_mtx);
447               if (fsij_device_state != FSIJ_DEVICE_EXITED)
448                 {
449                   chopstx_mutex_unlock (&usb_mtx);
450                   return USB_UNSUPPORT;
451                 }
452               chopstx_mutex_unlock (&usb_mtx);
453
454               if (addr < &_regnual_start || addr + detail->len > &__heap_end__)
455                 return USB_UNSUPPORT;
456
457               if (detail->index + detail->len < 256)
458                 memset (addr + detail->index + detail->len, 0, 256 - (detail->index + detail->len));
459
460               usb_lld_set_data_to_recv (addr, detail->len);
461               return USB_SUCCESS;
462             }
463           else if (req_no == USB_FSIJ_EXEC && detail->len == 0)
464             {
465               chopstx_mutex_lock (&usb_mtx);
466               if (fsij_device_state != FSIJ_DEVICE_EXITED)
467                 {
468                   chopstx_mutex_unlock (&usb_mtx);
469                   return USB_UNSUPPORT;
470                 }
471               chopstx_mutex_unlock (&usb_mtx);
472
473               if (((uint32_t)addr & 0x03))
474                 return USB_UNSUPPORT;
475
476               return download_check_crc32 ((uint32_t *)addr);
477             }
478           else if (req_no == USB_NEUG_SET_PASSWD && detail->len <= 32)
479             {
480               usbbuf[0] = detail->len;
481               usb_lld_set_data_to_recv (usbbuf + 1, detail->len);
482               return USB_SUCCESS;
483             }
484           else if (req_no == USB_NEUG_EXIT && detail->len <= 32)
485             {
486               chopstx_mutex_lock (&usb_mtx);
487               if (fsij_device_state != FSIJ_DEVICE_RUNNING)
488                 {
489                   chopstx_mutex_unlock (&usb_mtx);
490                   return USB_UNSUPPORT;
491                 }
492               chopstx_mutex_unlock (&usb_mtx);
493
494               usbbuf[0] = detail->len;
495               usb_lld_set_data_to_recv (usbbuf + 1, detail->len);
496               return USB_SUCCESS;
497             }
498         }
499     }
500   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
501            && detail->index == 0)
502     {
503 #ifdef FRAUCHEKY_SUPPORT
504       if (running_neug)
505         return vcom_port_data_setup (req, req_no, detail);
506       else
507         fraucheky_setup (req, req_no, detail);
508 #else
509       return vcom_port_data_setup (req, req_no, detail);
510 #endif
511     }
512
513   return USB_UNSUPPORT;
514 }
515
516 int
517 usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
518                        struct control_info *detail)
519 {
520 #ifdef FRAUCHEKY_SUPPORT
521   if (!running_neug)
522     return fraucheky_get_descriptor (rcp, desc_type, desc_index, detail);
523 #endif
524
525   if (rcp != DEVICE_RECIPIENT)
526     return USB_UNSUPPORT;
527
528   if (desc_type == DEVICE_DESCRIPTOR)
529     return usb_lld_reply_request (vcom_device_desc, sizeof (vcom_device_desc),
530                                   detail);
531   else if (desc_type == CONFIG_DESCRIPTOR)
532     return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
533                                   detail);
534   else if (desc_type == STRING_DESCRIPTOR)
535     {
536       const uint8_t *str;
537       int size;
538
539       switch (desc_index)
540         {
541         case 0:
542           str = vcom_string0;
543           size = sizeof (vcom_string0);
544           break;
545         case 1:
546           str = neug_string_vendor;
547           size = sizeof (neug_string_vendor);
548           break;
549         case 2:
550           str = neug_string_product;
551           size = sizeof (neug_string_product);
552           break;
553         case 3:
554           str = neug_string_serial;
555           size = sizeof (neug_string_serial);
556           break;
557         case 4:
558           str = neug_revision_detail;
559           size = sizeof (neug_revision_detail);
560           break;
561         case 5:
562           str = neug_config_options;
563           size = sizeof (neug_config_options);
564           break;
565         case 6:
566           str = sys_version;
567           size = sizeof (sys_version);
568           break;
569         case 7:
570           {
571             int i;
572             str = usbbuf;
573             for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
574               {
575                 if (sys_board_name[i] == 0)
576                   break;
577
578                 usbbuf[i*2+2] = sys_board_name[i];
579                 usbbuf[i*2+3] = 0;
580               }
581             usbbuf[0] = i*2 + 2;
582             usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
583             size = i*2 + 2;
584           }
585           break;
586         default:
587           return USB_UNSUPPORT;
588         }
589
590       return usb_lld_reply_request (str, size, detail);
591     }
592
593   return USB_UNSUPPORT;
594 }
595
596 static void
597 neug_setup_endpoints_for_interface (uint16_t interface, int stop)
598 {
599   if (interface == 0)
600     {
601 #ifdef FRAUCHEKY_SUPPORT
602       if (running_neug)
603         {
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         }
609       else
610         fraucheky_setup_endpoints_for_interface (stop);
611 #else
612       if (!stop)
613         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
614       else
615         usb_lld_stall_tx (ENDP2);
616 #endif
617     }
618   else if (interface == 1)
619     {
620       if (!stop)
621         {
622           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
623           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
624         }
625       else
626         {
627           usb_lld_stall_tx (ENDP1);
628           usb_lld_stall_rx (ENDP3);
629         }
630     }
631 }
632
633 int usb_cb_handle_event (uint8_t event_type, uint16_t value)
634 {
635   int i;
636   uint8_t current_conf;
637
638   switch (event_type)
639     {
640     case USB_EVENT_ADDRESS:
641       chopstx_mutex_lock (&usb_mtx);
642       bDeviceState = ADDRESSED;
643       chopstx_mutex_unlock (&usb_mtx);
644       return USB_SUCCESS;
645     case USB_EVENT_CONFIG:
646       current_conf = usb_lld_current_configuration ();
647       if (current_conf == 0)
648         {
649           if (value != 1)
650             return USB_UNSUPPORT;
651
652           usb_lld_set_configuration (1);
653           for (i = 0; i < NUM_INTERFACES; i++)
654             neug_setup_endpoints_for_interface (i, 0);
655           chopstx_mutex_lock (&usb_mtx);
656           bDeviceState = CONFIGURED;
657           chopstx_mutex_unlock (&usb_mtx);
658         }
659       else if (current_conf != value)
660         {
661           if (value != 0)
662             return USB_UNSUPPORT;
663
664           usb_lld_set_configuration (0);
665           for (i = 0; i < NUM_INTERFACES; i++)
666             neug_setup_endpoints_for_interface (i, 1);
667           chopstx_mutex_lock (&usb_mtx);
668           bDeviceState = ADDRESSED;
669           chopstx_mutex_unlock (&usb_mtx);
670         }
671       /* Do nothing when current_conf == value */
672       return USB_SUCCESS;
673
674       return USB_SUCCESS;
675     default:
676       break;
677     }
678
679   return USB_UNSUPPORT;
680 }
681
682
683 int usb_cb_interface (uint8_t cmd, struct control_info *detail)
684 {
685   const uint8_t zero = 0;
686   uint16_t interface = detail->index;
687   uint16_t alt = detail->value;
688
689   if (interface >= NUM_INTERFACES)
690     return USB_UNSUPPORT;
691
692   switch (cmd)
693     {
694     case USB_SET_INTERFACE:
695       if (alt != 0)
696         return USB_UNSUPPORT;
697       else
698         {
699           neug_setup_endpoints_for_interface (interface, 0);
700           return USB_SUCCESS;
701         }
702
703     case USB_GET_INTERFACE:
704       usb_lld_reply_request (&zero, 1, detail);
705       return USB_SUCCESS;
706
707     default:
708     case USB_QUERY_INTERFACE:
709       return USB_SUCCESS;
710     }
711 }
712
713 #define INTR_REQ_USB 20
714 #define PRIO_USB 3
715
716 static void *
717 usb_intr (void *arg)
718 {
719   chopstx_intr_t interrupt;
720
721   (void)arg;
722   usb_lld_init (vcom_config_desc[7]);
723   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
724   usb_interrupt_handler ();
725
726   while (1)
727     {
728       chopstx_intr_wait (&interrupt);
729
730       /* Process interrupt. */
731       usb_interrupt_handler ();
732     }
733
734   return NULL;
735 }
736
737 #define ID_OFFSET (2+SERIALNO_STR_LEN*2)
738 static void fill_serial_no_by_unique_id (void)
739 {
740   extern const uint8_t * unique_device_id (void);
741   uint8_t *p = &neug_string_serial[ID_OFFSET];
742   const uint8_t *u = unique_device_id () + 8;
743   int i;
744
745   for (i = 0; i < 4; i++)
746     {
747       uint8_t b = u[3-i];
748       uint8_t nibble;
749
750       nibble = (b >> 4);
751       nibble += (nibble >= 10 ? ('A' - 10) : '0');
752       p[i*4] = nibble;
753       p[i*4+1] = 0;
754       nibble = (b & 0x0f);
755       nibble += (nibble >= 10 ? ('A' - 10) : '0');
756       p[i*4+2] = nibble;
757       p[i*4+3] = 0;
758     }
759 }
760 \f
761 void
762 EP1_IN_Callback (void)
763 {
764   chopstx_mutex_lock (&usb_mtx);
765   chopstx_cond_signal (&cnd_usb);
766   chopstx_mutex_unlock (&usb_mtx);
767 }
768
769 void
770 EP2_IN_Callback (void)
771 {
772 }
773
774 void
775 EP3_OUT_Callback (void)
776 {
777   usb_lld_rx_enable (ENDP3);
778 }
779 \f
780 typedef uint32_t eventmask_t;
781 #define ALL_EVENTS (~0)
782
783 struct event_flag {
784   chopstx_mutex_t mutex;
785   chopstx_cond_t cond;
786   eventmask_t flag;
787 };
788
789 static void event_flag_init (struct event_flag *ev)
790 {
791   ev->flag = 0;
792   chopstx_mutex_init (&ev->mutex);
793   chopstx_cond_init (&ev->cond);
794 }
795
796
797 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
798 {
799   int n;
800
801   chopstx_mutex_lock (&ev->mutex);
802   while (!(ev->flag & m))
803     chopstx_cond_wait (&ev->cond, &ev->mutex);
804
805   n = __builtin_ffs ((ev->flag & m));
806   ev->flag &= ~(1 << (n - 1));
807   chopstx_mutex_unlock (&ev->mutex);
808
809   return (1 << (n - 1));
810 }
811
812 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
813 {
814   chopstx_mutex_lock (&ev->mutex);
815   ev->flag |= m;
816   chopstx_cond_signal (&ev->cond);
817   chopstx_mutex_unlock (&ev->mutex);
818 }
819
820 extern uint8_t __process1_stack_base__, __process1_stack_size__;
821 extern uint8_t __process3_stack_base__, __process3_stack_size__;
822
823 const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
824 const size_t __stacksize_led = (size_t)&__process1_stack_size__;
825 const uint32_t __stackaddr_usb = (uint32_t)&__process3_stack_base__;
826 const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
827
828
829 #define PRIO_LED 3
830 static struct event_flag led_event;
831
832 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
833 #define LED_TWOSHOTS            ((eventmask_t)2)
834 #define LED_ONESHOT_LONG        ((eventmask_t)4)
835
836 /*
837  * LED blinker: When notified, let LED emit for 100ms.
838  */
839 static void *
840 led_blinker (void *arg)
841 {
842   (void)arg;
843
844   set_led (0);
845
846   while (1)
847     {
848       eventmask_t m;
849
850       m = event_flag_waitone (&led_event, ALL_EVENTS);
851
852       set_led (1);
853       if (m == LED_ONESHOT_SHORT)
854         chopstx_usec_wait (100*1000);
855       else if (m == LED_TWOSHOTS)
856         {
857           chopstx_usec_wait (50*1000);
858           set_led (0);
859           chopstx_usec_wait (50*1000);
860           set_led (1);
861           chopstx_usec_wait (50*1000);
862         }
863       else
864         chopstx_usec_wait (250*1000);
865       set_led (0);
866     }
867
868   return NULL;
869 }
870 \f
871 #define RANDOM_BYTES_LENGTH 64
872 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
873
874 static void copy_to_tx (uint32_t v, int i)
875 {
876   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
877 }
878
879 /*
880  * In Gnuk 1.0.[12], reGNUal was not relocatable.
881  * Now, it's relocatable, but we need to calculate its entry address
882  * based on it's pre-defined address.
883  */
884 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
885 static uint32_t
886 calculate_regnual_entry_address (const uint8_t *addr)
887 {
888   const uint8_t *p = addr + 4;
889   uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
890
891   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
892   v += (uint32_t)addr;
893   return v;
894 }
895
896
897 /*
898  * Entry point.
899  *
900  * NOTE: the main function is already a thread in the system on entry.
901  */
902 int
903 main (int argc, char **argv)
904 {
905   uint32_t entry;
906   chopstx_t led_thread, usb_thd;
907   unsigned int count;
908
909   (void)argc;
910   (void)argv;
911
912   fill_serial_no_by_unique_id ();
913
914   adc_init ();
915
916   event_flag_init (&led_event);
917
918   chopstx_mutex_init (&usb_mtx);
919   chopstx_cond_init (&cnd_usb);
920
921 #ifdef FRAUCHEKY_SUPPORT
922   if (fraucheky_enabled ())
923     {
924     go_fraucheky:
925       running_neug = 0;
926       usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
927                                 usb_intr, NULL);
928       set_led (1);
929       fraucheky_main ();
930       chopstx_cancel (usb_thd);
931       chopstx_join (usb_thd, NULL);
932       usb_lld_shutdown ();
933     }
934
935   running_neug = 1;
936 #endif
937
938   led_thread = chopstx_create (PRIO_LED, __stackaddr_led, __stacksize_led,
939                                led_blinker, NULL);
940
941   usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
942                             usb_intr, NULL);
943
944   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
945
946   chopstx_mutex_lock (&usb_mtx);
947
948  not_configured:
949   count = 0;
950   /* A run-up */
951   while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
952     {
953       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
954         break;
955
956       chopstx_mutex_unlock (&usb_mtx);
957       neug_wait_full ();
958       neug_flush ();
959
960       if ((count & 0x0007) == 0)
961         event_flag_signal (&led_event, LED_ONESHOT_SHORT);
962       chopstx_usec_wait (25*1000);
963       count++;
964       chopstx_mutex_lock (&usb_mtx);
965     }
966
967   /* Holding USB_MTX.  */
968   while (1)
969     {
970       int last_was_fullsizepacket = 0;
971
972       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
973         break;
974
975       while (1)
976         {
977           wait_usb_connection = 5000*1000;
978           if (connected || bDeviceState != CONFIGURED
979               || fsij_device_state != FSIJ_DEVICE_RUNNING)
980             break;
981
982           chopstx_mutex_unlock (&usb_mtx);
983           neug_flush ();
984           neug_mode_select (line_coding.paritytype);
985           event_flag_signal (&led_event, LED_TWOSHOTS);
986           chopstx_usec_wait_var (&wait_usb_connection);
987           chopstx_mutex_lock (&usb_mtx);
988         }
989
990       if (bDeviceState != CONFIGURED)
991         goto not_configured;
992
993       /* The connection opened.  */
994       count = 0;
995
996       while (1)
997         {
998           int i;
999
1000           chopstx_mutex_unlock (&usb_mtx);
1001           /*
1002            * No parity is standard.  It means providing conditioned output.
1003            * When parity enabled, it means to provide raw output
1004            * (CRC32 filtered when odd, direct sample of ADC when even).
1005            *
1006            * line_coding.paritytype:
1007            *   0: None, 1: Odd, 2: Even
1008            */
1009           neug_mode_select (line_coding.paritytype);
1010
1011           if ((count & 0x03ff) == 0)
1012             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1013
1014           i = neug_consume_random (copy_to_tx);
1015
1016           if (i == 0 && !last_was_fullsizepacket)
1017             {    /* Only send ZLP when the last packet was fullsize.  */
1018               neug_wait_full ();
1019
1020               chopstx_mutex_lock (&usb_mtx);
1021               if (bDeviceState != CONFIGURED || !connected
1022                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1023                 break;
1024             }
1025           else
1026             {
1027               if (i == 64/4)
1028                 last_was_fullsizepacket = 1;
1029               else
1030                 last_was_fullsizepacket = 0;
1031
1032               chopstx_mutex_lock (&usb_mtx);
1033               if (bDeviceState != CONFIGURED || !connected
1034                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1035                 break;
1036
1037               /* Prepare sending random data.  */
1038               usb_lld_tx_enable (ENDP1, i * 4);
1039               chopstx_cond_wait (&cnd_usb, &usb_mtx);
1040               count++;
1041             }
1042         }
1043     }
1044
1045   chopstx_mutex_unlock (&usb_mtx);
1046
1047   chopstx_cancel (led_thread);
1048   chopstx_join (led_thread, NULL);
1049
1050   /*
1051    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED
1052    * or FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED.
1053    */
1054   neug_fini ();
1055
1056   chopstx_mutex_lock (&usb_mtx);
1057 #ifdef FRAUCHEKY_SUPPORT
1058   if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
1059     {
1060       while (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
1061         {
1062           chopstx_mutex_unlock (&usb_mtx);
1063           set_led (1);
1064           chopstx_usec_wait (500*1000);
1065           set_led (0);
1066           chopstx_usec_wait (500*1000);
1067           chopstx_mutex_lock (&usb_mtx);
1068         }
1069
1070       usb_lld_prepare_shutdown ();
1071       chopstx_mutex_unlock (&usb_mtx);
1072       chopstx_cancel (usb_thd);
1073       chopstx_join (usb_thd, NULL);
1074       usb_lld_shutdown ();
1075       goto go_fraucheky;
1076     }
1077 #endif
1078
1079   fsij_device_state = FSIJ_DEVICE_EXITED;
1080
1081   while (fsij_device_state == FSIJ_DEVICE_EXITED)
1082     {
1083       chopstx_mutex_unlock (&usb_mtx);
1084       chopstx_usec_wait (500*1000);
1085       chopstx_mutex_lock (&usb_mtx);
1086     }
1087   chopstx_mutex_unlock (&usb_mtx);
1088
1089   flash_unlock ();              /* Flash unlock should be done here */
1090   set_led (1);
1091   usb_lld_shutdown ();
1092
1093   /* Finish application.  */
1094   chopstx_cancel (usb_thd);
1095   chopstx_join (usb_thd, NULL);
1096
1097   /* Set vector */
1098   SCB->VTOR = (uint32_t)&_regnual_start;
1099   entry = calculate_regnual_entry_address (&_regnual_start);
1100 #ifdef DFU_SUPPORT
1101 #define FLASH_SYS_START_ADDR 0x08000000
1102 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
1103 #define CHIP_ID_REG ((uint32_t *)0xE0042000)
1104   {
1105     extern uint8_t _sys;
1106     uint32_t addr;
1107     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
1108     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
1109     uint32_t flash_page_size = 1024; /* 1KiB default */
1110
1111    if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device.  */
1112      flash_page_size += 0x0400; /* It's 2KiB. */
1113
1114     /* Kill DFU */
1115     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
1116          addr += flash_page_size)
1117       flash_erase_page (addr);
1118
1119     /* copy system service routines */
1120     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
1121
1122     /* Leave NeuG to exec reGNUal */
1123     (*func) ((void (*)(void))entry);
1124     for (;;);
1125   }
1126 #else
1127   /* Leave NeuG to exec reGNUal */
1128   flash_erase_all_and_exec ((void (*)(void))entry);
1129 #endif
1130
1131   /* Never reached */
1132   return 0;
1133 }