Update main.c for GNU/Linux emulation.
[gnuk/neug.git] / src / main.c
1 /*
2  * main.c - main routine of neug
3  *
4  * Main routine:
5  * Copyright (C) 2011, 2012, 2013, 2015, 2016, 2017
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 #ifndef GNU_LINUX_EMULATION
37 #include "mcu/stm32f103.h"
38 #endif
39 #include "adc.h"
40
41 enum {
42   FSIJ_DEVICE_RUNNING = 0,
43   FSIJ_DEVICE_EXITED,
44   FSIJ_DEVICE_EXEC_REQUESTED,
45   /**/
46   FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED = 254,
47   FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
48 };
49
50 #ifdef FRAUCHEKY_SUPPORT
51 static uint8_t running_neug;
52 extern void EP6_IN_Callback (uint16_t len);
53 extern void EP6_OUT_Callback (uint16_t len);
54 #endif
55
56 static chopstx_mutex_t usb_mtx;
57 static chopstx_cond_t usb_cnd;
58 static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
59 static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
60 static uint8_t connected;
61
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   DEVICE_DESCRIPTOR,            /* 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 #define VCOM_FEATURE_BUS_POWERED        0x80
91
92 /* Configuration Descriptor tree for a CDC.*/
93 static const uint8_t vcom_config_desc[67] = {
94   9,
95   CONFIG_DESCRIPTOR,            /* bDescriptorType: Configuration   */
96   /* Configuration Descriptor.*/
97   67, 0x00,                     /* wTotalLength.                    */
98   0x02,                         /* bNumInterfaces.                  */
99   0x01,                         /* bConfigurationValue.             */
100   0,                            /* iConfiguration.                  */
101   VCOM_FEATURE_BUS_POWERED,     /* bmAttributes.                    */
102   50,                           /* bMaxPower (100mA).               */
103   /* Interface Descriptor.*/
104   9,
105   INTERFACE_DESCRIPTOR,
106   0x00,            /* bInterfaceNumber.                */
107   0x00,            /* bAlternateSetting.               */
108   0x01,            /* bNumEndpoints.                   */
109   0x02,            /* bInterfaceClass (Communications Interface Class,
110                       CDC section 4.2).  */
111   0x02,            /* bInterfaceSubClass (Abstract Control Model, CDC
112                       section 4.3).  */
113   0x01,            /* bInterfaceProtocol (AT commands, CDC section
114                       4.4).  */
115   0,               /* iInterface.                      */
116   /* Header Functional Descriptor (CDC section 5.2.3).*/
117   5,          /* bLength.                         */
118   0x24,       /* bDescriptorType (CS_INTERFACE).  */
119   0x00,       /* bDescriptorSubtype (Header Functional Descriptor). */
120   0x10, 0x01, /* bcdCDC.                          */
121   /* Call Management Functional Descriptor. */
122   5,            /* bFunctionLength.                 */
123   0x24,         /* bDescriptorType (CS_INTERFACE).  */
124   0x01,         /* bDescriptorSubtype (Call Management Functional
125                    Descriptor). */
126   0x03,         /* bmCapabilities (D0+D1).          */
127   0x01,         /* bDataInterface.                  */
128   /* ACM Functional Descriptor.*/
129   4,            /* bFunctionLength.                 */
130   0x24,         /* bDescriptorType (CS_INTERFACE).  */
131   0x02,         /* bDescriptorSubtype (Abstract Control Management
132                    Descriptor).  */
133   0x02,         /* bmCapabilities.                  */
134   /* Union Functional Descriptor.*/
135   5,            /* bFunctionLength.                 */
136   0x24,         /* bDescriptorType (CS_INTERFACE).  */
137   0x06,         /* bDescriptorSubtype (Union Functional
138                    Descriptor).  */
139   0x00,         /* bMasterInterface (Communication Class
140                    Interface).  */
141   0x01,         /* bSlaveInterface0 (Data Class Interface).  */
142   /* Endpoint 2 Descriptor.*/
143   7,
144   ENDPOINT_DESCRIPTOR,
145   ENDP2|0x80,    /* bEndpointAddress.    */
146   0x03,          /* bmAttributes (Interrupt).        */
147   0x08, 0x00,    /* wMaxPacketSize.                  */
148   0xFF,          /* bInterval.                       */
149   /* Interface Descriptor.*/
150   9,
151   INTERFACE_DESCRIPTOR,          /* bDescriptorType: */
152   0x01,          /* bInterfaceNumber.                */
153   0x00,          /* bAlternateSetting.               */
154   0x02,          /* bNumEndpoints.                   */
155   0x0A,          /* bInterfaceClass (Data Class Interface, CDC section 4.5). */
156   0x00,          /* bInterfaceSubClass (CDC section 4.6). */
157   0x00,          /* bInterfaceProtocol (CDC section 4.7). */
158   0x00,          /* iInterface.                      */
159   /* Endpoint 3 Descriptor.*/
160   7,
161   ENDPOINT_DESCRIPTOR,          /* bDescriptorType: Endpoint */
162   ENDP3,    /* bEndpointAddress. */
163   0x02,                         /* bmAttributes (Bulk).             */
164   0x40, 0x00,                   /* wMaxPacketSize.                  */
165   0x00,                         /* bInterval.                       */
166   /* Endpoint 1 Descriptor.*/
167   7,
168   ENDPOINT_DESCRIPTOR,          /* bDescriptorType: Endpoint */
169   ENDP1|0x80,                   /* bEndpointAddress. */
170   0x02,                         /* bmAttributes (Bulk).             */
171   0x40, 0x00,                   /* wMaxPacketSize.                  */
172   0x00                          /* bInterval.                       */
173 };
174
175
176 /*
177  * U.S. English language identifier.
178  */
179 static const uint8_t vcom_string0[4] = {
180   4,                            /* bLength */
181   STRING_DESCRIPTOR,
182   0x09, 0x04                    /* LangID = 0x0409: US-English */
183 };
184
185 #include "usb-strings.c.inc"
186
187 static void neug_setup_endpoints_for_interface (struct usb_dev *dev,
188                                                 uint16_t interface, int stop);
189 #ifdef FRAUCHEKY_SUPPORT
190 #define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
191 extern int fraucheky_enabled (void);
192 extern void fraucheky_main (void);
193
194 extern void fraucheky_setup_endpoints_for_interface (int stop);
195 extern int fraucheky_setup (struct usb_dev *dev);
196 extern int fraucheky_get_descriptor (struct usb_dev *dev);
197 #endif
198
199 #define NUM_INTERFACES 2
200
201 static void
202 usb_device_reset (struct usb_dev *dev)
203 {
204   int i;
205
206   usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
207
208   /* Initialize Endpoint 0.  */
209 #ifdef GNU_LINUX_EMULATION
210   usb_lld_setup_endp (dev, ENDP0, 1, 1);
211 #else
212   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
213 #endif
214
215   /* Stop the interface */
216   for (i = 0; i < NUM_INTERFACES; i++)
217     neug_setup_endpoints_for_interface (dev, i, 1);
218
219   /* Notify upper layer.  */
220   chopstx_mutex_lock (&usb_mtx);
221   bDeviceState = ATTACHED;
222   connected = 0;
223   chopstx_cond_signal (&usb_cnd);
224   chopstx_mutex_unlock (&usb_mtx);
225 }
226
227 #ifndef GNU_LINUX_EMULATION
228 extern uint8_t _regnual_start, __heap_end__;
229
230 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
231 #endif
232
233 /* USB vendor requests to control pipe */
234 #define USB_FSIJ_MEMINFO          0
235 #define USB_FSIJ_DOWNLOAD         1
236 #define USB_FSIJ_EXEC             2
237 #define USB_NEUG_SET_PASSWD     253
238 #define USB_NEUG_GET_INFO       254
239 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
240
241 #define DEFAULT_PASSWD "12345678"
242 #define DEFAULT_PASSWD_LEN 8
243
244 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
245   0xff,
246   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
247   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
248   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
249 };
250 static uint8_t usbbuf[64];
251
252 #ifndef GNU_LINUX_EMULATION
253 static void set_passwd (void)
254 {
255   flash_unlock ();
256   if (neug_passwd[0] != 0xff)
257     flash_erase_page ((uintptr_t)neug_passwd);
258   if (usbbuf[0] == DEFAULT_PASSWD_LEN
259       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
260     return;
261   flash_write ((uintptr_t)neug_passwd, usbbuf, usbbuf[0] + 1);
262 }
263
264
265 /* After calling this function, CRC module remain enabled.  */
266 static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
267 {
268   uint32_t crc32 = *end_p;
269   const uint32_t *p;
270
271   crc32_rv_reset ();
272
273   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
274     crc32_rv_step (rbit (*p));
275
276   if ((rbit (crc32_rv_get ()) ^ crc32) == 0xffffffff)
277     return usb_lld_ctrl_ack (dev);
278
279   return -1;
280 }
281 #endif
282
283
284 #define NEUG_SPECIAL_BITRATE 110
285
286 struct line_coding
287 {
288   uint32_t bitrate;
289   uint8_t format;
290   uint8_t paritytype;
291   uint8_t datatype;
292 } __attribute__((packed));
293
294 static struct line_coding line_coding = {
295   115200, /* baud rate: 115200    */
296   0x00,   /* stop bits: 1         */
297   0x00,   /* parity:    none      */
298   0x08    /* bits:      8         */
299 };
300
301 #define CDC_CTRL_DTR            0x0001
302
303 static void
304 usb_ctrl_write_finish (struct usb_dev *dev)
305 {
306   struct device_req *arg = &dev->dev_req;
307   uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
308
309   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
310       && USB_SETUP_SET (arg->type))
311     {
312       if (arg->request == USB_FSIJ_EXEC)
313         {
314           chopstx_mutex_lock (&usb_mtx);
315           if (fsij_device_state == FSIJ_DEVICE_EXITED)
316             {
317               usb_lld_prepare_shutdown (); /* No further USB communication */
318               fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
319             }
320           chopstx_mutex_unlock (&usb_mtx);
321         }
322 #ifndef GNU_LINUX_EMULATION
323       else if (arg->request == USB_NEUG_SET_PASSWD)
324         set_passwd ();
325 #endif
326       else if (arg->request == USB_NEUG_EXIT)
327         {
328           if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
329                && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
330 #ifndef GNU_LINUX_EMULATION
331               || (neug_passwd[0] == usbbuf[0]
332                   && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0]))
333 #endif
334               )
335             {
336               chopstx_mutex_lock (&usb_mtx);
337               fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
338               chopstx_cond_signal (&usb_cnd);
339               chopstx_mutex_unlock (&usb_mtx);
340             }
341         }
342     }
343   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
344            && USB_SETUP_SET (arg->type))
345     {
346       if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
347         {
348           /* Open/close the connection.  */
349           chopstx_mutex_lock (&usb_mtx);
350           connected = (arg->value & CDC_CTRL_DTR)? 1 : 0;
351           chopstx_cond_signal (&usb_cnd);
352           chopstx_mutex_unlock (&usb_mtx);
353         }
354 #ifdef FRAUCHEKY_SUPPORT
355       else if (running_neug && arg->request == USB_CDC_REQ_SET_LINE_CODING)
356         {
357           chopstx_mutex_lock (&usb_mtx);
358           if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
359             {
360               fsij_device_state = FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED;
361               chopstx_cond_signal (&usb_cnd);
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       else if (!running_neug && arg->request == MSC_MASS_STORAGE_RESET_COMMAND)
368         fraucheky_setup_endpoints_for_interface (0);
369 #endif
370     }
371 }
372
373
374 static int
375 vcom_port_data_setup (struct usb_dev *dev)
376 {
377   struct device_req *arg = &dev->dev_req;
378
379   if (USB_SETUP_GET (arg->type))
380     {
381       if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
382         return usb_lld_ctrl_send (dev, &line_coding, sizeof(line_coding));
383     }
384   else  /* USB_SETUP_SET (req) */
385     {
386       if (arg->request == USB_CDC_REQ_SET_LINE_CODING
387           && arg->len == sizeof (line_coding))
388         return usb_lld_ctrl_recv (dev, &line_coding, sizeof (line_coding));
389       else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
390         return usb_lld_ctrl_ack (dev);
391     }
392
393   return -1;
394 }
395
396 static int
397 usb_setup (struct usb_dev *dev)
398 {
399   struct device_req *arg = &dev->dev_req;
400   uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
401
402   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
403     {
404       if (USB_SETUP_GET (arg->type))
405         {
406           if (arg->request == USB_FSIJ_MEMINFO)
407             {
408 #ifdef GNU_LINUX_EMULATION
409               return -1;
410 #else
411               chopstx_mutex_lock (&usb_mtx);
412               if (fsij_device_state != FSIJ_DEVICE_EXITED)
413                 {
414                   chopstx_mutex_unlock (&usb_mtx);
415                   return -1;
416                 }
417               chopstx_mutex_unlock (&usb_mtx);
418               return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
419 #endif
420             }
421           else if (arg->request == USB_NEUG_GET_INFO)
422             {
423               if (arg->index == 0)
424                 return usb_lld_ctrl_send (dev, &neug_mode, sizeof (uint8_t));
425               else if (arg->index == 1)
426                 return usb_lld_ctrl_send (dev, &neug_err_cnt, sizeof (uint16_t));
427               else if (arg->index == 2)
428                 return usb_lld_ctrl_send (dev, &neug_err_cnt_rc, sizeof (uint16_t));
429               else if (arg->index == 3)
430                 return usb_lld_ctrl_send (dev, &neug_err_cnt_p64, sizeof (uint16_t));
431               else if (arg->index == 4)
432                 return usb_lld_ctrl_send (dev, &neug_err_cnt_p4k, sizeof (uint16_t));
433               else if (arg->index == 5)
434                 return usb_lld_ctrl_send (dev, &neug_rc_max, sizeof (uint16_t));
435               else if (arg->index == 6)
436                 return usb_lld_ctrl_send (dev, &neug_p64_max, sizeof (uint16_t));
437               else if (arg->index == 7)
438                 return usb_lld_ctrl_send (dev, &neug_p4k_max, sizeof (uint16_t));
439               else
440                 return -1;
441             }
442         }
443       else /* SETUP_SET */
444         {
445           uint8_t *addr = (uint8_t *)(0x20000000UL + arg->value * 0x100 + arg->index);
446
447           if (arg->request == USB_FSIJ_DOWNLOAD)
448             {
449 #ifdef GNU_LINUX_EMULATION
450               return -1;
451 #else
452               chopstx_mutex_lock (&usb_mtx);
453               if (fsij_device_state != FSIJ_DEVICE_EXITED)
454                 {
455                   chopstx_mutex_unlock (&usb_mtx);
456                   return -1;
457                 }
458               chopstx_mutex_unlock (&usb_mtx);
459
460               if (addr < &_regnual_start || addr + arg->len > &__heap_end__)
461                 return -1;
462
463               if (arg->index + arg->len < 256)
464                 memset (addr + arg->index + arg->len, 0, 256 - (arg->index + arg->len));
465
466               return usb_lld_ctrl_recv (dev, addr, arg->len);
467 #endif
468             }
469           else if (arg->request == USB_FSIJ_EXEC && arg->len == 0)
470             {
471 #ifdef GNU_LINUX_EMULATION
472               return -1;
473 #else
474               chopstx_mutex_lock (&usb_mtx);
475               if (fsij_device_state != FSIJ_DEVICE_EXITED)
476                 {
477                   chopstx_mutex_unlock (&usb_mtx);
478                   return -1;
479                 }
480               chopstx_mutex_unlock (&usb_mtx);
481
482               if (((uintptr_t)addr & 0x03))
483                 return -1;
484
485               return download_check_crc32 (dev, (uint32_t *)addr);
486 #endif
487             }
488           else if (arg->request == USB_NEUG_SET_PASSWD && arg->len <= 32)
489             {
490               usbbuf[0] = arg->len;
491               return usb_lld_ctrl_recv (dev, usbbuf + 1, arg->len);
492             }
493           else if (arg->request == USB_NEUG_EXIT && arg->len <= 32)
494             {
495               chopstx_mutex_lock (&usb_mtx);
496               if (fsij_device_state != FSIJ_DEVICE_RUNNING)
497                 {
498                   chopstx_mutex_unlock (&usb_mtx);
499                   return -1;
500                 }
501               chopstx_mutex_unlock (&usb_mtx);
502
503               usbbuf[0] = arg->len;
504               return usb_lld_ctrl_recv (dev, usbbuf + 1, arg->len);
505             }
506         }
507     }
508   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
509            && arg->index == 0)
510     {
511 #ifdef FRAUCHEKY_SUPPORT
512       if (running_neug)
513         return vcom_port_data_setup (dev);
514       else
515         return fraucheky_setup (dev);
516 #else
517       return vcom_port_data_setup (dev);
518 #endif
519     }
520
521   return -1;
522 }
523
524 static int
525 usb_get_descriptor (struct usb_dev *dev)
526 {
527   struct device_req *arg = &dev->dev_req;
528   uint8_t rcp = arg->type & RECIPIENT;
529   uint8_t desc_type = (arg->value >> 8);
530   uint8_t desc_index = (arg->value & 0xff);
531
532 #ifdef FRAUCHEKY_SUPPORT
533   if (!running_neug)
534     return fraucheky_get_descriptor (dev);
535 #endif
536
537   if (rcp != DEVICE_RECIPIENT)
538     return -1;
539
540   if (desc_type == DEVICE_DESCRIPTOR)
541     return usb_lld_ctrl_send (dev,
542                               vcom_device_desc, sizeof (vcom_device_desc));
543   else if (desc_type == CONFIG_DESCRIPTOR)
544     return usb_lld_ctrl_send (dev,
545                               vcom_config_desc, sizeof (vcom_config_desc));
546   else if (desc_type == STRING_DESCRIPTOR)
547     {
548       const uint8_t *str;
549       int size;
550
551       switch (desc_index)
552         {
553         case 0:
554           str = vcom_string0;
555           size = sizeof (vcom_string0);
556           break;
557         case 1:
558           str = neug_string_vendor;
559           size = sizeof (neug_string_vendor);
560           break;
561         case 2:
562           str = neug_string_product;
563           size = sizeof (neug_string_product);
564           break;
565         case 3:
566           str = neug_string_serial;
567           size = sizeof (neug_string_serial);
568           break;
569         case 4:
570           str = neug_revision_detail;
571           size = sizeof (neug_revision_detail);
572           break;
573         case 5:
574           str = neug_config_options;
575           size = sizeof (neug_config_options);
576           break;
577         case 6:
578           str = sys_version;
579           size = sizeof (sys_version);
580           break;
581 #ifdef USE_SYS3
582         case 7:
583           {
584             int i;
585             str = usbbuf;
586             for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
587               {
588                 if (sys_board_name[i] == 0)
589                   break;
590
591                 usbbuf[i*2+2] = sys_board_name[i];
592                 usbbuf[i*2+3] = 0;
593               }
594             usbbuf[0] = i*2 + 2;
595             usbbuf[1] = STRING_DESCRIPTOR;
596             size = i*2 + 2;
597           }
598           break;
599 #endif
600         default:
601           return -1;
602         }
603
604       return usb_lld_ctrl_send (dev, str, size);
605     }
606
607   return -1;
608 }
609
610 static void
611 neug_setup_endpoints_for_interface (struct usb_dev *dev,
612                                     uint16_t interface, int stop)
613 {
614 #if !defined(GNU_LINUX_EMULATION)
615   (void)dev;
616 #endif
617   
618   if (interface == 0)
619     {
620 #ifdef FRAUCHEKY_SUPPORT
621       if (running_neug)
622         {
623           if (!stop)
624 #ifdef GNU_LINUX_EMULATION
625             usb_lld_setup_endp (dev, ENDP2, 0, 1);
626 #else
627             usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
628 #endif
629           else
630             usb_lld_stall_tx (ENDP2);
631         }
632       else
633         fraucheky_setup_endpoints_for_interface (stop);
634 #else
635       if (!stop)
636 #ifdef GNU_LINUX_EMULATION
637         usb_lld_setup_endp (dev, ENDP2, 0, 1);
638 #else
639         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
640 #endif
641       else
642         usb_lld_stall_tx (ENDP2);
643 #endif
644     }
645   else if (interface == 1)
646     {
647       if (!stop)
648         {
649 #ifdef GNU_LINUX_EMULATION
650           usb_lld_setup_endp (dev, ENDP1, 0, 1);
651           usb_lld_setup_endp (dev, ENDP3, 1, 0);
652 #else
653           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
654           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
655 #endif
656           /* Start with no data receiving (ENDP3 not enabled) */
657         }
658       else
659         {
660           usb_lld_stall_tx (ENDP1);
661           usb_lld_stall_rx (ENDP3);
662         }
663     }
664 }
665
666 static int
667 usb_set_configuration (struct usb_dev *dev)
668 {
669   int i;
670   uint8_t current_conf;
671
672   current_conf = usb_lld_current_configuration (dev);
673   if (current_conf == 0)
674     {
675       if (dev->dev_req.value != 1)
676         return -1;
677
678       usb_lld_set_configuration (dev, 1);
679       for (i = 0; i < NUM_INTERFACES; i++)
680         neug_setup_endpoints_for_interface (dev, i, 0);
681       chopstx_mutex_lock (&usb_mtx);
682       bDeviceState = CONFIGURED;
683       chopstx_mutex_unlock (&usb_mtx);
684     }
685   else if (current_conf != dev->dev_req.value)
686     {
687       if (dev->dev_req.value != 0)
688         return -1;
689
690       usb_lld_set_configuration (dev, 0);
691       for (i = 0; i < NUM_INTERFACES; i++)
692         neug_setup_endpoints_for_interface (dev, i, 1);
693       chopstx_mutex_lock (&usb_mtx);
694       bDeviceState = ADDRESSED;
695       chopstx_cond_signal (&usb_cnd);
696       chopstx_mutex_unlock (&usb_mtx);
697     }
698
699   /* Do nothing when current_conf == value */
700   return usb_lld_ctrl_ack (dev);
701 }
702
703
704 static int
705 usb_set_interface (struct usb_dev *dev)
706 {
707   uint16_t interface = dev->dev_req.index;
708   uint16_t alt = dev->dev_req.value;
709
710   if (interface >= NUM_INTERFACES)
711     return -1;
712
713   if (alt != 0)
714     return -1;
715   else
716     {
717       neug_setup_endpoints_for_interface (dev, interface, 0);
718       return usb_lld_ctrl_ack (dev);
719     }
720 }
721
722 static int
723 usb_get_interface (struct usb_dev *dev)
724 {
725   const uint8_t zero = 0;
726   uint16_t interface = dev->dev_req.index;
727
728   if (interface >= NUM_INTERFACES)
729     return -1;
730
731   return usb_lld_ctrl_send (dev, &zero, 1);
732 }
733
734
735 static int
736 usb_get_status_interface (struct usb_dev *dev)
737 {
738   const uint16_t status_info = 0;
739   uint16_t interface = dev->dev_req.index;
740
741   if (interface >= NUM_INTERFACES)
742     return -1;
743
744   return usb_lld_ctrl_send (dev, &status_info, 2);
745 }
746
747 static void usb_tx_done (uint8_t ep_num, uint16_t len);
748 static void usb_rx_ready (uint8_t ep_num, uint16_t len);
749
750
751 #define INTR_REQ_USB 20
752 #define PRIO_USB 3
753
754 static void *
755 usb_main (void *arg)
756 {
757   chopstx_intr_t interrupt;
758   struct usb_dev dev;
759   int e;
760
761   (void)arg;
762   usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
763   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
764   goto event_handle;    /* For old SYS < 3.0 */
765
766   while (1)
767     {
768       chopstx_intr_wait (&interrupt);
769
770       if (interrupt.ready)
771         {
772           uint8_t ep_num;
773
774         event_handle:
775           e = usb_lld_event_handler (&dev);
776           ep_num = USB_EVENT_ENDP (e);
777
778           if (ep_num != 0)
779             {
780               if (USB_EVENT_TXRX (e))
781                 usb_tx_done (ep_num, USB_EVENT_LEN (e));
782               else
783                 usb_rx_ready (ep_num, USB_EVENT_LEN (e));
784             }
785           else
786             switch (USB_EVENT_ID (e))
787               {
788               case USB_EVENT_DEVICE_RESET:
789                 usb_device_reset (&dev);
790                 continue;
791
792               case USB_EVENT_DEVICE_ADDRESSED:
793                 chopstx_mutex_lock (&usb_mtx);
794                 bDeviceState = ADDRESSED;
795                 chopstx_cond_signal (&usb_cnd);
796                 chopstx_mutex_unlock (&usb_mtx);
797                 continue;
798
799               case USB_EVENT_GET_DESCRIPTOR:
800                 if (usb_get_descriptor (&dev) < 0)
801                   usb_lld_ctrl_error (&dev);
802                 continue;
803
804               case USB_EVENT_SET_CONFIGURATION:
805                 if (usb_set_configuration (&dev) < 0)
806                   usb_lld_ctrl_error (&dev);
807                 continue;
808
809               case USB_EVENT_SET_INTERFACE:
810                 if (usb_set_interface (&dev) < 0)
811                   usb_lld_ctrl_error (&dev);
812                 continue;
813
814               case USB_EVENT_CTRL_REQUEST:
815                 /* Device specific device request.  */
816                 if (usb_setup (&dev) < 0)
817                   usb_lld_ctrl_error (&dev);
818                 continue;
819
820               case USB_EVENT_GET_STATUS_INTERFACE:
821                 if (usb_get_status_interface (&dev) < 0)
822                   usb_lld_ctrl_error (&dev);
823                 continue;
824
825               case USB_EVENT_GET_INTERFACE:
826                 if (usb_get_interface (&dev) < 0)
827                   usb_lld_ctrl_error (&dev);
828                 continue;
829
830               case USB_EVENT_SET_FEATURE_DEVICE:
831               case USB_EVENT_SET_FEATURE_ENDPOINT:
832               case USB_EVENT_CLEAR_FEATURE_DEVICE:
833               case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
834                 usb_lld_ctrl_ack (&dev);
835                 continue;
836
837               case USB_EVENT_CTRL_WRITE_FINISH:
838                 /* Control WRITE transfer finished.  */
839                 usb_ctrl_write_finish (&dev);
840                 continue;
841
842               case USB_EVENT_OK:
843               case USB_EVENT_DEVICE_SUSPEND:
844               default:
845                 continue;
846               }
847         }
848     }
849
850   return NULL;
851 }
852
853 #define ID_OFFSET (2+SERIALNO_STR_LEN*2)
854 static void fill_serial_no_by_unique_id (void)
855 {
856   extern const uint8_t * unique_device_id (void);
857   uint8_t *p = &neug_string_serial[ID_OFFSET];
858   const uint8_t *u = unique_device_id () + 8;
859   int i;
860
861   for (i = 0; i < 4; i++)
862     {
863       uint8_t b = u[3-i];
864       uint8_t nibble;
865
866       nibble = (b >> 4);
867       nibble += (nibble >= 10 ? ('A' - 10) : '0');
868       p[i*4] = nibble;
869       p[i*4+1] = 0;
870       nibble = (b & 0x0f);
871       nibble += (nibble >= 10 ? ('A' - 10) : '0');
872       p[i*4+2] = nibble;
873       p[i*4+3] = 0;
874     }
875 }
876
877
878 static void
879 usb_tx_done (uint8_t ep_num, uint16_t len)
880 {
881   if (ep_num == ENDP1)
882     {
883       chopstx_mutex_lock (&usb_mtx);
884       chopstx_cond_signal (&usb_cnd);
885       chopstx_mutex_unlock (&usb_mtx);
886     }
887   else if (ep_num == ENDP2)
888     {
889       /* INTERRUPT Transfer done */
890     }
891 #ifdef FRAUCHEKY_SUPPORT
892   else if (ep_num == ENDP6)
893     EP6_IN_Callback (len);
894 #else
895   (void)len;
896 #endif
897 }
898
899 #ifdef GNU_LINUX_EMULATION
900 static uint8_t endp3_buf[64];
901 #endif
902
903 static void
904 usb_rx_ready (uint8_t ep_num, uint16_t len)
905 {
906   if (ep_num == ENDP3)
907 #ifdef GNU_LINUX_EMULATION
908     usb_lld_rx_enable_buf (ENDP3, endp3_buf, 64);
909 #else
910     usb_lld_rx_enable (ENDP3);
911 #endif
912 #ifdef FRAUCHEKY_SUPPORT
913   else if (ep_num == ENDP6)
914     EP6_OUT_Callback (len);
915 #else
916   (void)len;
917 #endif
918 }
919 \f
920 typedef uint32_t eventmask_t;
921 #define ALL_EVENTS (~0)
922
923 struct event_flag {
924   chopstx_mutex_t mutex;
925   chopstx_cond_t cond;
926   eventmask_t flag;
927 };
928
929 static void event_flag_init (struct event_flag *ev)
930 {
931   ev->flag = 0;
932   chopstx_mutex_init (&ev->mutex);
933   chopstx_cond_init (&ev->cond);
934 }
935
936
937 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
938 {
939   int n;
940
941   chopstx_mutex_lock (&ev->mutex);
942   while (!(ev->flag & m))
943     chopstx_cond_wait (&ev->cond, &ev->mutex);
944
945   n = __builtin_ffs ((ev->flag & m));
946   ev->flag &= ~(1 << (n - 1));
947   chopstx_mutex_unlock (&ev->mutex);
948
949   return (1 << (n - 1));
950 }
951
952 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
953 {
954   chopstx_mutex_lock (&ev->mutex);
955   ev->flag |= m;
956   chopstx_cond_signal (&ev->cond);
957   chopstx_mutex_unlock (&ev->mutex);
958 }
959
960 #ifdef GNU_LINUX_EMULATION
961 static char __process1_stack_base__[4096];
962 static char __process3_stack_base__[4096];
963 #define STACK_SIZE_LED (sizeof __process1_stack_base__)
964 #define STACK_SIZE_USB (sizeof __process3_stack_base__)
965 #else
966 extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
967 extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
968 #define STACK_SIZE_LED ((uintptr_t)__process1_stack_size__)
969 #define STACK_SIZE_USB ((uintptr_t)__process3_stack_size__)
970 #endif
971
972 #define STACK_ADDR_LED ((uintptr_t)__process1_stack_base__)
973 #define STACK_ADDR_USB ((uintptr_t)__process3_stack_base__)
974
975
976 #define PRIO_LED 3
977 static struct event_flag led_event;
978
979 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
980 #define LED_TWOSHOTS            ((eventmask_t)2)
981 #define LED_ONESHOT_LONG        ((eventmask_t)4)
982
983 /*
984  * LED blinker: When notified, let LED emit for 100ms.
985  */
986 static void *
987 led_blinker (void *arg)
988 {
989   (void)arg;
990
991   set_led (0);
992
993   while (1)
994     {
995       eventmask_t m;
996
997       m = event_flag_waitone (&led_event, ALL_EVENTS);
998
999       set_led (1);
1000       if (m == LED_ONESHOT_SHORT)
1001         chopstx_usec_wait (100*1000);
1002       else if (m == LED_TWOSHOTS)
1003         {
1004           chopstx_usec_wait (50*1000);
1005           set_led (0);
1006           chopstx_usec_wait (50*1000);
1007           set_led (1);
1008           chopstx_usec_wait (50*1000);
1009         }
1010       else
1011         chopstx_usec_wait (250*1000);
1012       set_led (0);
1013     }
1014
1015   return NULL;
1016 }
1017 \f
1018 #define RANDOM_BYTES_LENGTH 64
1019 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
1020
1021 #ifdef GNU_LINUX_EMULATION
1022 static uint8_t endp1_buf[RANDOM_BYTES_LENGTH];
1023 #endif
1024
1025 static void copy_to_tx (uint32_t v, int i)
1026 {
1027 #ifdef GNU_LINUX_EMULATION
1028   memcpy (&endp1_buf[i], &v, 4);
1029 #else
1030   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
1031 #endif
1032 }
1033
1034 #ifndef GNU_LINUX_EMULATION
1035 /*
1036  * In Gnuk 1.0.[12], reGNUal was not relocatable.
1037  * Now, it's relocatable, but we need to calculate its entry address
1038  * based on it's pre-defined address.
1039  */
1040 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
1041 static uint32_t
1042 calculate_regnual_entry_address (const uint8_t *addr)
1043 {
1044   const uint8_t *p = addr + 4;
1045   uintptr_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
1046
1047   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
1048   v += (uintptr_t)addr;
1049   return v;
1050 }
1051 #endif
1052
1053
1054 static int
1055 check_usb_status (void *arg)
1056 {
1057   (void)arg;
1058
1059   return (connected || bDeviceState != CONFIGURED
1060           || fsij_device_state != FSIJ_DEVICE_RUNNING);
1061 }
1062
1063
1064 #ifdef GNU_LINUX_EMULATION
1065 #include <stdlib.h>
1066
1067 #define main emulated_main
1068 #endif
1069
1070 /*
1071  * Entry point.
1072  *
1073  * NOTE: the main function is already a thread in the system on entry.
1074  */
1075 int
1076 main (int argc, char **argv)
1077 {
1078 #ifndef GNU_LINUX_EMULATION
1079   uintptr_t entry;
1080 #endif
1081   chopstx_t led_thread, usb_thd;
1082   unsigned int count;
1083
1084   (void)argc;
1085   (void)argv;
1086
1087   fill_serial_no_by_unique_id ();
1088
1089   adc_init ();
1090
1091   event_flag_init (&led_event);
1092
1093   chopstx_mutex_init (&usb_mtx);
1094   chopstx_cond_init (&usb_cnd);
1095
1096 #ifdef FRAUCHEKY_SUPPORT
1097   if (fraucheky_enabled ())
1098     {
1099     go_fraucheky:
1100       bDeviceState = UNCONNECTED;
1101       running_neug = 0;
1102       usb_thd = chopstx_create (PRIO_USB, STACK_ADDR_USB, STACK_SIZE_USB,
1103                                 usb_main, NULL);
1104       while (bDeviceState != CONFIGURED)
1105         chopstx_usec_wait (250*1000);
1106       set_led (1);
1107       fraucheky_main ();
1108       chopstx_cancel (usb_thd);
1109       chopstx_join (usb_thd, NULL);
1110       usb_lld_shutdown ();
1111       bDeviceState = UNCONNECTED;
1112     }
1113
1114   running_neug = 1;
1115 #endif
1116
1117   led_thread = chopstx_create (PRIO_LED, STACK_ADDR_LED, STACK_SIZE_LED,
1118                                led_blinker, NULL);
1119
1120   usb_thd = chopstx_create (PRIO_USB, STACK_ADDR_USB, STACK_SIZE_USB,
1121                             usb_main, NULL);
1122
1123   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
1124
1125   chopstx_mutex_lock (&usb_mtx);
1126
1127  not_configured:
1128   count = 0;
1129   /* Initial run-up */
1130   while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
1131     {
1132       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
1133         break;
1134
1135       chopstx_mutex_unlock (&usb_mtx);
1136       neug_wait_full ();
1137       neug_flush ();
1138
1139       if ((count & 0x0007) == 0)
1140         event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1141       chopstx_usec_wait (25*1000);
1142       count++;
1143       chopstx_mutex_lock (&usb_mtx);
1144     }
1145
1146   /* Holding USB_MTX...  */
1147   while (1)
1148     {
1149       int last_was_fullsizepacket = 0;
1150
1151       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
1152         break;
1153
1154       chopstx_mutex_unlock (&usb_mtx);
1155       while (1)
1156         {
1157           uint32_t usec = 5000*1000;
1158           chopstx_poll_cond_t poll_desc;
1159           struct chx_poll_head *pd_array[1] = {
1160             (struct chx_poll_head *)&poll_desc
1161           };
1162
1163           poll_desc.type = CHOPSTX_POLL_COND;
1164           poll_desc.ready = 0;
1165           poll_desc.cond = &usb_cnd;
1166           poll_desc.mutex = &usb_mtx;
1167           poll_desc.check = check_usb_status;
1168           poll_desc.arg = NULL;
1169
1170           if (chopstx_poll (&usec, 1, pd_array))
1171             break;
1172
1173           /* Timeout */
1174           neug_flush ();
1175           neug_mode_select (line_coding.paritytype);
1176           event_flag_signal (&led_event, LED_TWOSHOTS);
1177         }
1178
1179       chopstx_mutex_lock (&usb_mtx);
1180       if (bDeviceState != CONFIGURED)
1181         goto not_configured;
1182
1183       /* The connection opened.  */
1184       count = 0;
1185
1186       while (1)
1187         {
1188           int i;
1189
1190           chopstx_mutex_unlock (&usb_mtx);
1191           /*
1192            * No parity is standard.  It means providing conditioned output.
1193            * When parity enabled, it means to provide raw output
1194            * (CRC32 filtered when odd, direct sample of ADC when even).
1195            *
1196            * line_coding.paritytype:
1197            *   0: None, 1: Odd, 2: Even
1198            */
1199           neug_mode_select (line_coding.paritytype);
1200
1201           if ((count & 0x03ff) == 0)
1202             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
1203
1204           i = neug_consume_random (copy_to_tx);
1205
1206           if (i == 0 && !last_was_fullsizepacket)
1207             {    /* Only send ZLP when the last packet was fullsize.  */
1208               neug_wait_full ();
1209
1210               chopstx_mutex_lock (&usb_mtx);
1211               if (bDeviceState != CONFIGURED || !connected
1212                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1213                 break;
1214             }
1215           else
1216             {
1217               if (i == 64/4)
1218                 last_was_fullsizepacket = 1;
1219               else
1220                 last_was_fullsizepacket = 0;
1221
1222               chopstx_mutex_lock (&usb_mtx);
1223               if (bDeviceState != CONFIGURED || !connected
1224                   || fsij_device_state != FSIJ_DEVICE_RUNNING)
1225                 break;
1226
1227               /* Prepare sending random data.  */
1228 #ifdef GNU_LINUX_EMULATION
1229               usb_lld_tx_enable_buf (ENDP1, endp1_buf, i * 4);
1230 #else
1231               usb_lld_tx_enable (ENDP1, i * 4);
1232 #endif
1233               chopstx_cond_wait (&usb_cnd, &usb_mtx);
1234               count++;
1235             }
1236         }
1237     }
1238
1239   chopstx_mutex_unlock (&usb_mtx);
1240
1241   chopstx_cancel (led_thread);
1242   chopstx_join (led_thread, NULL);
1243
1244   /*
1245    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED
1246    * or FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED.
1247    */
1248   neug_fini ();
1249
1250   chopstx_mutex_lock (&usb_mtx);
1251 #ifdef FRAUCHEKY_SUPPORT
1252   if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
1253     {
1254       while (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
1255         {
1256           chopstx_mutex_unlock (&usb_mtx);
1257           set_led (1);
1258           chopstx_usec_wait (500*1000);
1259           set_led (0);
1260           chopstx_usec_wait (500*1000);
1261           chopstx_mutex_lock (&usb_mtx);
1262         }
1263
1264       usb_lld_prepare_shutdown ();
1265       chopstx_mutex_unlock (&usb_mtx);
1266       chopstx_cancel (usb_thd);
1267       chopstx_join (usb_thd, NULL);
1268       usb_lld_shutdown ();
1269       goto go_fraucheky;
1270     }
1271 #endif
1272
1273   fsij_device_state = FSIJ_DEVICE_EXITED;
1274
1275   while (fsij_device_state == FSIJ_DEVICE_EXITED)
1276     {
1277       chopstx_mutex_unlock (&usb_mtx);
1278       chopstx_usec_wait (500*1000);
1279       chopstx_mutex_lock (&usb_mtx);
1280     }
1281   chopstx_mutex_unlock (&usb_mtx);
1282
1283   flash_unlock ();              /* Flash unlock should be done here */
1284   set_led (1);
1285   usb_lld_shutdown ();
1286
1287   /* Finish application.  */
1288   chopstx_cancel (usb_thd);
1289   chopstx_join (usb_thd, NULL);
1290
1291 #ifdef GNU_LINUX_EMULATION
1292   exit (0);
1293 #else
1294   /* Set vector */
1295   SCB->VTOR = (uintptr_t)&_regnual_start;
1296   entry = calculate_regnual_entry_address (&_regnual_start);
1297 #ifdef DFU_SUPPORT
1298 #define FLASH_SYS_START_ADDR 0x08000000
1299 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
1300 #define CHIP_ID_REG ((uint32_t *)0xE0042000)
1301   {
1302     extern uint8_t _sys;
1303     uint32_t addr;
1304     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
1305     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
1306     uint32_t flash_page_size = 1024; /* 1KiB default */
1307
1308    if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device.  */
1309      flash_page_size += 0x0400; /* It's 2KiB. */
1310
1311     /* Kill DFU */
1312     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
1313          addr += flash_page_size)
1314       flash_erase_page (addr);
1315
1316     /* copy system service routines */
1317     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
1318
1319     /* Leave NeuG to exec reGNUal */
1320     (*func) ((void (*)(void))entry);
1321     for (;;);
1322   }
1323 #else
1324   /* Leave NeuG to exec reGNUal */
1325   flash_erase_all_and_exec ((void (*)(void))entry);
1326 #endif
1327 #endif
1328
1329   /* Never reached */
1330   return 0;
1331 }