Update main.c for GNU/Linux emulation.
[gnuk/neug.git] / src / main.c
index a1d6e67..f8a1e8d 100644 (file)
@@ -2,7 +2,7 @@
  * main.c - main routine of neug
  *
  * Main routine:
  * main.c - main routine of neug
  *
  * Main routine:
- * Copyright (C) 2011, 2012, 2013, 2015, 2016
+ * Copyright (C) 2011, 2012, 2013, 2015, 2016, 2017
  *              Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  *              Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
@@ -33,7 +33,9 @@
 #include "neug.h"
 #include "usb_lld.h"
 #include "sys.h"
 #include "neug.h"
 #include "usb_lld.h"
 #include "sys.h"
+#ifndef GNU_LINUX_EMULATION
 #include "mcu/stm32f103.h"
 #include "mcu/stm32f103.h"
+#endif
 #include "adc.h"
 
 enum {
 #include "adc.h"
 
 enum {
@@ -182,8 +184,10 @@ static const uint8_t vcom_string0[4] = {
 
 #include "usb-strings.c.inc"
 
 
 #include "usb-strings.c.inc"
 
-static void neug_setup_endpoints_for_interface (uint16_t interface, int stop);
+static void neug_setup_endpoints_for_interface (struct usb_dev *dev,
+                                               uint16_t interface, int stop);
 #ifdef FRAUCHEKY_SUPPORT
 #ifdef FRAUCHEKY_SUPPORT
+#define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
 extern int fraucheky_enabled (void);
 extern void fraucheky_main (void);
 
 extern int fraucheky_enabled (void);
 extern void fraucheky_main (void);
 
@@ -202,11 +206,15 @@ usb_device_reset (struct usb_dev *dev)
   usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
 
   /* Initialize Endpoint 0.  */
   usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
 
   /* Initialize Endpoint 0.  */
+#ifdef GNU_LINUX_EMULATION
+  usb_lld_setup_endp (dev, ENDP0, 1, 1);
+#else
   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
+#endif
 
   /* Stop the interface */
   for (i = 0; i < NUM_INTERFACES; i++)
 
   /* Stop the interface */
   for (i = 0; i < NUM_INTERFACES; i++)
-    neug_setup_endpoints_for_interface (i, 1);
+    neug_setup_endpoints_for_interface (dev, i, 1);
 
   /* Notify upper layer.  */
   chopstx_mutex_lock (&usb_mtx);
 
   /* Notify upper layer.  */
   chopstx_mutex_lock (&usb_mtx);
@@ -216,9 +224,11 @@ usb_device_reset (struct usb_dev *dev)
   chopstx_mutex_unlock (&usb_mtx);
 }
 
   chopstx_mutex_unlock (&usb_mtx);
 }
 
+#ifndef GNU_LINUX_EMULATION
 extern uint8_t _regnual_start, __heap_end__;
 
 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
 extern uint8_t _regnual_start, __heap_end__;
 
 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
+#endif
 
 /* USB vendor requests to control pipe */
 #define USB_FSIJ_MEMINFO         0
 
 /* USB vendor requests to control pipe */
 #define USB_FSIJ_MEMINFO         0
@@ -228,6 +238,9 @@ static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
 #define USB_NEUG_GET_INFO      254
 #define USB_NEUG_EXIT          255 /* Ask to exit and to receive reGNUal */
 
 #define USB_NEUG_GET_INFO      254
 #define USB_NEUG_EXIT          255 /* Ask to exit and to receive reGNUal */
 
+#define DEFAULT_PASSWD "12345678"
+#define DEFAULT_PASSWD_LEN 8
+
 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
   0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
   0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -236,27 +249,18 @@ uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
 };
 static uint8_t usbbuf[64];
 
 };
 static uint8_t usbbuf[64];
 
-#define DEFAULT_PASSWD "12345678"
-#define DEFAULT_PASSWD_LEN 8
-
+#ifndef GNU_LINUX_EMULATION
 static void set_passwd (void)
 {
   flash_unlock ();
   if (neug_passwd[0] != 0xff)
 static void set_passwd (void)
 {
   flash_unlock ();
   if (neug_passwd[0] != 0xff)
-    flash_erase_page ((uint32_t)neug_passwd);
+    flash_erase_page ((uintptr_t)neug_passwd);
   if (usbbuf[0] == DEFAULT_PASSWD_LEN
       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
     return;
   if (usbbuf[0] == DEFAULT_PASSWD_LEN
       && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
     return;
-  flash_write ((uint32_t)neug_passwd, usbbuf, usbbuf[0] + 1);
+  flash_write ((uintptr_t)neug_passwd, usbbuf, usbbuf[0] + 1);
 }
 
 }
 
-static uint32_t rbit (uint32_t v)
-{
-  uint32_t r;
-
-  asm ("rbit   %0, %1" : "=r" (r) : "r" (v));
-  return r;
-}
 
 /* After calling this function, CRC module remain enabled.  */
 static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
 
 /* After calling this function, CRC module remain enabled.  */
 static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
@@ -264,17 +268,17 @@ static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
   uint32_t crc32 = *end_p;
   const uint32_t *p;
 
   uint32_t crc32 = *end_p;
   const uint32_t *p;
 
-  RCC->AHBENR |= RCC_AHBENR_CRCEN;
-  CRC->CR = CRC_CR_RESET;
+  crc32_rv_reset ();
 
   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
 
   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
-    CRC->DR = rbit (*p);
+    crc32_rv_step (rbit (*p));
 
 
-  if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
+  if ((rbit (crc32_rv_get ()) ^ crc32) == 0xffffffff)
     return usb_lld_ctrl_ack (dev);
 
   return -1;
 }
     return usb_lld_ctrl_ack (dev);
 
   return -1;
 }
+#endif
 
 
 #define NEUG_SPECIAL_BITRATE 110
 
 
 #define NEUG_SPECIAL_BITRATE 110
@@ -315,14 +319,19 @@ usb_ctrl_write_finish (struct usb_dev *dev)
            }
          chopstx_mutex_unlock (&usb_mtx);
        }
            }
          chopstx_mutex_unlock (&usb_mtx);
        }
+#ifndef GNU_LINUX_EMULATION
       else if (arg->request == USB_NEUG_SET_PASSWD)
        set_passwd ();
       else if (arg->request == USB_NEUG_SET_PASSWD)
        set_passwd ();
+#endif
       else if (arg->request == USB_NEUG_EXIT)
        {
          if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
               && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
       else if (arg->request == USB_NEUG_EXIT)
        {
          if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
               && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
+#ifndef GNU_LINUX_EMULATION
              || (neug_passwd[0] == usbbuf[0]
              || (neug_passwd[0] == usbbuf[0]
-                 && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0])))
+                 && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0]))
+#endif
+             )
            {
              chopstx_mutex_lock (&usb_mtx);
              fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
            {
              chopstx_mutex_lock (&usb_mtx);
              fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
@@ -343,7 +352,7 @@ usb_ctrl_write_finish (struct usb_dev *dev)
          chopstx_mutex_unlock (&usb_mtx);
        }
 #ifdef FRAUCHEKY_SUPPORT
          chopstx_mutex_unlock (&usb_mtx);
        }
 #ifdef FRAUCHEKY_SUPPORT
-      else if (arg->request == USB_CDC_REQ_SET_LINE_CODING)
+      else if (running_neug && arg->request == USB_CDC_REQ_SET_LINE_CODING)
        {
          chopstx_mutex_lock (&usb_mtx);
          if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
        {
          chopstx_mutex_lock (&usb_mtx);
          if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
@@ -355,6 +364,8 @@ usb_ctrl_write_finish (struct usb_dev *dev)
            fsij_device_state = FSIJ_DEVICE_RUNNING;
          chopstx_mutex_unlock (&usb_mtx);
        }
            fsij_device_state = FSIJ_DEVICE_RUNNING;
          chopstx_mutex_unlock (&usb_mtx);
        }
+      else if (!running_neug && arg->request == MSC_MASS_STORAGE_RESET_COMMAND)
+       fraucheky_setup_endpoints_for_interface (0);
 #endif
     }
 }
 #endif
     }
 }
@@ -394,6 +405,9 @@ usb_setup (struct usb_dev *dev)
        {
          if (arg->request == USB_FSIJ_MEMINFO)
            {
        {
          if (arg->request == USB_FSIJ_MEMINFO)
            {
+#ifdef GNU_LINUX_EMULATION
+             return -1;
+#else
              chopstx_mutex_lock (&usb_mtx);
              if (fsij_device_state != FSIJ_DEVICE_EXITED)
                {
              chopstx_mutex_lock (&usb_mtx);
              if (fsij_device_state != FSIJ_DEVICE_EXITED)
                {
@@ -402,6 +416,7 @@ usb_setup (struct usb_dev *dev)
                }
              chopstx_mutex_unlock (&usb_mtx);
              return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
                }
              chopstx_mutex_unlock (&usb_mtx);
              return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
+#endif
            }
          else if (arg->request == USB_NEUG_GET_INFO)
            {
            }
          else if (arg->request == USB_NEUG_GET_INFO)
            {
@@ -427,10 +442,13 @@ usb_setup (struct usb_dev *dev)
        }
       else /* SETUP_SET */
        {
        }
       else /* SETUP_SET */
        {
-         uint8_t *addr = (uint8_t *)(0x20000000 + arg->value * 0x100 + arg->index);
+         uint8_t *addr = (uint8_t *)(0x20000000UL + arg->value * 0x100 + arg->index);
 
          if (arg->request == USB_FSIJ_DOWNLOAD)
            {
 
          if (arg->request == USB_FSIJ_DOWNLOAD)
            {
+#ifdef GNU_LINUX_EMULATION
+             return -1;
+#else
              chopstx_mutex_lock (&usb_mtx);
              if (fsij_device_state != FSIJ_DEVICE_EXITED)
                {
              chopstx_mutex_lock (&usb_mtx);
              if (fsij_device_state != FSIJ_DEVICE_EXITED)
                {
@@ -446,9 +464,13 @@ usb_setup (struct usb_dev *dev)
                memset (addr + arg->index + arg->len, 0, 256 - (arg->index + arg->len));
 
              return usb_lld_ctrl_recv (dev, addr, arg->len);
                memset (addr + arg->index + arg->len, 0, 256 - (arg->index + arg->len));
 
              return usb_lld_ctrl_recv (dev, addr, arg->len);
+#endif
            }
          else if (arg->request == USB_FSIJ_EXEC && arg->len == 0)
            {
            }
          else if (arg->request == USB_FSIJ_EXEC && arg->len == 0)
            {
+#ifdef GNU_LINUX_EMULATION
+             return -1;
+#else
              chopstx_mutex_lock (&usb_mtx);
              if (fsij_device_state != FSIJ_DEVICE_EXITED)
                {
              chopstx_mutex_lock (&usb_mtx);
              if (fsij_device_state != FSIJ_DEVICE_EXITED)
                {
@@ -457,10 +479,11 @@ usb_setup (struct usb_dev *dev)
                }
              chopstx_mutex_unlock (&usb_mtx);
 
                }
              chopstx_mutex_unlock (&usb_mtx);
 
-             if (((uint32_t)addr & 0x03))
+             if (((uintptr_t)addr & 0x03))
                return -1;
 
              return download_check_crc32 (dev, (uint32_t *)addr);
                return -1;
 
              return download_check_crc32 (dev, (uint32_t *)addr);
+#endif
            }
          else if (arg->request == USB_NEUG_SET_PASSWD && arg->len <= 32)
            {
            }
          else if (arg->request == USB_NEUG_SET_PASSWD && arg->len <= 32)
            {
@@ -585,15 +608,24 @@ usb_get_descriptor (struct usb_dev *dev)
 }
 
 static void
 }
 
 static void
-neug_setup_endpoints_for_interface (uint16_t interface, int stop)
+neug_setup_endpoints_for_interface (struct usb_dev *dev,
+                                   uint16_t interface, int stop)
 {
 {
+#if !defined(GNU_LINUX_EMULATION)
+  (void)dev;
+#endif
+  
   if (interface == 0)
     {
 #ifdef FRAUCHEKY_SUPPORT
       if (running_neug)
        {
          if (!stop)
   if (interface == 0)
     {
 #ifdef FRAUCHEKY_SUPPORT
       if (running_neug)
        {
          if (!stop)
+#ifdef GNU_LINUX_EMULATION
+           usb_lld_setup_endp (dev, ENDP2, 0, 1);
+#else
            usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
            usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
+#endif
          else
            usb_lld_stall_tx (ENDP2);
        }
          else
            usb_lld_stall_tx (ENDP2);
        }
@@ -601,7 +633,11 @@ neug_setup_endpoints_for_interface (uint16_t interface, int stop)
        fraucheky_setup_endpoints_for_interface (stop);
 #else
       if (!stop)
        fraucheky_setup_endpoints_for_interface (stop);
 #else
       if (!stop)
+#ifdef GNU_LINUX_EMULATION
+       usb_lld_setup_endp (dev, ENDP2, 0, 1);
+#else
        usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
        usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
+#endif
       else
        usb_lld_stall_tx (ENDP2);
 #endif
       else
        usb_lld_stall_tx (ENDP2);
 #endif
@@ -610,8 +646,13 @@ neug_setup_endpoints_for_interface (uint16_t interface, int stop)
     {
       if (!stop)
        {
     {
       if (!stop)
        {
+#ifdef GNU_LINUX_EMULATION
+         usb_lld_setup_endp (dev, ENDP1, 0, 1);
+         usb_lld_setup_endp (dev, ENDP3, 1, 0);
+#else
          usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
          usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
          usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
          usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
+#endif
          /* Start with no data receiving (ENDP3 not enabled) */
        }
       else
          /* Start with no data receiving (ENDP3 not enabled) */
        }
       else
@@ -636,7 +677,7 @@ usb_set_configuration (struct usb_dev *dev)
 
       usb_lld_set_configuration (dev, 1);
       for (i = 0; i < NUM_INTERFACES; i++)
 
       usb_lld_set_configuration (dev, 1);
       for (i = 0; i < NUM_INTERFACES; i++)
-       neug_setup_endpoints_for_interface (i, 0);
+       neug_setup_endpoints_for_interface (dev, i, 0);
       chopstx_mutex_lock (&usb_mtx);
       bDeviceState = CONFIGURED;
       chopstx_mutex_unlock (&usb_mtx);
       chopstx_mutex_lock (&usb_mtx);
       bDeviceState = CONFIGURED;
       chopstx_mutex_unlock (&usb_mtx);
@@ -648,7 +689,7 @@ usb_set_configuration (struct usb_dev *dev)
 
       usb_lld_set_configuration (dev, 0);
       for (i = 0; i < NUM_INTERFACES; i++)
 
       usb_lld_set_configuration (dev, 0);
       for (i = 0; i < NUM_INTERFACES; i++)
-       neug_setup_endpoints_for_interface (i, 1);
+       neug_setup_endpoints_for_interface (dev, i, 1);
       chopstx_mutex_lock (&usb_mtx);
       bDeviceState = ADDRESSED;
       chopstx_cond_signal (&usb_cnd);
       chopstx_mutex_lock (&usb_mtx);
       bDeviceState = ADDRESSED;
       chopstx_cond_signal (&usb_cnd);
@@ -656,8 +697,7 @@ usb_set_configuration (struct usb_dev *dev)
     }
 
   /* Do nothing when current_conf == value */
     }
 
   /* Do nothing when current_conf == value */
-  usb_lld_ctrl_ack (dev);
-  return 0;
+  return usb_lld_ctrl_ack (dev);
 }
 
 
 }
 
 
@@ -674,9 +714,8 @@ usb_set_interface (struct usb_dev *dev)
     return -1;
   else
     {
     return -1;
   else
     {
-      neug_setup_endpoints_for_interface (interface, 0);
-      usb_lld_ctrl_ack (dev);
-      return 0;
+      neug_setup_endpoints_for_interface (dev, interface, 0);
+      return usb_lld_ctrl_ack (dev);
     }
 }
 
     }
 }
 
@@ -726,7 +765,7 @@ usb_main (void *arg)
 
   while (1)
     {
 
   while (1)
     {
-      chopstx_poll (NULL, 1, &interrupt);
+      chopstx_intr_wait (&interrupt);
 
       if (interrupt.ready)
        {
 
       if (interrupt.ready)
        {
@@ -839,8 +878,6 @@ static void fill_serial_no_by_unique_id (void)
 static void
 usb_tx_done (uint8_t ep_num, uint16_t len)
 {
 static void
 usb_tx_done (uint8_t ep_num, uint16_t len)
 {
-  (void)len;
-
   if (ep_num == ENDP1)
     {
       chopstx_mutex_lock (&usb_mtx);
   if (ep_num == ENDP1)
     {
       chopstx_mutex_lock (&usb_mtx);
@@ -854,17 +891,29 @@ usb_tx_done (uint8_t ep_num, uint16_t len)
 #ifdef FRAUCHEKY_SUPPORT
   else if (ep_num == ENDP6)
     EP6_IN_Callback (len);
 #ifdef FRAUCHEKY_SUPPORT
   else if (ep_num == ENDP6)
     EP6_IN_Callback (len);
+#else
+  (void)len;
 #endif
 }
 
 #endif
 }
 
+#ifdef GNU_LINUX_EMULATION
+static uint8_t endp3_buf[64];
+#endif
+
 static void
 usb_rx_ready (uint8_t ep_num, uint16_t len)
 {
   if (ep_num == ENDP3)
 static void
 usb_rx_ready (uint8_t ep_num, uint16_t len)
 {
   if (ep_num == ENDP3)
+#ifdef GNU_LINUX_EMULATION
+    usb_lld_rx_enable_buf (ENDP3, endp3_buf, 64);
+#else
     usb_lld_rx_enable (ENDP3);
     usb_lld_rx_enable (ENDP3);
+#endif
 #ifdef FRAUCHEKY_SUPPORT
   else if (ep_num == ENDP6)
     EP6_OUT_Callback (len);
 #ifdef FRAUCHEKY_SUPPORT
   else if (ep_num == ENDP6)
     EP6_OUT_Callback (len);
+#else
+  (void)len;
 #endif
 }
 \f
 #endif
 }
 \f
@@ -908,13 +957,20 @@ static void event_flag_signal (struct event_flag *ev, eventmask_t m)
   chopstx_mutex_unlock (&ev->mutex);
 }
 
   chopstx_mutex_unlock (&ev->mutex);
 }
 
-extern uint8_t __process1_stack_base__, __process1_stack_size__;
-extern uint8_t __process3_stack_base__, __process3_stack_size__;
+#ifdef GNU_LINUX_EMULATION
+static char __process1_stack_base__[4096];
+static char __process3_stack_base__[4096];
+#define STACK_SIZE_LED (sizeof __process1_stack_base__)
+#define STACK_SIZE_USB (sizeof __process3_stack_base__)
+#else
+extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
+extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
+#define STACK_SIZE_LED ((uintptr_t)__process1_stack_size__)
+#define STACK_SIZE_USB ((uintptr_t)__process3_stack_size__)
+#endif
 
 
-const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
-const size_t __stacksize_led = (size_t)&__process1_stack_size__;
-const uint32_t __stackaddr_usb = (uint32_t)&__process3_stack_base__;
-const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
+#define STACK_ADDR_LED ((uintptr_t)__process1_stack_base__)
+#define STACK_ADDR_USB ((uintptr_t)__process3_stack_base__)
 
 
 #define PRIO_LED 3
 
 
 #define PRIO_LED 3
@@ -962,11 +1018,20 @@ led_blinker (void *arg)
 #define RANDOM_BYTES_LENGTH 64
 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
 
 #define RANDOM_BYTES_LENGTH 64
 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
 
+#ifdef GNU_LINUX_EMULATION
+static uint8_t endp1_buf[RANDOM_BYTES_LENGTH];
+#endif
+
 static void copy_to_tx (uint32_t v, int i)
 {
 static void copy_to_tx (uint32_t v, int i)
 {
+#ifdef GNU_LINUX_EMULATION
+  memcpy (&endp1_buf[i], &v, 4);
+#else
   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
+#endif
 }
 
 }
 
+#ifndef GNU_LINUX_EMULATION
 /*
  * In Gnuk 1.0.[12], reGNUal was not relocatable.
  * Now, it's relocatable, but we need to calculate its entry address
 /*
  * In Gnuk 1.0.[12], reGNUal was not relocatable.
  * Now, it's relocatable, but we need to calculate its entry address
@@ -977,12 +1042,13 @@ static uint32_t
 calculate_regnual_entry_address (const uint8_t *addr)
 {
   const uint8_t *p = addr + 4;
 calculate_regnual_entry_address (const uint8_t *addr)
 {
   const uint8_t *p = addr + 4;
-  uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
+  uintptr_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
 
   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
 
   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
-  v += (uint32_t)addr;
+  v += (uintptr_t)addr;
   return v;
 }
   return v;
 }
+#endif
 
 
 static int
 
 
 static int
@@ -994,6 +1060,13 @@ check_usb_status (void *arg)
          || fsij_device_state != FSIJ_DEVICE_RUNNING);
 }
 
          || fsij_device_state != FSIJ_DEVICE_RUNNING);
 }
 
+
+#ifdef GNU_LINUX_EMULATION
+#include <stdlib.h>
+
+#define main emulated_main
+#endif
+
 /*
  * Entry point.
  *
 /*
  * Entry point.
  *
@@ -1002,7 +1075,9 @@ check_usb_status (void *arg)
 int
 main (int argc, char **argv)
 {
 int
 main (int argc, char **argv)
 {
-  uint32_t entry;
+#ifndef GNU_LINUX_EMULATION
+  uintptr_t entry;
+#endif
   chopstx_t led_thread, usb_thd;
   unsigned int count;
 
   chopstx_t led_thread, usb_thd;
   unsigned int count;
 
@@ -1024,7 +1099,7 @@ main (int argc, char **argv)
     go_fraucheky:
       bDeviceState = UNCONNECTED;
       running_neug = 0;
     go_fraucheky:
       bDeviceState = UNCONNECTED;
       running_neug = 0;
-      usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
+      usb_thd = chopstx_create (PRIO_USB, STACK_ADDR_USB, STACK_SIZE_USB,
                                usb_main, NULL);
       while (bDeviceState != CONFIGURED)
        chopstx_usec_wait (250*1000);
                                usb_main, NULL);
       while (bDeviceState != CONFIGURED)
        chopstx_usec_wait (250*1000);
@@ -1039,10 +1114,10 @@ main (int argc, char **argv)
   running_neug = 1;
 #endif
 
   running_neug = 1;
 #endif
 
-  led_thread = chopstx_create (PRIO_LED, __stackaddr_led, __stacksize_led,
+  led_thread = chopstx_create (PRIO_LED, STACK_ADDR_LED, STACK_SIZE_LED,
                               led_blinker, NULL);
 
                               led_blinker, NULL);
 
-  usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
+  usb_thd = chopstx_create (PRIO_USB, STACK_ADDR_USB, STACK_SIZE_USB,
                            usb_main, NULL);
 
   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
                            usb_main, NULL);
 
   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
@@ -1079,8 +1154,11 @@ main (int argc, char **argv)
       chopstx_mutex_unlock (&usb_mtx);
       while (1)
        {
       chopstx_mutex_unlock (&usb_mtx);
       while (1)
        {
-         chopstx_poll_cond_t poll_desc;
          uint32_t usec = 5000*1000;
          uint32_t usec = 5000*1000;
+         chopstx_poll_cond_t poll_desc;
+         struct chx_poll_head *pd_array[1] = {
+           (struct chx_poll_head *)&poll_desc
+         };
 
          poll_desc.type = CHOPSTX_POLL_COND;
          poll_desc.ready = 0;
 
          poll_desc.type = CHOPSTX_POLL_COND;
          poll_desc.ready = 0;
@@ -1089,7 +1167,7 @@ main (int argc, char **argv)
          poll_desc.check = check_usb_status;
          poll_desc.arg = NULL;
 
          poll_desc.check = check_usb_status;
          poll_desc.arg = NULL;
 
-         if (chopstx_poll (&usec, 1, &poll_desc))
+         if (chopstx_poll (&usec, 1, pd_array))
            break;
 
          /* Timeout */
            break;
 
          /* Timeout */
@@ -1147,7 +1225,11 @@ main (int argc, char **argv)
                break;
 
              /* Prepare sending random data.  */
                break;
 
              /* Prepare sending random data.  */
+#ifdef GNU_LINUX_EMULATION
+             usb_lld_tx_enable_buf (ENDP1, endp1_buf, i * 4);
+#else
              usb_lld_tx_enable (ENDP1, i * 4);
              usb_lld_tx_enable (ENDP1, i * 4);
+#endif
              chopstx_cond_wait (&usb_cnd, &usb_mtx);
              count++;
            }
              chopstx_cond_wait (&usb_cnd, &usb_mtx);
              count++;
            }
@@ -1206,8 +1288,11 @@ main (int argc, char **argv)
   chopstx_cancel (usb_thd);
   chopstx_join (usb_thd, NULL);
 
   chopstx_cancel (usb_thd);
   chopstx_join (usb_thd, NULL);
 
+#ifdef GNU_LINUX_EMULATION
+  exit (0);
+#else
   /* Set vector */
   /* Set vector */
-  SCB->VTOR = (uint32_t)&_regnual_start;
+  SCB->VTOR = (uintptr_t)&_regnual_start;
   entry = calculate_regnual_entry_address (&_regnual_start);
 #ifdef DFU_SUPPORT
 #define FLASH_SYS_START_ADDR 0x08000000
   entry = calculate_regnual_entry_address (&_regnual_start);
 #ifdef DFU_SUPPORT
 #define FLASH_SYS_START_ADDR 0x08000000
@@ -1238,6 +1323,7 @@ main (int argc, char **argv)
 #else
   /* Leave NeuG to exec reGNUal */
   flash_erase_all_and_exec ((void (*)(void))entry);
 #else
   /* Leave NeuG to exec reGNUal */
   flash_erase_all_and_exec ((void (*)(void))entry);
+#endif
 #endif
 
   /* Never reached */
 #endif
 
   /* Never reached */